What you can do with it
A folder of notes
Markdown, text, HTML, and the text layer of a PDF become one crystal. The same name in two files is one node.
A small repository
Rust, TypeScript, JavaScript, Python, Go, Java, and C/C++ are read as text. Import edges are drawn when the target file is in the folder.
Retrieve across files
Three ranked lists — vector, lexical, and a walk along relates-to — fuse by rank. Reciprocal rank fusion, k = 60.
Ask your own model
One call, with the retrieved passages. A small OpenAI-compatible model is enough, cloud or local. Without an endpoint, the graph and retrieve still run.
How a folder becomes a crystal
- Pick a folder. Files, imports, and sibling links draw first. Ingest hangs the text chunks off each file.
- Names are extracted without a model. One normalized spelling is one node.
mentionsties it to the files.relates_tolinks two names that share a chunk. - A spelling fold is kept as a merge note. Names that embed as near-duplicates but do not share a spelling stay two nodes, flagged
conflicts_with. A flag is recoverable. A silent merge is not. - Click a node. The card shows type, files, neighbors by weight, the passages, betweenness next to degree, and the raw payload.
- Hub spread (LinLog), from 1 to 15, pushes connected nodes apart and widens the chunk ring around each file. Glow, from 0 to 1.5, scales the edge haze. Each folder remembers its own pair.
- Hop is one step. Blast is two. Both are buttons on the crystal. Ask does not send tools. It sends the passages from retrieve, once.
Limits
This is free, and it is for a folder of notes or a small repository. It is not for a massive codebase. The stop is in the app, not in Qdrant. Past the cap, ingest finishes and the log says what was cut.
- 400 chunks for the whole folder, 80 for one file, about 1 800 characters a chunk.
- 400 file nodes drawn. 10 000 files walked.
- One text file up to 2 MB. One PDF up to 32 MB, text layer only.
- Images are nodes, with no OCR. Office files are counted, not parsed.
node_modules,target,dist,.git, and hidden directories are skipped.
Concepts and the stack
- Tauri 2, Rust, a small Vite front end, three.js for the verse.
- Qdrant and nomic-embed-text v1.5 (768 dimensions) travel inside the app. llama.cpp serves the embedder. Ports are chosen free at launch.
- Reciprocal rank fusion, Cormack, Clarke, and Buettcher, 2009. Fusion reads rank, never the cosine and never the edge weight.
- The third list is the Zep / Graphiti pattern: walk
relates_toby weight, then fuse. This build does that rank fusion only, not the extra MMR or node-distance stages. - Hub spread is degree-scaled repulsion, the LinLog idea: a hub pushes harder than a leaf. Betweenness is shown on the card as a bridge score, and it is not used to delete nodes.
Who made it
Michal directed it, tested it, and decided what shipped. None of the application code was written by hand. The work was a sequence of AI seats, each given a job.
- Claude Code Opus 5, and Cursor Opus 5, set the initial design and the architecture, and wrote the assignments in hive chat that the build followed.
- Grok 4.6, in Cursor, cut the earlier versions of the crystal.
- Grok 4.7, in Cursor as Codemaster, built the app as it ships: the standalone engines, the entity graph, the detail card, hub spread, and this release.
The point of saying so is the method. A person can aim a build, keep the constraints, and ship, with the code coming from the seats and the judgment staying with the person.