repo-graph

A structural map of your codebase for AI coding assistants.

The model navigates to the right files by structure — instead of reading your whole repo or guessing. Works in any MCP client.

$ pip install mcp-repo-graph

Same bug, same model, same prompt — the only difference is whether repo-graph is installed.

Why a graph, in 30 seconds

Same bug, same model, same prompt. The only difference is whether repo-graph is installed. Without it: 75,308 tokens and 4m36s of grep-and-read. With it: 29,838 tokens and about 30s.

Install — pick your client

One command — registers the server for the current project:

claude mcp add repo-graph -- uvx mcp-repo-graph --repo .

Or install as a plugin (bundles config + usage instructions):

claude plugin marketplace add James-Chahwan/repo-graph
claude plugin install repo-graph@james-chahwan

Install the extension (it wraps the MCP server and works in Chat):

code --install-extension james-chahwan.repo-graph

Or search repo-graph in the Extensions marketplace.

Add to your MCP config (~/.cursor/mcp.json or Windsurf's MCP settings):

{
  "mcpServers": {
    "repo-graph": {
      "command": "uvx",
      "args": ["mcp-repo-graph", "--repo", "."]
    }
  }
}

One command:

codex mcp add repo-graph -- uvx mcp-repo-graph --repo .

Or add to ~/.codex/config.toml:

[mcp_servers.repo-graph]
command = "uvx"
args = ["mcp-repo-graph", "--repo", "."]

Verify with /mcp in the Codex TUI.

One command:

gemini mcp add repo-graph uvx mcp-repo-graph --repo .

Or add to ~/.gemini/settings.json:

{
  "mcpServers": {
    "repo-graph": {
      "command": "uvx",
      "args": ["mcp-repo-graph", "--repo", "."]
    }
  }
}

Restart Gemini CLI; check with /mcp.

In the editor: agent panel → … → Manage MCP Servers → View raw config, then add to mcp_config.json:

{
  "mcpServers": {
    "repo-graph": {
      "command": "uvx",
      "args": ["mcp-repo-graph", "--repo", "."]
    }
  }
}

Save, then refresh under Installed MCP Servers. (Remote servers use serverUrl; a local one like this uses command/args.)

Download the desktop extension and open it with Claude Desktop:

github.com/James-Chahwan/repo-graph → mcpb/repo-graph-*.mcpb

Or add the same mcpServers block (see “Any MCP client”) to your Claude Desktop config.

repo-graph speaks standard MCP over stdio. Point any client at:

{
  "mcpServers": {
    "repo-graph": {
      "command": "uvx",
      "args": ["mcp-repo-graph", "--repo", "."]
    }
  }
}

Listed on the MCP Registry as io.github.James-Chahwan/repo-graph.

Zero-install run (recommended):

uvx mcp-repo-graph --repo /path/to/your/repo

Or install, then run the server pointed at a repo:

pip install mcp-repo-graph
repo-graph --repo /path/to/your/repo

What it does

repo-graph parses your codebase with tree-sitter and builds a lightweight graph of what exists, how things connect, and where the entry points are — across 20+ languages and frameworks, frontend to backend. Your assistant queries the graph, finds the minimal set of files it needs, and reads only those. Less context burned, fewer wrong guesses, faster answers — for you and the model.

Six tools, one verb each, backed by the Rust engine. Every call returns a complete, ranked, located answer in one shot, so your assistant doesn't spiral through a dozen lookups.

orient

Repo shape, entry points, and where the graph is blind, so you know when to grep.

find

Any text — symbol, keyword, stacktrace, failing test, or diff — → the ranked nodes that matter.

impact

Blast radius: what a change affects or depends on, ranked and located, dead code flagged ⊘.

trace

A feature end-to-end across the stack, or the path between two nodes.

read

A node's exact source, sliced from its file — plus who calls it and what tests it.

refresh

Rebuild the graph. Incremental, and it self-updates as you edit.

It tells you when it doesn't know

Every code-graph tool looks good on the queries it can answer. The ones that cost you are the silent misses, where an empty result leaves your assistant guessing whether nothing uses this or the tool just couldn't see it. repo-graph answers an empty query with the reason, whether that reason is a fact or a heuristic, and which extractions are partial for that mechanism.

  No answer (no_edges, FACT): no carry edge touches `backend::server::server` in this
  graph; `backend::server::server` is a container: structural IMPORTS/CONTAINS/DEFINES
  are not carry edges, so seed a symbol inside it
    looked over: CALLS
    blind spots (grep to confirm):
      ⚠ CALLS (*): calls through reflection, dynamic dispatch, or higher-order
        indirection are not resolved — verify: grep the callee name
    searched 26 nodes

orient reports the same blind spots up front, so your assistant knows when to grep instead of trusting a gap.

Measured, not asserted. 14 symbols across FastAPI, Gin, Hono and NestJS, each a case where the graph honestly has no edge but real callers exist. Same agent, same task, the only difference being whether the empty answer explained itself. Cost fell about 3× on identical tasks, in 28 of 28 matched pairs, at the same number of turns. It did not change correctness: the model answered "not safe to delete" in all 56 runs, so this buys cheaper answers, not safer ones. One model, n=14, our own harness, so treat it as directional. Raw results: bench/absence.
whole diffs

Pass every symbol a change touches. One walk, one ranking. Names that don't resolve come back listed, not silently dropped.

dead code

Anything unreachable from a known entry point is flagged ⊘, so "nothing calls this" is a claim you can act on.

real labels

A declared component, service, hook or guard is labelled as one, not flattened to "class".

every row located

Each answer carries path:line, so the next step is a read, not a search.

It runs on your machine

There are hosted code-graph services now. They index your repo on their servers and you query it over the network. That's a real trade, and it's worth being explicit about which side of it repo-graph is on.

A hosted index

  • ✕
    Grant a third party read access to your repositories
  • ✕
    Your code is uploaded and indexed off your machine
  • ✕
    Per-seat monthly fee, per repo-size tier
  • ✕
    Fresh on push, so uncommitted work isn't in the graph
  • ✕
    Private, air-gapped or client repos are often a non-starter

repo-graph

  • ✓
    Nothing to grant. No app, no OAuth, no account
  • ✓
    Your source never leaves the machine. Parsing and the graph are local
  • ✓
    Free. MIT-licensed, no seats, no repo limits
  • ✓
    Fresh on save. A watcher rebuilds incrementally as you edit
  • ✓
    Works offline, on air-gapped boxes, and on repos you can't upload

The usual objection to running it yourself is that a local index goes stale. That's what the watcher is for. If it does drift, the engine rebuilds it on connect instead of serving you something old.

What you can ask

Say it in plain language to your assistant — repo-graph answers structurally, in one lookup, instead of grepping and reading files.

“Where does this frontend action end up in the backend?”

trace

Cross-stack path in one hop — grep can’t link stacks.

“What breaks if I change this component?”

impact

Ranked blast radius, forward or backward, with likely-dead code flagged ⊘.

“Show me how the login feature flows.”

trace

Entry point → handlers → data, each hop labelled — not a keyword guess.

“Get enough context to work in this repo.”

orient

Whole-repo structural map, capped to fit the context window.

“Find everything related to billing.”

find

The relevant cluster from a seed, ranked by relevance.

“Here’s a stacktrace — where do I even start?”

find

Paste the error; get the exact nodes it implicates, ranked.

One idea at a time

Fifteen short cuts, each showing one thing the graph does that a text search can't. Click to play.

See it on real repos

Real tool output against the current engine. This is what your assistant gets before it opens a single file.

Times are a cold build from a fresh clone. A warm start reads the cached graph in 0.02 to 0.18s, so your assistant never waits for it.