Real-time global intelligence dashboard. AI-powered news aggregation, geopolitical monitoring, and infrastructure tracking in a unified situational awareness interface
MCP server and code graph for coding agents
Graft builds a local markdown code graph from your repo, then wires that graph into agent workflows through Claude Code setup, hooks, and an MCP server. The graph is refreshed as code changes, so agents can trace symbols, find relevant files, and answer with current context instead of rediscovering the repo each time.
Videos about this repo
Builders who want Claude Code, Cursor, Codex, Gemini CLI, or other agents to work with codebase context that stays fresh.
You can give your agent repo-specific context up front, so it spends less time re-exploring files and more time making the change.
What it does
Local code graph
Builds a `graft/` folder of linked markdown nodes that describe systems, APIs, and concepts in the repo.
MCP tools
Provides tools like `graft_find_code`, `graft_file_api`, `graft_trace_calls`, `graft_find_all`, `graft_repo_map`, and `graft_check_freshness`.
Agent wiring
Writes instruction files and, for Claude Code, adds a status line, hooks, and live sync in `.claude/`.
Freshness checks
Rebuilds only what changed and can detect when the local graph has drifted from the working tree.
Multi-agent support
Wires into agent-specific files for Claude Code, Codex, Cursor, Gemini, Copilot, Windsurf, Grok, Kiro, and AdaL.
How to get it
- 1Run
npm install -g @nanonets/graft # install the CLI, once graft init # build the graph + wire it into Claude Code
- 2graft build adds graft/ to your .gitignore automatically — the graph is a local,…
git add .claude && git commit -m "wire in graft"
README
Turbocharge Claude Code, Cursor, Codex, Gemini & every coding agent: faster, cheaper, with contextual understanding specific to your codebase.
Up to 4× cheaper and 3× faster, with better or no loss of correctness.
| Metric | Cold Claude Code | Claude Code with graft |
|---|---|---|
| Tool-call reduction | Baseline | +46% |
| Token savings | Baseline | +42% |
| Time savings | Baseline | +60% |
| Correctness | 54% | 66% (+12 pts) |
This works beyond code too.
A living skill file that learns from every task and gets sharper the more your team works.
Contents
- Quick start
- The problem
- What Graft does
- Benchmark
- SWE-bench Verified
- How the graph gets built
- Supported languages
- What's in a node
- What runs where
- Agent integration — MCP server · Claude Code (deep integration)
- CLI
- Search & orient (
graft grep/graft map) - Monorepos & multi-repo folders
- Visualize it (
graft viz) - Tested on your popular repos
- Development
- License
Quick start
npm install -g @nanonets/graft # install the CLI, once
graft init # build the graph + wire it into Claude Code
That is the whole setup. graft init asks which of your coding agents to wire up, builds graft/ from your code, and drops a statusline and hooks into .claude/, so from the next session on Graft rides along in Claude Code: it pulls the matching nodes into each prompt and rebuilds the graph in the background after every turn. No daemon, no re-indexing to remember, nothing to run or maintain by default — the graph is just files.
Nothing is written until you pick. Run graft init --dry-run to see every file it would touch first, or graft init --agents claude to skip the prompt and wire Claude Code alone.
graft build adds graft/ to your .gitignore automatically — the graph is a local, regenerable cache (like node_modules), not something you commit. What you share is the wiring init dropped into .claude/; each teammate runs graft build to generate their own graph:
git add .claude && git commit -m "wire in graft"
Prefer not to install globally? npx @nanonets/graft init works the same way.
The problem
Every task, your coding agent starts blind. Before it changes anything, it re-explores the repo: grep a term, open a file, follow an import, back out, try again. It is rebuilding a picture of a codebase it mapped an hour ago and threw away. That rediscovery burns most of a run's tool calls, tokens, and latency, and it is pure overhead:
- Repeated. Every task pays the exploration cost again, from zero.
- Discarded. Whatever the agent figured out dies with the session.
- Unshared. The next teammate, and their agent, start from scratch too.
Humans onboard to a codebase once. Agents onboard every single time.
What Graft does
Graft builds that understanding once and writes it into your repo as a folder of linked markdown files, one node per system, API, or concept.
- Real explanations, not a list of symbols. Each node says, in plain English, what a part of the system does and how it connects to the rest, the way a senior engineer would explain it. That is the part an agent actually needs so it can skip the exploration. It is not a dump of function names.
- A real graph you can read. No embeddings, no similarity search, no index to keep warm. The graph is a set of linked files your agent opens, greps, and follows, exactly the way it reads any other file in the repo.
- A local cache, not a committed artifact.
graft buildwritesgraft/and adds it to.gitignore— it's a regenerable local cache, likenode_modules. What you commit is the small wiringgraft initdrops in (.claude/,AGENTS.md, the MCP config); each teammate runsgraft buildto generate their own graph. No database, no server, no setup. - Always fresh, automatically. Every query rebuilds the graph against the working tree first — structural,
$0, ~3ms when nothing moved — soask/grep/callers/skeleton/mapdescribe the code as it is right now, including uncommitted edits.graft checkis a local freshness signal; there's no stale index to babysit. - Your provider, your key, your model. Summaries are written by any provider you choose — OpenAI, Anthropic (native), OpenRouter, Fireworks, Groq, OrcaRouter, a LiteLLM proxy, or a local model — under your own key. The structural code graph (
graft build,graft check) is deterministic tree-sitter and never calls a model at all.

Benchmark
An agent that reads the graph should be cheaper and faster without getting more answers wrong. That's the whole claim, so we measured it instead of asserting it.
The harness ran three variants of the same Claude Sonnet 5 agent with the same file tools: cold (explores from zero), Graft (a graft ask --source bundle pushed up front), and pull (graft_find_code/graft_file_api tools, nothing injected — context paid for only when asked). An Opus 4.8 judge scored correctness with a required-keyword floor, so a fast-but-wrong answer couldn't win by being fast. Cost is cache-aware: reads ≈0.1×, writes 1.25×, the billing model agents actually run under.
162 runs, two repos (graft itself and a real Node/Express auth service), 3 trials each, tasks split between single-file and multi-file questions.
| Metric (mean/task) | Cold Claude Code | Claude Code with graft |
|---|---|---|
| Cost savings ($) | 0.0429 | 0.0292 (+32%) |
| Token savings | 8,070 | 4,650 (+42%) |
| Tool-call savings | 4.2 | 2.3 (+46%) |
| Latency savings (s) | 39.8 | 15.8 (+60%) |
| Correctness | 93% | 93% (equal) |
Graft never answered worse than cold, on any corpus. The pull variant gave up most of that speed for something bigger: correctness jumped to 98%, +5 points over cold, the strongest single result in the sweep. Push when speed is what you need; pull when being right matters more.
SWE-bench Verified
The sweep above is our harness measuring our mechanism. So we ran the industry-standard one too — SWE-bench Verified, real GitHub issues from real repos, graded by the official swebench harness. No judge model, no similarity score: your patch is applied, the maintainers' own tests are run, and you either flip the failing test without breaking the passing ones or you don't.
50 instances, same model on both arms — Claude Sonnet 5 — same Docker images, same turn limits. The only difference is whether graft is wired in.
| Correctness & efficiency | Cold Claude Code | Claude Code with graft | Improvement |
|---|---|---|---|
| Correctness | 27 / 50 (54%) | 33 / 50 (66%) | +12 pts |
| Token savings | 142.0M | 109.4M | +23% |
| Cost savings | $52.34 | $42.43 | +19% |
| Tool-call savings | 1,370 | 1,031 | +25% |
| API-request savings | 2,455 | 1,875 | +24% |
| Wall-clock savings | 13,094s | 8,922s | +32% |
graft resolved 33 of 50 instances against Cold Claude Code's 27 — and got there with 25% fewer tool calls, 23% fewer tokens, and 32% less wall-clock time. Every correctness win has the same shape: the baseline patches one file and misses its siblings. On django-11532 it patched 1 of the 5 files the fix requires and broke 18 previously-passing tests, twice over. On django-16263 it patched 1 of 4 and scored 102 / 103. graft found the rest — and on django-16263 did it in half the tokens and half the time.
Two harnesses, two claims: the controlled sweep says graft is cheaper and faster, SWE-bench says it's also more correct.
Correctness over all instances; tokens, cost and calls over the instances both arms resolved, for a like-for-like comparison. Official SWE-bench Verified images and official swebench 4.1.0 grader, native x86_64.
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.
flowchart LR
S[Source files] --> T["Tier 1 — tree-sitter<br/>no model, no key"]
S --> P1["Pass 1 — LLM summarizes<br/>each file (--deep)"]
T --> W["graft/.graph/wiring.json<br/>per-symbol code graph"]
P1 --> P2["Pass 2 — group into nodes<br/>+ typed links"]
P2 --> N["graft/*.md<br/>markdown node graph"]
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. Git determines the visible file set; freshness compares the working-tree bytes rather than commit or index state. 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.
Supported languages
Graft parses with tree-sitter at two levels of fidelity, plus an optional
compiler-grade layer — all $0 and deterministic (no model, no key):
-
Full-fidelity — hand-written extractors with scope-aware, cross-file call and import resolution: TypeScript / JavaScript (incl. JSX & TSX), Python, Go, Java, Kotlin, PHP, Swift (classes, structs, enums, actors, protocols; extension members attach to the extended type), R (
.R/.r— plain functions, S3/S4/R6 classes and methods, roxygen@export,library()/source()imports). -
Broad — symbols (functions, classes, methods, types, …) plus name-resolved call edges via a generic tree-sitter extractor, one grammar per language: Rust, C, C++, C#, Ruby, Scala, Elixir, Solidity, OCaml, Zig, Dart, Clojure, Nix, Lua.
-
Compiler-grade edges (opt-in) —
graft build --lspadds preciselsp_resolvedcall edges (member calls the static pass can't type) when a language server is on yourPATH: rust-analyzer (Rust), clangd (C/C++), gopls (Go), pyright (Python), typescript-language-server (TS/JS). It's best-effort — with no server installed the graph is unchanged.
Twenty-three languages in total. A file whose language isn't listed is skipped, not indexed. Adding a broad-tier language is a small contribution — see CREDITS.md for the folks who added the current set.
What's in a node
A node is a single markdown file. Most code maps stop at an address: this thing lives in that file, on that line. That tells an agent where to look, not what it will find, so it still has to open the source and read. A Graft node holds the meaning inline, so the agent learns what it needs up front and opens the file only when it wants more.
Each node holds:
| Part | What it holds |
|---|---|
| Summary | A plain-English explanation of what the code does, written by the model and cached. It is there whether or not the code was ever documented, and it is regenerated when the source changes. |
| Crux | The handful of lines that actually carry the logic: the guard, the skip condition, the state change. Lifted straight from the source and stored inline, so the agent sees how it works, not just what. |
| Sources | The exact files the node is built from, each tracked by a content hash, so Graft can tell precisely when a node has gone stale. |
| Links | Typed connections to other nodes (depends_on, part_of, uses, implements, produces), written as [[wikilinks]] your agent can follow. |
| Notes | Anything you write below the generated block. It is preserved across regenerations, so your own context is never overwritten. |
That is three depths in one file: the summary says what the code does, the crux shows how, and the sources point to the rest if the agent needs it. A plain index makes it read a whole file to learn one thing. A Graft node hands it the answer inline, and the follow-up read often never happens.
The crux is stored as the code itself, not as a line range, on purpose. Line numbers drift whenever unrelated code above them shifts, but the lines that matter do not. Keeping the text, not the numbers, means the crux stays correct even as the file around it moves.
Summary, sources, links, and notes ship today in markdown nodes. The crux ships per-symbol in the code graph (graft build --deep); inlining it into markdown nodes is next.
What runs where
- On your machine, no key, no network: the structural code graph.
graft build(wiring graph + per-file cards),graft check, andgraft askare deterministic tree-sitter — they never call a model. - Through your provider key: the LLM-written parts —
graft build --deepadds the concept nodes (file summaries + node synthesis) and the per-symbol summaries and cruxes. graft is vendor-neutral: setGRAFT_PROVIDER(openaifor any OpenAI-compatible endpoint,anthropicfor the native API, orlitellm/orcarouterfor a gateway that speaks the OpenAI-compatible format), yourGRAFT_API_KEY,GRAFT_MODEL, and — for theopenaiwire format —GRAFT_BASE_URLto point at OpenRouter, Fireworks, Groq, a LiteLLM proxy, a local server, or OpenAI itself. Or pass--provider/--model/--api-key/--base-urlon the command line. (OPENROUTER_API_KEYstill works as a deprecated fallback, andORCAROUTER_API_KEYas a second one.) - Anonymous usage stats — the only network calls are the LLM requests you configured, a daily npm version check, and one batched usage ping. The ping carries buckets and fixed labels only: never your code, file paths, repo name, symbols, queries, or error messages.
TELEMETRY.mdis the complete list andgraft telemetry debugprints exactly what your machine would send. Turn it off withgraft telemetry disable,DO_NOT_TRACK=1, or by unchecking the box ingraft init; it is off in CI and in any build from source.
See .env.example for the full list of settings (model, base URL, graph directory).
Agent integration
One command wires Graft into the coding agents you use:
npx @nanonets/graft init
# detects your agents and writes each one's native instruction file;
# Claude Code additionally gets the live statusline + hooks below
On a terminal, init shows you every agent it knows about — flagging the ones it detected (via their config directories) and listing the exact files each would write — and wires only the ones you select. Claude Code is pre-selected; nothing else is. Selected agents get a marker-fenced Graft section in their shared instruction file — AGENTS.md (Codex, OpenCode and other CLIs that read it), GEMINI.md, .github/copilot-instructions.md — or a wholly-owned rule/skill file for the agents that use one: .claude/skills/graft/SKILL.md, .cursor/rules/graft.mdc, .kiro/steering/graft.md, .windsurf/rules/graft.md, .grok/skills/graft/SKILL.md for Grok (xAI), .adal/skills/graft/SKILL.md for AdaL. Claude Code is in the second group: init writes its own skill file and never touches your CLAUDE.md. Re-running only updates Graft's own section (or replaces the owned file) and never touches the rest of your content.
With no TTY to prompt on — CI, a Dockerfile, a piped shell — init writes nothing and prints the command to run instead. Pass --agents <ids> or --yes to make a scripted run explicit.
| Flag | Effect |
|---|---|
--agents <ids...> | wire only these, no prompt — ids: agents, cursor, gemini, grok, copilot, kiro, windsurf, adal, claude |
--yes, -y | skip the prompt and wire every detected agent |
--dry-run | print every file init would touch, then exit without writing |
--all-agents | write instruction files for every known agent, detected or not |
--no-agents | Claude Code wiring only; skip other agents |
--list-agents | print the known agent ids and exit |
--no-mcp | skip MCP server registration |
--no-hooks | skip hook installation |
--no-statusline | skip writing Claude Code statusLine (same as GRAFT_NO_STATUSLINE=1) |
--no-global | skip writes outside this repo (the ~/.codex/ entries below) |
Writes outside the repo
Selecting the agents host also touches your user-level Codex config, when ~/.codex/ exists:
| Path | What changes |
|---|---|
~/.codex/config.toml | registers the Graft MCP server ([mcp_servers.graft]) |
~/.codex/hooks/graft/graft-hooks.cjs | the post-edit hook shim |
~/.codex/hooks.json | a PostToolUse entry matching Write|Edit|MultiEdit |
Both configs are user-level, so they apply to every repo you open with Codex, not just this one. The picker labels these machine-wide, --dry-run lists them in their own section, and --no-global skips them while still wiring AGENTS.md.
MCP server
graft init also registers Graft's MCP server with agents that support it, so these six tools appear natively, no shell required. Claude Code gets this too: graft init writes the server into the project's .mcp.json (restart Claude Code to load it). Skip with --no-mcp; run it manually with graft mcp [dir].
| Tool | Takes | What it's for |
|---|---|---|
graft_find_code | a question | Ranked nodes with file:line, source inlined — usually the full answer, no follow-up read needed. |
graft_file_api | a file path | Every signature in that file, no bodies — the API surface for a tenth of the tokens. |
graft_trace_calls | a symbol | Who depends on it, or what it depends on with direction: out, N levels deep for blast radius. |
graft_find_all | a regex | Every hit, grouped by enclosing symbol, ranked by how coupled that symbol is. |
graft_repo_map | nothing | A first look at an unfamiliar repo: directory clusters, hubs, hotspots. |
graft_check_freshness | nothing | Whether the local graph has drifted from the code. |
Register it by hand if your agent needs it explicit:
{ "mcpServers": { "graft": { "command": "npx", "args": ["-y", "@nanonets/graft", "mcp"] } } }
Where a CLI agent supports user-level hooks.json, init also installs Graft's post-edit hook — blast-radius warnings and automatic $0 graph re-sync after edits (skip with --no-hooks).
Claude Code (deep integration)
graft init always wires up Claude Code, and Claude Code gets more than the skill file above. From then on, any Claude Code session opened in the repo gets:
- a live statusline — graph size, % enriched, and a
⚠ N stalewarning when the code has moved ahead of the graph - auto-sync — every graft query brings the graph up to date first, so an answer always describes the code as it is right now, uncommitted edits included. A query refreshes only what it reads; the markdown under
graft/is refreshed by the background rebuild
Files in the repo
- .claude
- .github
- assets
- deploy
- docs
- scripts
- src
- test
- viewer
- .dockerignore
- .env.example
- .gitignore
- .ignore
- .mailmap
- CHANGELOG.md
- CREDITS.md
- Dockerfile
- LICENSE
- package-lock.json
- package.json
- README.md
- SECURITY.md
- TELEMETRY.md
- tsconfig.json
Discussion (0)
Ask about usage, or say what you built with itSign in to join the discussion.
No comments yet. Be the first to say what this is good for.
More connectors
High-performance code intelligence MCP server. Indexes codebases into a persistent knowledge graph — average repo in milliseconds. 158 languages, sub-ms queries, 99% fewer tokens. Single static binary, zero dependencies.

Universal provider proxy for OpenAI Codex & Claude Code — use any LLM (Claude, Gemini, Grok, DeepSeek, Ollama…) with Codex CLI, App, SDK, and Claude Code
Git-native persistent memory for AI coding agents. Implements Google OKF v0.2 with sub-300µs in-memory BM25 search, embedded MCP server, and progressive disclosure. Slashes token bloat by 80% with zero external databases or dependencies. Built in pure Go.
Local-first code intelligence graph for MCP and CLI. Builds a persistent map of your codebase so AI coding tools read only what matters, with benchmarked context reductions on reviews and large-repo workflows.
Stop your AI from making things up — it proposes, deterministic tools decide, every claim checked against ground truth with evidence. Grounded facts and context survive resets. Reverse engineering is the proving ground. MCP server + CLI.