repo2graph
Bir ajan bir kod tabanını grep ile taradığında, ya tüm dosyaları bağlama döker ya da farklı kelimeler tahmin ettiği için kodu tamamen kaçırır. repo2graph bunun yerine gerçek çağrı grafiğini oluşturur ve neyi döndüreceğine karar vermek için bunu kullanır — böylece çağıranlar ve çağrılanlar zaten ekli olarak, sabit bir token bütçesi içinde gerçek kaynak kodu elde edersiniz.
Dokümantasyon
Ask a repository a question and get back the source that answers it. Every block is headed
[cite: path:start-end], and the whole reply fits under a token ceiling that the tool enforces.
One tree-sitter pass records who calls whom, who imports what, and which files keep changing
together in git. Retrieval starts from BM25 matches and follows those links.
It needs no model, no API key, no language server and no database. Building, querying and the
MCP server make no network calls; the only exceptions are rag --answer (opt-in, sends the pack
to an LLM) and repo2graph github (clones a repository). Use it from the CLI, as an MCP server in Claude Code or Cursor, or as a GitHub Action.
Try it
uvx repo2graph demo # bundled example repo, five questions answered
uvx repo2graph build . -o .r2g # index your own code
uvx repo2graph rag "how does routing work" -o .r2g # a cited, budget-bounded context pack
Give an agent the same thing over MCP:
claude mcp add repo2graph -- uvx --from "repo2graph[mcp]" repo2graph-mcp .
Cursor, Claude Desktop and other clients: docs/mcp.md. Step-by-step with expected output: docs/quickstart.md.
Is it better than grep?
No, not at finding code. We measured it on 35 questions about Flask, requests, FastAPI and Hono, scored against the definitions that answer them, with both tools held to the same token budget (method, per-question results, reproduction):
| Budget | repo2graph | grep, then read around the hits |
|---|---|---|
| 2,000 tokens | 30% | 35% |
| 4,000 tokens | 39% | 61% |
| 8,000 tokens | 52% | 72% |
Graph expansion adds nothing over BM25 alone at these budgets. The causes are ranking problems: whole-file and whole-class chunks win the seed ranking and use up the budget, and expansion doesn't follow the edge direction the question asks for. They're diagnosed in the benchmark write-up and are the next thing to fix.
What it does do that grep doesn't:
- Relationships in one hop.
repo_neighboursreturns a symbol's callers, callees, base classes and defining file, each with a line number. Every edge carries aconfidence: a name that could mean several definitions is markedambiguousand priced at1/n, not guessed. - A hard ceiling. The pack is measured, clamped and re-measured before it's returned (12k tokens max over MCP), so an agent can't flood its own context through this tool.
- PR blast radius in CI.
repo2graph impactreports what a diff touches: callers, importers, subclasses, and the files git history says usually change alongside it (CO_CHANGE).
How it compares with Serena, Aider's repo map, CodeGraphContext, code-graph-rag, Sourcegraph, Cursor's index and Claude Code's own search, including when to use those instead: docs/comparison.md.
Five questions to start with
| Ask your repo | What the graph adds |
|---|---|
Where is authentication enforced? | the guard itself, plus the routes that call it |
What calls <function>? | CALLS edges into it, each with a confidence score |
What tests cover <module>? | IMPORTS edges from the test module back to the code under test |
What would be affected by changing <api>? | the definition, then its direct callers from the CALLS edges into it (explain node) |
Trace <a request> from route to persistence. | the handler and its callees one hop at a time, each block cited to file and line |
GitHub Action
- uses: actions/checkout@v4
with: { fetch-depth: 0 } # full history, so CO_CHANGE edges are meaningful
- uses: Srinivasan-78/repo2graph@v2
with:
git-history: "500"
commit-branch: graph # optional: publish graph.html to a browsable branch
@v2 follows every 2.x release; pin an exact tag (@v2.2.0) to upgrade by hand. The Action never
calls an LLM. Inputs, outputs and the PR-impact workflow: docs/github-action.md,
docs/pr-impact.md.
Commands
| Command | Does |
|---|---|
repo2graph build <path> -o .r2g | Parse a repo into a graph and chunks (--incremental, --git-history N) |
repo2graph query "<q>" -o .r2g | BM25 search plus one graph hop |
repo2graph rag "<q>" -o .r2g | Budget-bounded, cited context pack (--answer sends it to an LLM: opt-in, the only path that sends code anywhere) |
repo2graph impact -i .r2g --base main | Blast radius of a diff |
repo2graph explain <edge|node|retrieval> | Why an edge exists, or why a block was retrieved |
repo2graph github <owner/repo> -o <dir> | Fetch, build and clean up without a local clone |
repo2graph demo | Index a bundled example and answer the five questions above |
repo2graph map, repo2graph stats, repo2graph index-status, repo2graph embed | Re-render graph.html, report counts and freshness, add optional dense vectors |
repo2graph doctor, repo2graph bug-report, repo2graph explain-path, repo2graph completion | Diagnose setup, build a privacy-safe bug bundle, say why a path is (not) indexed, shell completion |
repo2graph-mcp <path> | stdio MCP server: repo_map, repo_search, repo_neighbours, repo_impact, and two status tools |
Full flags: docs/cli.md. Python API: docs/python-api.md.
What it can't do
- Resolve calls by type. Calls are matched by name, scoped by class, file, imports and
directory.
x.get()on a receiver of unknown type is recorded as a low-confidence guess, not a fact. For exact references, use a language-server tool. - See dynamic dispatch, reflection or computed imports. A missing edge doesn't prove that no call exists.
- Cross language boundaries (Python calling C++ through bindings).
- Rebuild itself when files change.
index-statusreports staleness; rebuild withbuild --incremental.
Symbols, calls and classes are extracted for Python, JS, TS, TSX, Go, Rust, Java, Ruby, C, C++, C#, PHP, Kotlin, Swift, Scala, Bash and Lua. Every other file is still indexed as text. Measured rates for each limitation: docs/limitations.md.
Status
The 2.x CLI, MCP tools and output schema follow semver: breaking changes wait for 3.0. Default paths run locally, send no telemetry and exclude secrets from agent replies unconditionally (privacy, threat model, security policy). A Docker image for read-only, non-root deployments is described in docs/ENTERPRISE_DEPLOYMENT.md.
Contributing
git clone https://github.com/Srinivasan-78/repo2graph && cd repo2graph
python3 -m venv .venv && .venv/bin/pip install -e ".[dev]"
make lint format-check typecheck test
Branch from develop. Start with .github/CONTRIBUTING.md,
docs/good-first-issues.md and
docs/ARCHITECTURE.md. The most useful contribution right now is new
questions for the retrieval benchmark, especially on repositories
you know well. All docs: docs/README.md.
MIT licensed.