code-review-graph

tirth8205MIT活跃维护

本地优先的代码智能图谱,为 MCP 和 CLI 构建持久化代码库地图,让 AI 编码工具只读取相关部分,显著减少代码审查和大仓库场景的上下文消耗。

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.

v2.3.9发布于 2026-09-18 19:41 UTC32,678star +45 / 7 天2,973fork同步于 2026-11-10 05:20 UTC

怎么上手

由 README 提炼,执行前请确认
pip install code-review-graph
code-review-graph install
code-review-graph build
硬件要求按 README 说明

README 未说明

下载:源码 zip·GitHub Releases(安装包)本站不镜像安装包

项目说明

由 README 自动翻译提炼

本地代码知识图谱,让 AI 编码工具只读改动相关的文件,减少审查上下文

本地优先的代码智能图谱,为 MCP 和 CLI 构建持久化代码库地图,让 AI 编码工具只读取相关部分,显著减少代码审查和大仓库场景的上下文消耗。

核心能力

  • 用 Tree-sitter 解析代码为 AST,构建函数、类、导入的节点与调用、继承、测试覆盖的边
  • 通过 MCP 向 AI 工具提供最小审查文件集与爆炸半径分析
  • 增量更新与 watch 模式保持图谱新鲜,无需全量重建
  • 一条 install 命令自动检测并配置 Cursor、Claude Code、Codex 等十余种平台
  • detect-changes --brief 输出 Token 节省面板,对比原始上下文用量

容易踩的坑

需要 Python 3.10+;install 后需重启编辑器或工具才能生效;visualize --format svg 需额外安装 eval extra 中的 matplotlib

内容由模型根据 README 生成,可能不完整或不准确,以官方文档为准。看原文 README

最近发版

5 个版本v2.3.9
  1. v2.3.9最新正式版2026-09-18 · 2026-09-18 19:41 UTC

    [2.3.9] - 2026-09-18

    Added

    • visualize can draw a neighbourhood instead of the whole repository. The D3 page falls back to one bubble per community past 3000 nodes or 9000 edges, which a shallow clone of django (45,111 nodes, 397,762 edges) passes by 15x and 44x, so every serious codebase got the bubble view. Nine new flags seed a view and bound it: --seed-symbol, --seed-file, --seed-changed with --seed-changed-base, --seed-flow, --path-from and --path-to for a shortest path, and --depth, --render-depth and --max-nodes for how much is carried and drawn. Nodes outside the neighbourhood are absent from the payload rather than dimmed. A hop is a semantic edge (CALLS, IMPORTS_FROM, INHERITS, IMPLEMENTS, TESTED_BY, DEPENDS_ON); CONTAINS is structural and deliberately not a hop. Search, filters, community colouring, the flow selector and the keyboard shortcuts all keep working, and the default output is still one self-contained HTML file. The whole-repository view is unchanged when no seed flag is passed.
    • cross_repo_search_tool accepts repos, a list of registry aliases or folder names, to search only part of the registry. Names that match no entry come back in unknown and names that match several entries in ambiguous; both lists are bounded like every other list (#915).
    • query_graph_tool resolves dotted targets such as Details.QueryHandler.Handle through an indexed nodes.symbol column, added by migration v10. See Upgrade notes for the full schema move (#942, #934).
    • update and build_or_update_graph_tool report files that failed to parse: the status is partial, the summary names the files and the CLI prints a warning on stderr. A failed file keeps its previous graph rows (#952).
    • CRG_HOOK_WORKTREES=1 keeps the generated pre-commit hook active inside a linked Git worktree (#953).
    • CRG_DISCOVERY_TIMEOUT bounds each Git command that discovers what changed when a review tool or command was not handed an explicit file list. It defaults to 5 seconds, capped at CRG_GIT_TIMEOUT so an unset-but-lowered general budget still wins; setting it explicitly is an instruction and is used as given, above CRG_GIT_TIMEOUT included. When it is unset and CRG_GIT_TIMEOUT was set explicitly, discovery inherits that value, so the documented remedy for slow Git keeps working. Read on every call rather than frozen at import. CRG_GIT_TIMEOUT keeps its 30-second default and still governs build, update and watch (#262).
    • staging is promoted to testing automatically, once a day, when it has commits testing lacks, every required status check is green on its tip, and the promotion gate has not failed on the testing tip. .github/workflows/auto-promote.yml opens the promotion pull request and merges it with a merge commit, so contributor authorship survives; the decision lives in scripts/auto_promote.py and reads the required contexts from the testing ruleset at run time. It merges only a pull request it opened itself — same repository, staging → testing, labelled auto-promotion, and pinned with --match-head-commit to the commit whose checks were read — all re-verified immediately before the merge, so a fork branch named staging, a base branch changed after the fact, or a promotion pull request opened by hand cannot be merged by it. A hand-started run defaults to a dry run. Requires Allow GitHub Actions to create and approve pull requests under Settings → Actions → General. Promotion to main is never automatic and the workflow cannot target it.

    Changed

    • Keyword search is rebuilt, and it needs a rebuilt graph. _fts_search wrapped the whole query in one pair of double quotes, so every multi-word search was an exact-adjacency phrase match: on a build of this repository password hashing returned 0 rows. Queries are now built from tokens — each quoted, given a prefi
  2. v2.3.82026-08-21 · 2026-08-21 22:37 UTC
    查看更新说明

    Patch release. 85 merged pull requests since v2.3.7, most of them fixes from community reports.

    Watch mode stops going quiet

    watch was the weakest surface in 2.3.7, and three separate failures could leave the daemon reporting ok while the graph stopped updating:

    • OS watches are no longer registered inside ignored trees, so a Maven target/ or a large node_modules cannot exhaust the inotify budget (#811).
    • Deleting and recreating a watched directory (rm -rf src && mkdir src, or two ordinary git checkouts) is recognized as a replaced directory rather than a dead watcher, on filesystems that change the inode and on those that hand the same one straight back.
    • A repository reached through a symlinked path is watched and indexed instead of silently dropping every event, through both watch --repo and serve --auto-watch (#892).

    One graph per repository, however you spell the root

    Every path-valued --repo is canonicalized at the CLI boundary, and the full build, incremental update and watch entry points each resolve their root. ., a relative path, a trailing slash, a symlinked path and an absolute path no longer split the graph or reconcile each other away. A run whose stored File nodes all belong to a different root is now refused with a clear error instead of emptying the graph file by file (#889).

    Token budgets that hold

    #849 found get_affected_flows returning roughly 247k tokens inside a workflow documented as "5 tool calls, 800 tokens total". Measuring all 30 registered tools against a real 5.6k-node graph found the same shape in ten more places. Every response list now carries a hard ceiling, keeps its untruncated total, and reports "showing N of M", so a short answer is distinguishable from a truncated one (#849, #853, #887). Four query tools remain and are tracked in #888.

    Honest empty results

    Empty results from query_graph, get_impact_radius and semantic_search_nodes now carry a one-sentence confidence field saying why the count is zero — never indexed, graph behind the working tree, a known static-analysis gap for that language, or a verified real absence. Responses that carry results are byte-identical to before (#314, #819, #850, #851).

    Also in this release

    • code-review-graph forget PATH ... drops already-parsed files without a full rebuild.
    • uninstall --platform NAME unbinds a single platform and leaves the rest intact.
    • A Voyage AI embedding provider, and embeddings persisted after every batch so an interrupted cloud run keeps its progress (#783).
    • Language fixes: C# receiver calls and namespace imports, Swift initializers and subscripts, Java method names, Kotlin import comments, Go generic receivers, Python module-suffix import resolution, jsconfig.json path aliases.
    • visualize --serve works offline, and status no longer reports phantom languages.

    Full detail in CHANGELOG.md.

  3. v2.3.72026-07-18 · 2026-07-18 00:33 UTC
    查看更新说明

    code-review-graph 2.3.7

    Maintainer-reconciliation release containing the verified work merged since v2.3.6. The four client-validation drafts remain excluded. No breaking changes.

    Highlights

    • expanded CLI-first workflows, CommonJS parsing, quiet/JSON output, enrichment, and dead-code analysis
    • broader Terraform, Ansible, VB.NET, SystemVerilog, Rust, PHP/Laravel, Julia, Python, C#, Java, Spring, and WebFlux graph coverage
    • bounded transitive test coverage, churn risk, weighted impact ranking, graph provenance, documentation-aware embeddings, and safe JSON export
    • safer uninstall and platform configuration, including CodeBuddy and official OpenCode contracts
    • hardened MCP concurrency, daemon lifecycle, Windows process handling, Git path parsing, ignore rules, community detection, and visualization layout
    • updated supported dependency and GitHub Action versions, plus secure fork-PR review handling
    • closed all three open high-severity CodeQL alerts

    Validation

    • release PR: 15/15 checks passed
    • merged main commit: 13/13 checks passed
    • wheel and source distribution built successfully with version 2.3.7

    See CHANGELOG.md for the detailed release notes and PR references.

  4. v2.3.6v2.3.6 — community-response release2026-06-10 · 2026-06-10 18:29 UTC
    查看更新说明

    Community-response release. Built from a full audit of every open PR, issue, and discussion — community fixes merged with credit, verified defects fixed (including two open Windows bugs), benchmark claims made independently checkable, and the project's first self-hosted PR review bot: this repo now reviews its own pull requests with its own graph.

    Highlights

    • Custom languages without forking (#320): drop a .code-review-graph/languages.toml into your repo to index any grammar shipped by tree-sitter-language-pack. See docs/CUSTOM_LANGUAGES.md.
    • GitHub Action for risk-scored PR reviews: builds/restores the graph from CI cache and posts a sticky review comment with risk table, affected flows, test gaps, and token savings. See docs/GITHUB_ACTION.md.
    • Honest benchmarks: new agent_baseline benchmark (graph vs a realistic grep-and-read agent), failed eval runs excluded from aggregates instead of inflating them, non-circular co-change ground truth for impact accuracy, weekly report-only eval CI. README now leads with the ~82x median; 528x is the best case, not the headline.
    • docs/FAQ.md: vs LSP, vs RAG, vs agentic grep, when NOT to use this tool, and how to verify it's working.

    Fixes

    • Windows: daemon status WinError 87 crash (#511) and CLI detect-changes mapping 0 functions (#528)
    • store_file_batch transaction guard (#489 — community PR #529 by @Devilthelegend, thank you)
    • Unknown embedding providers now error instead of silently using the local model
    • Analysis tools no longer leak SQLite connections; fastmcp capped <4; git hooks now work in worktrees and core.hooksPath/husky setups; shipped hooks drain stdin
    • Translated READMEs carry staleness banners and no longer contradict the English benchmark numbers

    Full details in CHANGELOG.md. No breaking changes.

  5. v2.3.5v2.3.5 — Real-time token savings, visible to humans2026-05-25 · 2026-05-25 22:01 UTC
    查看更新说明

    Real-time token savings, visible to humans. The estimated context-savings metric introduced in 2.3.4 was JSON-only. In 2.3.5 it surfaces as a clean boxed panel on the CLI and is verifiable against a real tokenizer in one flag — so when you reach for code-review-graph to review a change, you can immediately see how much of your context window the graph just kept out.

    Token Savings demo

    Highlights

    • 🪟 Token Savings panel on both code-review-graph detect-changes --brief and the new code-review-graph update --brief. Per-category breakdown (Functions / Tests / Risk / Other) that sums exactly to the graph response size.
    • ✅ --verify flag cross-checks the displayed numbers against OpenAI's cl100k_base tokenizer. Calibration shows the estimate stays within +0.5% of real GPT-4 tokens in aggregate across 222 mixed-language source files (data in docs/REPRODUCING.md).
    • 🔁 Deterministic eval pipeline — pinned upstream SHAs, full clones with returncode checks, fixed Leiden seed. Two contributors running the benchmark recipe on different machines on different days now produce identical numbers.
    • 🎯 Multi-hop retrieval benchmark + richer embedding text + identifier-aware search boost lift compound-query accuracy from 0.545 → 0.909.
    • 📦 code-review-graph embed CLI subcommand for explicit embedding generation. Previously only reachable via MCP.

    What the panel looks like

    ```text ┌─────────────────────── Token Savings ────────────────────────┐ │ Full context would be: 12,921 tokens │ │ Graph context used: 762 tokens │ │ Saved: 12,159 tokens (~94%) │ │ Breakdown: Functions 244 · Tests 191 · Risk 244 · Other 83 │ └──────────────────────────────────────────────────────────────┘ ```

    Add --verify to grow a Verified (tiktoken) row so the numbers are no longer just an estimate.

    Reproduction

    End-to-end recipe with canonical numbers in docs/REPRODUCING.md. All 6 test repos pin upstream SHAs, embeddings are deterministic on CPU, Leiden detection is seeded.

    Full release notes

    CHANGELOG.md — v2.3.5 entry

用户点评

登录用户的真实使用记录,可按版本和硬件筛选
共 0 条

    还没有人点评。第一个说出真实体验的人最有价值。

    README 原文

    未翻译

    AI coding tools often re-read large parts of a codebase to review a change. code-review-graph builds a structural map of the code with Tree-sitter, keeps it updated incrementally, and serves compact context over MCP, so the assistant reads only the files a change touches.


    Quick Start

    pip install code-review-graph          # or: pipx install code-review-graph
    code-review-graph install              # detect installed AI coding tools and configure each one
    code-review-graph build                # parse the codebase
    

    install detects which AI coding tools you have, writes an MCP server entry for each, installs hooks and skills where the platform supports them, and adds graph instructions to the platform's rules file. The MCP entry uses poetry run or uv run inside a Poetry or uv project environment, uvx code-review-graph serve when uvx is on PATH, and otherwise the current Python interpreter. Restart the editor or tool afterwards.

    To configure one platform, pass --platform with one of codex, claude-code, cursor, windsurf, zed, continue, opencode, antigravity, gemini-cli, qwen, kiro, qoder, copilot, copilot-cli, codebuddy, or hermes:

    code-review-graph install --platform cursor
    code-review-graph install --platform codebuddy
    

    Config file locations are listed in docs/USAGE.md. Requires Python 3.10+.

    For Codex, the installer also places a global code-review-graph Skill under $CODEX_HOME/skills/code-review-graph/ (default: ~/.codex/skills/code-review-graph/). It prefers CRG MCP tools and falls back to the bundled read-only CLI when MCP is unavailable; a missing, empty, or stale graph never triggers an implicit build or update. WSL and Windows Codex runtimes have separate CODEX_HOME directories and tool inventories, so install and refresh the runtime that will execute the task.

    uninstall removes CRG-owned files and entries from a Git or SVN working tree and leaves other MCP servers, hooks, skills and JSONC comments alone. Run it from anywhere inside the tree. Shared config files are replaced atomically, so a failed write leaves the original intact.

    code-review-graph uninstall --dry-run    # preview only
    code-review-graph uninstall              # preview, confirm, apply
    code-review-graph uninstall --yes        # apply without prompting
    code-review-graph uninstall --all-repos  # also clean every registered repository
    code-review-graph uninstall --keep-data  # remove integrations, keep graph databases
    code-review-graph uninstall --keep-user-configs --repo .  # this project only
    

    Then open the project and ask the assistant:

    Build the code review graph for this project
    

    Build time scales with repository size; a cold build of a ~3,000-file repository took about 40 seconds (measured). After that, hooks and watch mode keep the graph updated. If some files fail to parse, the result has status partial and names them in its summary; the CLI also prints a Warning: line on stderr, and those files keep their previous graph rows.

    How It Works

    The repository is parsed into ASTs with Tree-sitter and stored as a graph of nodes (functions, classes, imports) and edges (calls, inheritance, test coverage). At review time the graph is queried for the smallest set of files the assistant needs to read.

    Blast-radius analysis

    When a file changes, the graph traces every caller, dependent and test that could be affected. The assistant reads those files instead of scanning the whole project.

    Incremental updates

    Hooks, the git hooks (pre-commit, post-checkout, post-merge, post-rewrite) and watch mode trigger incremental updates. The update diffs changed files, finds their dependents through the graph's import and call edges, and re-parses only the files whose SHA-256 hash changed. On a ~3,000-file project (django) a two-file edit re-indexes in about 2.5 seconds on the path the hooks use, of which ~1.4 s is process start-up; a no-op update costs only that start-up. See Incremental update latency.

    Whole codebase or targeted answer?

    Instead of feeding a whole corpus to the model, the graph returns a slice shaped to the question. In the 2026-08-02 capture of this repository at 84bde354, 208,821 source tokens became ~3,190 tokens per question. The repository has grown a lot since that snapshot, so both numbers are larger today.

    Language coverage and notebooks

    The parser extracts functions, classes, imports, call sites, inheritance and tests, using Tree-sitter where a grammar exists and targeted fallbacks elsewhere. Supported: Python, JavaScript/TypeScript/TSX, Go, Rust, Java, C/C++, C#, VB.NET, Ruby, Kotlin, Swift, PHP, Scala, Solidity, Dart, R, Perl, Lua/Luau, Objective-C, shell scripts, Elixir, Zig, PowerShell, Julia, ReScript, GDScript, Nix, Verilog/SystemVerilog, SQL/PL/SQL (Oracle), Terraform/OpenTofu (.tf; other .hcl files become file nodes only), Ansible YAML (playbooks, roles, tasks), Spring Boot application config (application.properties, application.yml, application.yaml and their application-<profile> variants; key names and value types only, never values), value-free generic YAML structure, Vue/Svelte SFCs, Astro files (parsed with the TypeScript grammar), Jupyter and Databricks notebooks (.ipynb), Perl XS files (.xs), and Robot Framework files (.robot, .resource). Other .properties files are not treated as source code.

    PHP projects also get repository-bounded Composer PSR-4 resolution, Blade template references, and Laravel Route and Eloquent edges when the source shows explicit framework imports, model inheritance and receiver evidence. Static Laravel routes in routes/*.php emit Endpoint nodes and controller HANDLES edges, including literal group prefixes.

    Java projects get Spring dependency-injection call resolution, request endpoints and WebFlux routes, scheduled triggers, application-event publisher-to-listener edges, and Temporal workflow and activity edges. Each resolver runs after the parse and needs the injected field, published event or workflow stub to be visible in the repository.

    Add your own language

    If your repository uses a language the parser does not cover, add a languages.toml to .code-review-graph/ that maps file extensions to any grammar bundled in tree_sitter_language_pack, plus the node types for functions, classes, imports and calls:

    [languages.erlang]
    extensions = [".erl"]
    grammar = "erlang"
    function_node_types = ["function_clause"]
    class_node_types = ["record_decl"]
    import_node_types = ["import_attribute"]
    call_node_types = ["call"]
    

    The generic tree-sitter walker does the extraction. Built-in languages cannot be overridden. See docs/CUSTOM_LANGUAGES.md for the schema, validation rules and a worked example.

    Risk-scored PR reviews in CI (GitHub Action)

    The same analysis runs as a composite GitHub Action. The graph is built and queried on your CI runner; no source code is sent to an external service. On each pull request the action posts one sticky comment with risk-scored functions, affected execution flows and test gaps, updated in place on every push. The optional fail-on-risk input turns it into a merge gate.

    # .github/workflows/code-review-graph.yml
    on:
      pull_request:
    
    permissions:
      contents: read
      pull-requests: write
    
    jobs:
      review:
        runs-on: ubuntu-latest
        steps:
          - uses: actions/checkout@v7
          - uses: tirth8205/[email protected]
            with:
              github-token: ${{ secrets.GITHUB_TOKEN }}
    

    See docs/GITHUB_ACTION.md for inputs, risk levels and caching, or the workflow this repository runs on itself in .github/workflows/pr-review.yml.


    Benchmarks

    The median per-question token reduction across the 6 repositories is about 63x (whole-corpus baseline vs graph query). The 358x maximum is one repository (fastapi, the largest corpus), not the typical result.

    All numbers come from the evaluation runner against 6 open-source repositories (13 commits). Every config pins an upstream SHA, Leiden runs with a fixed seed, and embeddings are deterministic on CPU, so two runs on different machines produce the same numbers. The reproduction recipe is in docs/REPRODUCING.md. A weekly report-only run on the two smallest configs lives in .github/workflows/eval.yml.

    For a typical agent question ("how does authentication work", "what is the main entry point", and so on), the graph returns ~2,200 to 3,900 tokens of search hits plus neighbour edges instead of every source file. The table averages the 5 sample questions defined in code_review_graph/token_benchmark.py.

    RepoSnapshot SHAnaive_corpus_tokensavg graph_tokensReduction
    fastapi22381558948,7932,653357.6x
    flaska29f88ce143,5942,19665.4x
    code-review-graph84bde354208,8213,19065.5x
    gin5c00df8a166,8682,76660.3x
    httpxb55d4635142,3562,66153.5x
    expressb4ab7d65136,0523,93634.6x

    Captured 2026-08-02 from clean clones at the pinned SHAs (crg 2.3.7, local all-MiniLM-L6-v2 embeddings). These numbers are lower than the 2026-05-25 capture they replace: node embedding text became richer, so avg graph_tokens rose in every repo. fastapi is measured at its current pin 22381558 rather than the retired 0227991a.

    The Reduction column is naive_corpus_tokens / avg graph_tokens, so it divides out from the two columns beside it. The benchmark's own average_reduction_ratio averages the five per-question ratios instead, which always reads higher; those per-question figures are in docs/REPRODUCING.md.

    The code-review-graph row is a snapshot, not a current measurement. The repository has grown since 84bde354, so its corpus and graph are both much larger today.

    The whole-corpus baseline is an upper bound no real agent pays; an agent greps for identifiers and reads the best-matching files. The agent_baseline eval benchmark measures that case (a pure-Python grep over the corpus, top-3 files by match count, token-counted against the graph query cost). Against that realistic baseline the median across 18 questions on 6 repositories is 6.65x (mean 14.8x, range 4.2x to 72.6x), captured 2026-09-22, before search and this baseline began ranking test files lower, so code-review-graph eval --benchmark agent_baseline --embed now gives different numbers until the capture is redone. The full table is in docs/REPRODUCING.md, under "Canonical capture, 2026-09-22".

    The ratio tracks repository size, because the graph answer stays flat (2,432 to 4,021 tokens across every repo measured) while the grep baseline grows with the corpus: 4.5x on express, 52x on fastapi. Both figures measure retrieval cost, the tokens needed to locate an answer. An agent that then opens the files the graph named pays the graph on top of its usual reads rather than instead of them; semantic_search_nodes_tool(include_source=True) returns the code with the locations so it does not have to, and measuring that path end-to-end is open work.

    The formal token_efficiency benchmark measures a different scenario, the full get_review_context() JSON against only the changed-file content of a commit, and reports ratios below 1 for small commits because the response carries impact-radius edges and source snippets. The two benchmarks answer different questions; see docs/REPRODUCING.md.

    Review and impact tools attach a compact context_savings estimate to their responses. The CLI shows the same figures in the Token Savings panel (see Usage below) and --verify compares them with OpenAI's cl100k_base tokenizer. Calibration across 222 sample files puts the estimate within about 1% of real tokens in aggregate (data).

    Blast-radius analysis recovers every file in the ground truth on all 13 evaluation commits. Read that as an upper bound, not as "100% recall": the ground truth (changed files plus files with call or import edges into them) comes from the same graph the predictor traverses. The lower precision is deliberate; flagging an extra file costs less than missing a broken dependency.

    RepoCommitsAvg F1Avg PrecisionRecall (graph-derived upper bound)
    httpx20.8630.7851.0
    code-review-graph20.7340.5841.0
    fastapi20.6970.5391.0
    express20.6670.5001.0
    flask20.6330.4851.0
    gin30.6090.4391.0
    Average130.6930.5461.000

    The benchmark also runs a co-change mode: the predictor is seeded with one changed file and graded against the other files the author touched in the same commit, which is evidence from git history rather than from the graph. Both modes appear in the result CSVs (ground_truth_mode column). In the 2026-08-02 capture co-change mode returned predicted_files = 0 on every graded commit, so it is not yet a usable measurement and no co-change number is quoted.

    From the same 2026-08-02 clean-room build at the pinned SHAs above. Embedding counts are lower than node counts because File nodes are not embedded. The code-review-graph row is that snapshot, not the repository as it stands now.

    RepoNodesEdgesEmbeddings
    fastapi6,28732,0365,159
    express1,99019,4921,849
    gin1,58917,2371,491
    code-review-graph1,4469,0941,354
    flask1,4158,2591,329
    httpx1,2638,2361,193

    Limitations

    • Impact "recall 1.0" is circular. The historical ground truth comes from the same graph edges the predictor walks, so it is an upper bound by construction. The co-change mode is not yet a usable measurement.
    • Small single-file changes. Graph context can exceed a plain file read for trivial edits. The overhead is the structural metadata that makes multi-file analysis possible.
    • Search ranking. Keyword search usually finds the right result near the top, but ranking needs work. Express queries can return no hits because of module-pattern naming.
    • Flow detection. Entry-point detection is strongest for Python and PHP/Laravel. JavaScript and Go flow detection needs work.
    • Precision vs recall. Impact analysis is conservative. It flags files that might be affected, which means false positives in large dependency graphs.

    Features

    FeatureDetails
    Incremental updatesRe-parses only files whose hash changed. On a ~3,000-file repo a two-file edit takes ~2.5 s on the hook path (measured).
    Language and notebook supportSee Language coverage above.
    Framework-aware PHP parsingRepository-bounded Composer PSR-4 imports, Blade template references, evidence-gated Laravel Route-to-controller and Eloquent relationship edges
    Framework-aware Java parsingSpring dependency-injection call resolution, request endpoints and WebFlux routes, scheduled triggers, application-event publisher-to-listener edges, Temporal workflow and activity edges, and Spring Boot config keys indexed without their values
    Blast-radius analysisWhich functions, classes and files are likely affected by a change
    Auto-update hooksEditor hooks, git hooks (before each commit, after checkout, merge and rebase) and watch mode update the graph as you work
    Semantic searchOptional vector embeddings via sentence-transformers, Google Gemini, MiniMax, Voyage AI, or any OpenAI-compatible endpoint (OpenAI, Azure, new-api, LiteLLM, vLLM, LocalAI)
    Interactive visualisationD3.js force-directed graph with search, community legend toggles and degree-scaled nodes
    Hub and bridge detectionMost-connected nodes and chokepoints (betweenness centrality)
    Surprise scoringUnexpected coupling: cross-community, cross-language, peripheral-to-hub edges
    Knowledge gap analysisIsolated nodes, untested hotspots, thin communities
    Suggested questionsReview questions generated from bridges, hubs and surprises
    Edge confidenceTwo-tier confidence (EXTRACTED/INFERRED) with float scores on edges
    Graph traversalBFS/DFS from any node with configurable depth and token budget
    Export formatsGraphML (Gephi/yEd), Neo4j Cypher, Obsidian vault, JSON, and SVG (SVG needs matplotlib from the eval extra)
    Token benchmarkingcode_review_graph/token_benchmark.py measures whole-corpus tokens against graph query tokens per question
    Estimated context savingscontext_savings metadata (estimated, saved_tokens, saved_percent) on review, impact, detect-changes and architecture responses
    Community auto-splitCommunities above 25% of the graph are split recursively with Leiden
    Execution flowsCall chains from entry points, sorted by weighted criticality
    Community detectionLeiden clustering with resolution scaled to graph size
    Architecture overviewCommunity-based architecture map with coupling warnings
    Risk-scored reviewsdetect_changes maps diffs to affected functions, YAML paths, flows and test gaps
    Custom languagesNew languages via .code-review-graph/languages.toml, no fork needed
    GitHub ActionSticky risk-scored PR review comments in CI, with an optional fail-on-risk merge gate
    Refactoring toolsRename preview, framework-aware dead code detection, community-driven suggestions
    Wiki generationMarkdown wiki from community structure
    Multi-repo registryRegister several repos and search across them
    Multi-repo daemoncrg-daemon watches several repos as child processes, with health checks and restart
    MCP prompts5 workflow templates: review, architecture, debug, onboard, pre-merge
    Full-text searchFTS5 hybrid search combining keyword and vector similarity
    Local storageOne SQLite file in .code-review-graph/; no external database or cloud service

    Usage

    install writes these four skills for the platforms that support them (Claude Code, Gemini CLI, CodeBuddy Code, Hermes Agent and Qoder). Ask for one by name.

    SkillDescription
    explore-codebaseNavigate and understand codebase structure using the knowledge graph
    review-changesPerform a structured code review using change detection and impact
    debug-issueSystematically debug issues using graph-powered code navigation
    refactor-safelyPlan and execute safe refactoring using dependency analysis

    Qoder also gets build-graph, review-delta and review-pr from the repository's skills/ directory.

    code-review-graph install          # Detect and configure all platforms
    code-review-graph install --platform <name>  # One platform
    code-review-graph uninstall --dry-run  # Preview removal of installed artifacts
    code-review-graph build            # Parse the whole codebase
    code-review-graph update           # Incremental update (changed files only)
    code-review-graph status           # Graph statistics
    code-review-graph watch            # Update on file changes
    code-review-graph forget <path>    # Drop already-parsed files from the graph
    code-review-graph dead-code        # Functions and classes with no callers or tests
    code-review-graph visualize        # Interactive HTML graph
    code-review-graph visualize --format json      # Export graph data as JSON
    code-review-graph visualize --format graphml   # Export as GraphML
    code-review-graph visualize --format svg       # Export as SVG (needs matplotlib)
    code-review-graph visualize --format obsidian  # Export as Obsidian vault
    code-review-graph visualize --format cypher    # Export as Neo4j Cypher
    code-review-graph wiki             # Markdown wiki from communities
    code-review-graph detect-changes --brief         # Risk panel + token savings (read-only)
    code-review-graph detect-changes --brief --base main  # Against the merge base of main and HEAD
    code-review-graph update --brief                 # Refresh graph + same panel
    code-review-graph detect-changes --brief --verify  # Cross-check against tiktoken
    code-review-graph register <path>  # Register repo in the multi-repo registry
    code-review-graph unregister <path|alias>  # Remove repo from the registry
    code-review-graph repos            # List registered repositories
    code-review-graph daemon start     # Start the multi-repo watch daemon
    code-review-graph daemon stop      # Stop the daemon
    code-review-graph daemon status    # Daemon status and repos
    code-review-graph eval             # Run evaluation benchmarks
    code-review-graph serve            # Start the MCP server (stdio)
    code-review-graph serve --http     # MCP over Streamable HTTP on localhost:5555
    

    This is a selection. code-review-graph --help lists every command, and docs/COMMANDS.md documents their flags.

    When detect-changes --base names a branch, the diff runs against the merge base of that branch and HEAD. Commit hashes and other revisions are used as given.

    visualize --format svg needs matplotlib, which ships in the eval extra (pip install "code-review-graph[eval]"). The other export formats need no extra install.

    JSON exports are written inside the local graph data directory, which Git ignores by default. They can contain absolute paths and code-structure metadata, so inspect an export before publishing it.

    Both commands print the same panel showing how many tokens the graph saved compared with handing the changed files to an agent raw. They differ in one thing: whether the graph is refreshed first.

    ┌─────────────────────── Token Savings ────────────────────────┐
    │ Full context would be:     12,921 tokens                     │
    │ Graph context used:           762 tokens                     │
    │ Saved:                     12,159 tokens (~94%)              │
    │ Breakdown: Functions 244 · Tests 191 · Risk 244 · Other 83   │
    └──────────────────────────────────────────────────────────────┘
    
    CommandWhat it doesWhen to use
    detect-changes --briefRead-only. Queries the existing graph for the current changes and prints the panel.Most of the time; hooks or crg-daemon keep the graph fresh.
    update --briefRe-parses the changed files into the graph first, then prints the same panel.After a rebase, a large change set, or whenever the graph may be stale.

    Add --verify to either command to compare the figures with OpenAI's cl100k_base tokenizer (needs pip install tiktoken). The estimate is within about 1% of real tokens in aggregate; see docs/REPRODUCING.md.

    The same context_savings metadata is attached to the JSON responses of the get_impact_radius, get_review_context, detect_changes and get_architecture_overview MCP tools.

    If your editor does not support hooks (for example Cursor or OpenCode), or you want the graph kept fresh without editor integration, the daemon watches your repositories and updates their graphs. It ships with code-review-graph; no separate install.

    # 1. Register the repos to watch
    crg-daemon add ~/project-a --alias proj-a
    crg-daemon add ~/project-b
    
    # 2. Start the daemon (runs in the background)
    crg-daemon start
    
    # 3. Check on it
    crg-daemon status                 # daemon and per-repo watcher status
    crg-daemon logs --repo proj-a -f  # tail logs for one repo
    crg-daemon stop                   # stop the daemon and all watchers
    

    Also available as code-review-graph daemon start|stop|status|....

    crg-daemon add writes to ~/.code-review-graph/watch.toml, which you can also edit directly:

    [[repos]]
    path = "/home/user/project-a"
    alias = "proj-a"
    
    [[repos]]
    path = "/home/user/project-b"
    alias = "project-b"
    

    The daemon watches this file and starts or stops watcher processes as repos are added or removed. A health check every 30 seconds restarts dead watchers.

    See docs/COMMANDS.md for the full config reference.

    The assistant uses these once the graph is built.

    ToolDescription
    build_or_update_graph_toolBuild or incrementally update the graph
    run_postprocess_toolRe-run flow detection, community detection and FTS indexing
    get_minimal_context_toolCompact context (~100 tokens); call this first
    get_impact_radius_toolBlast radius of changed files
    get_review_context_toolReview context with structural summary
    query_graph_toolCallers, callees, tests, imports, inheritance queries
    traverse_graph_toolBFS/DFS traversal from any node with a token budget
    semantic_search_nodes_toolSearch code entities by name or meaning
    embed_graph_toolCompute vector embeddings for semantic search
    list_graph_stats_toolGraph size and health
    get_docs_section_toolRetrieve documentation sections
    find_large_functions_toolFunctions, classes or files above a line-count threshold
    list_flows_toolExecution flows sorted by criticality
    get_flow_toolOne execution flow
    get_affected_flows_toolFlows affected by changed files
    list_communities_toolDetected code communities
    get_community_toolOne community
    get_architecture_overview_toolArchitecture overview from community structure
    detect_changes_toolRisk-scored change impact analysis
    get_hub_nodes_toolMost-connected nodes
    get_bridge_nodes_toolChokepoints by betweenness centrality
    get_knowledge_gaps_toolStructural weaknesses and untested hotspots
    get_surprising_connections_toolUnexpected cross-community coupling
    get_suggested_questions_toolReview questions generated from the analysis
    refactor_toolRename preview, dead code detection, suggestions
    apply_refactor_toolApply a previously previewed refactoring
    generate_wiki_toolMarkdown wiki from communities
    get_wiki_page_toolOne wiki page
    list_repos_toolRegistered repositories
    cross_repo_search_toolSearch registered repositories; repos limits the search to a subset

    MCP prompts (5 workflow templates): review_changes, architecture_map, debug_issue, onboard_developer, pre_merge_check

    To exclude paths from indexing, create a .code-review-graphignore file in the repository root:

    generated/**
    *.generated.ts
    vendor/**
    node_modules/**
    

    In git repositories only tracked files are indexed (git ls-files), so gitignored files are skipped. Use .code-review-graphignore to exclude tracked files or when git is not available. The default ignore list is in docs/USAGE.md.

    Optional dependency groups:

    pip install "code-review-graph[embeddings]"          # Local vector embeddings (sentence-transformers)
    pip install "code-review-graph[google-embeddings]"   # Google Gemini embeddings
    pip install "code-review-graph[communities]"         # Community detection (igraph)
    pip install "code-review-graph[enrichment]"          # Python call-resolution enrichment (Jedi)
    pip install "code-review-graph[eval]"                # Evaluation benchmarks and SVG export (matplotlib)
    pip install "code-review-graph[wiki]"                # ollama client (not used by the current wiki generator)
    pip install "code-review-graph[all]"                 # All optional dependencies
    

    Environment Variables

    VariableDescriptionDefault
    CRG_GIT_TIMEOUTTimeout in seconds for Git operations (build, update, watch)30
    CRG_DISCOVERY_TIMEOUTTimeout in seconds for each Git command that discovers what changed, when a review tool or command was not given an explicit file list. Running out reports an error, never "no changes"5, or CRG_GIT_TIMEOUT when you set that explicitly
    CRG_DATA_DIRDirectory for graph databases and generated artefacts-
    CRG_HOOK_WORKTREESSet to 1 to let the generated git hooks run in linked git worktrees-
    CRG_EMBEDDING_MODELDefault model for local vector embeddingsall-MiniLM-L6-v2
    CRG_ACCEPT_CLOUD_EMBEDDINGSSet to 1 to suppress the cloud embedding egress warning-
    CRG_ALLOW_REMOTE_CODEAllow HuggingFace models that require trust_remote_code=True0
    CRG_VECTOR_CACHESet to 1 to keep the decoded embedding vectors in memory between semantic searches instead of reading them all back from SQLite on every query. Costs RAM (vectors × dimensions × 4 bytes per cached index) and one open read connection per cached database for the life of the process: on Windows, graph.db cannot be deleted or replaced while it is open-
    CRG_MAX_IMPACT_NODESMaximum nodes in impact analysis500
    CRG_MAX_IMPACT_DEPTHSearch depth for blast-radius analysis2
    CRG_MAX_BFS_DEPTHMaximum depth for graph traversal15
    CRG_MAX_CHANGED_FUNCSMaximum changed functions analysed in one change report500
    CRG_MAX_TRANSITIVE_FRONTIERMaximum frontier size for transitive caller/callee expansion50
    CRG_CALLER_TEST_ROUTE_DEPTHHops to walk up incoming CALLS when looking for a tested caller of an untested changed symbol. Reported as a note, never as coverage2
    CRG_CALLER_TEST_ROUTE_MAX_CALLERSMaximum callers examined while looking for that tested caller500
    CRG_TOOL_TIMEOUTTimeout in seconds for read-only MCP tools (0 disables). Does not bound the tools that write: build, postprocess, embed, wiki and apply-refactor0
    CRG_CHURN_WINDOW_DAYSWindow for detect-changes --churn commit counts90
    CRG_LEIDEN_SEEDSeed for Leiden community detection42
    CRG_RECURSE_SUBMODULESInclude git submodules when set to 1, true or yes-
    CRG_TOOLSComma-separated allowlist of MCP tools to expose when serving-
    GOOGLE_API_KEYAPI key for Google Gemini embeddings-
    MINIMAX_API_KEYAPI key for MiniMax embeddings-
    VOYAGE_API_KEYAPI key for Voyage embeddings-
    CRG_VOYAGE_MODELModel for Voyage embeddingsvoyage-code-3
    CRG_VOYAGE_OUTPUT_DIMENSIONOutput dimension for Voyage embeddings1024
    CRG_VOYAGE_OUTPUT_DTYPEOutput dtype for Voyage embeddingsfloat
    CRG_VOYAGE_BASE_URLVoyage embeddings endpointhttps://api.voyageai.com/v1
    CRG_VOYAGE_BATCH_SIZEBatch size for Voyage requests100
    CRG_VOYAGE_MIN_INTERVAL_SECMinimum delay between Voyage requests0
    CRG_OPENAI_BASE_URLOpenAI-compatible embeddings endpoint-
    CRG_OPENAI_API_KEYAPI key for OpenAI-compatible embeddings-
    CRG_OPENAI_MODELModel for OpenAI-compatible embeddings-
    CRG_OPENAI_DIMENSIONPin the embedding dimension (v3 models support reduction)-
    CRG_OPENAI_BATCH_SIZEBatch size for OpenAI-compatible requests100
    NO_COLORDisable ANSI colours in the terminal-
    CRG_SERIAL_PARSESet to 1 to disable parallel parsing (for debugging)-

    OpenAI-compatible embeddings (OpenAI, Azure, or a self-hosted gateway such as new-api, LiteLLM, vLLM, LocalAI, or Ollama in OpenAI mode) need no extra install. Set the variables and pass provider="openai" to embed_graph:

    export CRG_OPENAI_BASE_URL=http://127.0.0.1:3000/v1     # or https://api.openai.com/v1
    export CRG_OPENAI_API_KEY=sk-...
    export CRG_OPENAI_MODEL=text-embedding-3-small          # whatever your gateway serves
    # optional:
    export CRG_OPENAI_DIMENSION=1536                        # pin dim (v3 models support reduction)
    export CRG_OPENAI_BATCH_SIZE=100                        # lower for gateways with tight limits
                                                            # (e.g. Qwen text-embedding-v4 caps at 10)
    

    The cloud-egress warning is skipped when the base URL points at localhost (127.0.0.1, localhost, 0.0.0.0, ::1).

    Voyage embeddings need no extra install. Set VOYAGE_API_KEY and pass provider="voyage" to embed_graph; the default model is voyage-code-3:

    export VOYAGE_API_KEY=pa-...
    export CRG_ACCEPT_CLOUD_EMBEDDINGS=1
    code-review-graph embed --provider voyage --model voyage-code-3
    

    Model selection. Avoid -preview, -beta or -exp model IDs for an index you plan to keep; preview models can change weights (a different dimension forces a full re-embed) or be withdrawn. Prefer GA releases such as text-embedding-3-small / text-embedding-3-large (OpenAI), Qwen/Qwen3-Embedding-8B (self-hosted vLLM or LocalAI), or gemini-embedding-001 (native Gemini provider, which needs GOOGLE_API_KEY).

    The embedding text is identifiers, signatures, structural context, and a bounded first-paragraph docstring or doc-comment summary. Function bodies are not sent. Graphs created before documentation extraction was added need one full code-review-graph build before re-embedding. Routine builds never refresh embeddings; to refresh after a build, pass both --embedding-provider and --embedding-model. Cloud providers receive this source-derived text and may charge for it.

    Tool Filtering

    CRG exposes 30 MCP tools by default. To limit the server to a subset, use --tools or the CRG_TOOLS environment variable:

    # CLI flag
    code-review-graph serve --tools query_graph_tool,semantic_search_nodes_tool,detect_changes_tool
    
    # Environment variable
    CRG_TOOLS=query_graph_tool,semantic_search_nodes_tool code-review-graph serve
    

    The flag takes precedence over the variable. When neither is set, all tools are available. In an MCP client config:

    {
      "mcpServers": {
        "code-review-graph": {
          "command": "code-review-graph",
          "args": ["serve", "--tools", "query_graph_tool,semantic_search_nodes_tool,detect_changes_tool,get_review_context_tool"]
        }
      }
    }
    

    FAQ and comparisons

    Answers in docs/FAQ.md:

    Troubleshooting

    More cases, including Windows/WSL, are in docs/TROUBLESHOOTING.md.

    pip / pipx cannot download hatchling (or Errno 9 / Bad file descriptor to PyPI)

    Installing from a source tree (for example pipx install .) needs build dependencies from PyPI. If you see Could not find a version that satisfies the requirement hatchling after connection warnings, the Python in that terminal may not be able to open an HTTPS connection to pypi.org. This is seen most often in an editor's integrated terminal, and sometimes with a VPN, firewall or proxy.

    1. Run the same command from Terminal.app or iTerm instead of the editor's terminal.

    2. Install from a checkout with uv, which uses different download machinery:

      cd /path/to/code-review-graph
      uv tool install . --force
      
    3. For development in a clone, use uv sync and uv run code-review-graph ....

    To diagnose: python3 scripts/diagnose_pypi_connectivity.py. If it prints FAILED, the problem is the network environment, not the package name.

    Windows: Invalid JSON: EOF while parsing or MCP error -32000: Connection closed

    Do not use a cmd /c wrapper in the Claude Code config. Point ~/.claude.json at the .exe directly and set UTF-8 through the config:

    "code-review-graph": {
      "command": "C:\\path\\to\\your\\venv\\Scripts\\code-review-graph.exe",
      "args": ["serve", "--repo", "C:\\path\\to\\your\\project"],
      "env": { "PYTHONUTF8": "1" }
    }
    

    Contributing

    git clone https://github.com/tirth8205/code-review-graph.git
    cd code-review-graph
    python3 -m venv .venv && source .venv/bin/activate
    pip install -e ".[dev]"
    pytest
    

    Pull requests target staging (the default branch). Changes are promoted staging → testing → main, and releases are tagged from main. The first step runs once a day by itself when staging is green; promotion to main is never automatic. See CONTRIBUTING.md for the full flow.

    To add a built-in language, edit code_review_graph/parser.py: add the extension to EXTENSION_TO_LANGUAGE and node type mappings to _CLASS_TYPES, _FUNCTION_TYPES, _IMPORT_TYPES and _CALL_TYPES. Include a test fixture and open a PR. For a language you only need in one repository, use languages.toml instead.

    Licence

    MIT. See LICENSE.