How the graph gets built
Graft builds the graph in two passes, both powered by a language model:
- Read each file. Every source file is summarized once into a short description of what it does.
- Group into nodes. Those summaries are grouped into a curated set of nodes (subsystems, key files, and concepts) with typed links between them. Graft chooses the right level of detail for you instead of making one node per file, so a big repo becomes a few dozen readable nodes.
Every pass is cached by content hash — the LLM ones and the tree-sitter parse alike. Re-running only touches the files that changed, so the second build is fast and cheap (on this repo, 124 files: 0.74s cold, 0.18s after one edited file, 0.18s with nothing changed). graft build --no-reuse forces a cold re-parse.
That cheapness is what lets every query refresh the graph before it answers. A retrieval call stats the tree against the last build’s fingerprint (~3ms), and rebuilds only if something moved — so ask/grep/callers/skeleton/map describe the code as it is right now, including edits that are unsaved to git: uncommitted, unstaged, or staged all look the same to graft, which never reads git at all. The refresh is structural and $0; it never calls the LLM. Turn it off per-command with --no-refresh, or everywhere with GRAFT_NO_REFRESH=1.
Alongside the markdown graph, graft build builds graft/.graph/wiring.json — a per-symbol code graph — plus a per-file wiring card mirroring your source tree. Tier 1 is pure tree-sitter (every function, class, and call edge; deterministic, no model, no network), which is why plain graft build needs no key. The --deep pass adds a one-line summary and a crux excerpt per symbol, cached by body hash.