Code Graph has two surfaces: a CLI you run directly, and an MCP server your coding agent calls on your behalf. They share one on-disk graph snapshot — the CLI builds it, the MCP server reads it.
Getting started
Install
Use your usual package manager. Each one drops two binaries on your PATH: code_graph (CLI) and code_graph-mcp (MCP server).
brew tap renso-ai/code-graph https://github.com/renso-ai/code-graph-homebrew
brew install renso-ai/code-graph/code-graph
npm · pip · cargo · go · curl options are listed on the install section.
First rebuild
From the root of any repository, build the graph:
code_graph rebuild
The first rebuild walks the whole tree. Subsequent rebuilds are incremental — only changed slices are re-indexed. Snapshots are written under .code_graph/snapshots/<id>/ with an atomic current.json pointer.
What gets stored
One graph holds everything Code Graph found in the repo:
code_graph-mcp speaks Model Context Protocol over JSON-RPC stdio. Most tools are read-only. The managed-policy tool also mutates — every write is atomic, dry-run-aware, and routes through the same writer the CLI uses.
Auto-discovery
On first run, code_graph-mcp --register adds the server to the launcher config of whichever clients it finds on the machine.
The server treats its working directory as the analyzed workspace. To scope it to one repo, set the launcher's cwd for the server entry — don't inject environment variables. Known CODE_GRAPH_* and RDB_* variables are scrubbed before each child code_graph call.
The twelve tools
Each tool takes an action field plus whatever that action needs, and its description carries per-action when/why guidance so an agent can pick the right endpoint from the tool list alone. Successful calls return a short text status and the full parsed payload in structuredContent. The authoritative CLI⇄MCP map is in docs/mcp-server.md.
Read the feature catalog, validate @feature tags, see the resolved tagging guide, and mutate the committed feature registry (deterministic and byte-identical to the CLI).
Slim read-only aggregator over the six managed policy surfaces. Two actions: status (which surfaces are configured in this workspace) and list (surfaces + the verbs each supports). To read or change a specific surface, use its own tool below.
Six per-surface registry tools, all the same shape as code_graph_feature: read + validate + mutate, with dry_run on every mutating action. Lifecycle transitions are named verbs, never --status: accept/reject/deprecate/supersede on ADRs; deprecate/reactivate on invariants. Attach/detach is always link/unlink. Delete is remove. The record id is the first positional argument.
Landmines are tripwires, not tickets — there is no resolved status. A landmine is addressed by link-ing its recurrence guard (invariant/test/ADR) and stays in place as the institutional-memory signal. It leaves the registry only via remove, and only when invalid or obsolete.
When an MCP session first reads the graph, the server writes a pin file under .code_graph/snapshots/sessions/<session_id>.json. index-prune won't garbage-collect a pinned snapshot, so the agent keeps reading the same view even when a concurrent rebuild moves current.json.
After a rebuild lands, call {"action": "repin"} to switch to the new snapshot. The pin is removed automatically when the server process exits.
Managed policy registries
Each of the six committed policy surfaces Code Graph already validates — ADRs, layer policy, the quality baseline, landmines, invariants, the doc-symbol allowlist — gets its own MCP tool, all the same shape as code_graph_feature: read + validate + mutate, with dry_run on every mutating action. code_graph_manage is the slim read-only cross-surface aggregator (status/list only).
Lifecycle transitions are named verbs, never a --status flag. ADRs flow proposed → accepted → deprecated (or superseded); invariants flow active ↔ deprecated via deprecate/reactivate. Landmines have no resolved status — they are tripwires, addressed by link-ing their recurrence guard (an invariant/test/ADR) and kept as institutional memory.
// Cross-surface read-only aggregator
{ "tool": "code_graph_manage", "action": "status" }
// One tool per surface — bare verbs (the tool name carries the surface)
{ "tool": "code_graph_adr", "action": "add",
"title": "Snapshot Activation Is Atomic", "dry_run": true }
{ "tool": "code_graph_adr", "action": "accept", "id": "ADR-0007" }
{ "tool": "code_graph_invariants", "action": "add",
"statement": "snapshot activation is atomic" }
{ "tool": "code_graph_invariants", "action": "link", "id": "CG-INV-001",
"sites": ["crates/code_graph/src/v2/snapshot.rs"],
"tests": ["snap_atomic"] }
{ "tool": "code_graph_landmines", "action": "link", "id": "LM-0001",
"related_invariants": ["CG-INV-001"] } // address by linking its guard
{ "tool": "code_graph_landmines", "action": "remove",
"id": "LM-0099", "dry_run": true } // preview-then-write
All writes route through the same atomic, deterministic registry writer the CLI uses, so an MCP-originated change is byte-identical to its CLI equivalent. The files are committed — git is the audit trail. Records are targeted by id only (no fuzzy match); every mutating call accepts dry_run to preview the diff and write nothing.
CLI
The CLI builds the graph and is also a perfectly good way to query it directly. Run code_graph --help for the full flag list.
rebuild
Build (or incrementally update) the snapshot. Pick a profile to bias chunk size, response budgets, and adapter strictness.
Bounded LLM context for one entity, file, or query. Includes direct deps, reverse deps, affected crates and tests, endpoints, features, docs, and small source snippets.
Manage the project-local policy surfaces from the CLI. The same atomic writer used by the MCP code_graph_manage tool.
code_graph manage status
code_graph adr add --title "Snapshot activation is atomic"
code_graph invariants add --id CG-INV-001 \
--statement "snapshot activation is atomic"
code_graph invariants site CG-INV-001 --path crates/code_graph/src/v2/snapshot.rs
code_graph landmines import design/landmines.md
code_graph quality-baseline accept --reason "new adapter coverage"
snapshots & rollback
Every rebuild writes a new snapshot directory and atomically swaps the current.json pointer. You can list, diff, prune, or roll back without touching the build cache.
Trend history is kept outside snapshot directories under .code_graph/trends/trends.jsonl, so rollback never loses it.
How agents use it
The agent loop
A coding agent typically runs four steps per task. Each maps to one MCP tool — no shell-out, no grep.
1
Search
code_graph_context with action: "search" finds the entry points relevant to the user's request.
2
Context
code_graph_context with action: "context_pack" returns a bounded set of related entities, tests, docs, and source snippets.
3
Impact
Before proposing an edit, code_graph_impact with action: "blast_radius" tells the agent which callers, tests, ADRs, and invariants would be affected.
4
Verify
After the edit, code_graph_impact with action: "affected_tests" gives the agent the exact test command to run.
Across the whole loop, the agent calls code_graph_session with action: "current" once to pin a snapshot, so reads stay consistent.
Local-only mode
Indexing, search, blast radius, and MCP serving all run locally against the on-disk snapshot. Source code never leaves the machine. The control plane only sees:
License heartbeats — to confirm the seat is still paid.
Anonymous, hashed snapshot fingerprints — to power optional cross-machine pinning.
Numeric aggregates (node count, edge count, rebuild duration) — for quota and trend reporting.
That's the full surface. No file contents, no symbol names, no commit messages.