code-review-graph
Memory server
Created by Tirth
Published in tirth8205/code-review-graph. Publisher page
32,711 GitHub stars
What it is
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.
AutoGineer overview, from the brain’s own files
code-review-graph is a local-first memory system designed to solve the token-heavy problem of AI code review. By parsing a repository into a structural map of functions, classes, imports, and tests using Tree-sitter, it stores the codebase as a graph in a local SQLite database. When an AI agent needs to review a change, the system calculates the blast radius—identifying only the relevant callers, dependents, and tests—and serves this compact context over the Model Context Protocol (MCP). This approach significantly reduces the token count required for agents to understand code impact, often by orders of magnitude. The system supports incremental updates via file system hooks and watch mode, ensuring the graph remains accurate without full re-parsing. It is designed for local execution, keeping data on the user's machine, and integrates directly with various AI coding tools and CLI environments.
How it works
Memory model: Hybrid
AutoGineer overview, from the brain’s own files
The system uses Tree-sitter to parse source code into an Abstract Syntax Tree (AST), which is then stored as nodes and edges in a local SQLite database. When a user requests a review or code analysis, the system queries this graph to determine the blast radius of a change. It then provides the AI agent with a minimal, relevant subset of the codebase rather than the entire repository. The graph is kept up-to-date incrementally; hooks and watch mode detect file changes, diff them, and re-parse only the affected files and their immediate dependents.
| Folder | Role | Files |
|---|---|---|
| .github | agent-config | 15 |
| docs | docs | 13 |
| hooks | hooks | 2 |
| scripts | scripts | 7 |
| skills | agent-instructions | 7 |
| tests | tests | 354 |
| .beads | folder | 9 |
| code-review-graph-vscode | folder | 32 |
| code_review_graph | folder | 103 |
| diagrams | folder | 12 |
| evaluate | folder | 24 |
The agent reads
- get_review_context_tool evidence: AGENTS.md
- query_graph_tool evidence: AGENTS.md
- skills/ evidence: README.md
- get_docs_section_tool evidence: README.md
- get_suggested_questions_tool evidence: README.md
The agent writes
- .gitignore evidence: CLAUDE.md
- .mcp.json evidence: README.md
- code_review_graph/cli.py evidence: README.md
- code_review_graph/parser.py evidence: README.md
Requirements
Apps: Docker
Runtimes: Python >=3.10
Databases: Neo4j, SQLite
API keys (by name): CRG_OPENAI_API_KEY, GITHUB_TOKEN, GOOGLE_API_KEY, MINIMAX_API_KEY, VOYAGE_API_KEY
Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Google Antigravity, Kiro, OpenCode, Amp, Roo Code, Cline, JetBrains Junie, Devin (ex-Windsurf)
Set it up
This brain runs code automatically: 3 hooks (claude-code). Review hooks/hooks.json before opening the folder in Claude Code. No step below turns a hook on for you.
hooks/hooks.json:cat >/dev/null || true; command -v code-review-graph >/dev/null 2>&1 || exit 0; git rev-parse --git-dir >/dev/null 2>&1 && code-review-graph status --repo "$(git rev-parse --show-toplevel 2>/dev/null)" || echo 'Not a git repo, skipping'hooks/hooks.json:cat >/dev/null || true; code-review-graph build >/dev/null 2>&1 &hooks/hooks.json:command -v code-review-graph >/dev/null 2>&1 && code-review-graph hook-update; cat >/dev/null || true
- Not scanned by AutoGineerIts dependencies are installed by pip or uv when you run it and were not scanned by AutoGineer (9 declared). https://pypi.org/project/code-review-graph/
Created by Tirth. Published in tirth8205/code-review-graph. Licence: MIT License.
Usage
AutoGineer overview, from the brain’s own files
- Install the tool via pip and run the install command to configure your AI coding tools.
- Build the initial knowledge graph for your project.
- Use MCP-enabled AI agents to query the graph for impact analysis, code reviews, or architectural questions.
- Rely on automatic incremental updates triggered by file changes to keep the graph in sync.
- “Build the code review graph for this project”
- The system parses the repository and initializes the SQLite graph database for use by AI agents.
- “What is the impact of changing this function?”
- The agent uses the graph to identify and present the callers, dependents, and tests affected by the change.
Documentation by Tirth
<h1 align="center">code-review-graph</h1>
<p align="center"> <a href="https://trendshift.io/repositories/23329?utm_source=repository-badge&utm_medium=badge&utm_campaign=badge-repository-23329" target="_blank" rel="noopener noreferrer"> <img src="https://trendshift.io/api/badge/repositories/23329" alt="tirth8205%2Fcode-review-graph | Trendshift" width="250" height="55" /> </a> </p>
<p align="center"> <strong>A local code knowledge graph that gives AI coding tools precise review context over MCP.</strong> </p> <p align="center"> <a href="README.md">English</a> | <a href="README.zh-CN.md">简体中文</a> | <a href="README.ja-JP.md">日本語</a> | <a href="README.ko-KR.md">한국어</a> | <a href="README.hi-IN.md">हिन्दी</a> </p>
<p align="center"> <a href="https://pypi.org/project/code-review-graph/"><img src="https://img.shields.io/pypi/v/code-review-graph?style=flat-square&color=blue" alt="PyPI"></a> <a href="https://pepy.tech/project/code-review-graph"><img src="https://img.shields.io/pepy/dt/code-review-graph?style=flat-square" alt="Downloads"></a> <a href="https://github.com/tirth8205/code-review-graph/stargazers"><img src="https://img.shields.io/github/stars/tirth8205/code-review-graph?style=flat-square" alt="Stars"></a> <a href="https://opensource.org/licenses/MIT"><img src="https://img.shields.io/badge/License-MIT-yellow.svg?style=flat-square" alt="MIT Licence"></a> <a href="https://github.com/tirth8205/code-review-graph/actions/workflows/ci.yml"><img src="https://github.com/tirth8205/code-review-graph/actions/workflows/ci.yml/badge.svg?branch=staging" alt="CI"></a> <a href="https://www.python.org/"><img src="https://img.shields.io/badge/python-3.10%2B-blue.svg?style=flat-square" alt="Python 3.10+"></a> <a href="https://modelcontextprotocol.io/"><img src="https://img.shields.io/badge/MCP-compatible-green.svg?style=flat-square" alt="MCP"></a> <a href="https://code-review-graph.com"><img src="https://img.shields.io/badge/website-code--review--graph.com-blue?style=flat-square" alt="Website"></a> <a href="https://discord.gg/3p58KXqGFN"><img src="https://img.shields.io/badge/discord-join-5865F2?style=flat-square&logo=discord&logoColor=white" alt="Discord"></a> </p>
<p align="center"> <a href="docs/USAGE.md">Usage</a> · <a href="docs/COMMANDS.md">Commands</a> · <a href="docs/FAQ.md">FAQ</a> · <a href="docs/TROUBLESHOOTING.md">Troubleshooting</a> · <a href="docs/GITHUB_ACTION.md">GitHub Action</a> · <a href="docs/REPRODUCING.md">Reproducing the benchmarks</a> · <a href="docs/ROADMAP.md">Roadmap</a> </p>
<br>
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.
<p align="center"> <img src="diagrams/diagram1_before_vs_after.png" alt="The Token Problem: reading flask's whole corpus costs 143,594 tokens, a graph answer costs 2,196 (65x fewer)" width="85%" /> </p>
What it does
Maps your code. Functions, classes, imports, calls and tests become one graph.
Shows what a change can break. The callers, dependents and tests it can reach, with a risk score.
Stays up to date. Hooks and watch mode parse again only the files that changed.
Works with your AI tools. One
installsets up each tool it finds.Stays on your machine. One SQLite file, no cloud service; cloud embeddings are opt-in.
Quick Start
Requires Python 3.10+.
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<details> <summary><strong>What <code>install</code> changes, and how to preview it first</strong></summary> <br>
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. Nothing is written until install has listed the files it will change and you have answered its question about instruction files; install --dry-run shows each change as a diff and writes nothing. Restart the editor or tool afterwards.
The files install writes, such as .claude/ and .mcp.json, stay visible to git in case your team commits them. install --gitignore adds the ones that run created to a marked block in .gitignore; uninstall removes the block.
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.
</details>
<details> <summary><strong>Every supported platform, and how to set up just one</strong></summary> <br>
<p align="center"> <img src="diagrams/diagram8_supported_platforms.png" alt="One install, every platform: detects Codex, Claude Code, CodeBuddy Code, Cursor, Windsurf, Zed, Continue, OpenCode, MiMo Code, Antigravity, Gemini CLI, Qwen Code, Qoder, Kiro, GitHub Copilot, GitHub Copilot CLI, Hermes Agent and DeepSeek Harness" width="85%" /> </p>
To configure one platform, pass --platform with one of codex, claude-code, cursor, windsurf, zed, continue, opencode, mimo, antigravity, gemini-cli, qwen, kiro, qoder, copilot, copilot-cli, codebuddy, hermes, or dsh:
code-review-graph install --platform cursor
code-review-graph install --platform codebuddyConfig file locations are listed in docs/USAGE.md. Requires Python 3.10+.
</details>
<details> <summary><strong>Remove it again with <code>uninstall</code></strong></summary> <br>
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</details>
Restart the editor or tool after install.
Then open the project and ask the assistant:
Build the code review graph for this project<details> <summary><strong>How long a build takes, and what a partial build means</strong></summary> <br>
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.
</details>
Run with Docker or Podman
<details> <summary><strong>Build the image, then run it on your repository</strong></summary> <br>
Build the image from the repository root:
docker build -t code-review-graph:local .From the repository you want to analyse, run:
docker run --rm \
--user "$(id -u):$(id -g)" \
--env HOME=/tmp \
--volume "$PWD:/workspace" \
code-review-graph:local buildThe mounted repository must be writable. The command above uses your
user and group IDs so the generated .code-review-graph/ directory
remains owned by your user. Run these commands as a non-root host user.
For Podman, build the same Dockerfile and preserve your user mapping:
podman build -t code-review-graph:local .
podman run --rm \
--userns=keep-id \
--env HOME=/tmp \
--volume "$PWD:/workspace" \
code-review-graph:local buildThe graph persists in .code-review-graph/ in the mounted repository and stores
absolute container paths such as /workspace/app.py. Run update and
detect-changes through Docker or Podman with the same /workspace mount.
A host update on this graph can fail with "built with a different repository
root". To switch to host commands, run code-review-graph build on the host
to rebuild the graph with host paths.
Replace build with status to inspect the saved graph.
The image includes Git and defaults to a non-root user.
No graph is generated during image construction.
These examples use macOS/Linux shell syntax. On macOS, start your
Docker-compatible engine or Podman machine before running them. On a host with
SELinux on, such as Fedora, add :z to the mount ("$PWD:/workspace:z"), or
the container is refused access to the repository.
</details>
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.
<details> <summary><strong>Two diagrams: how the assistant uses the graph, and the build pipeline</strong></summary> <br>
<p align="center"> <img src="diagrams/diagram7_mcp_integration_flow.png" alt="How the assistant uses the graph: the user asks for a review, the assistant calls MCP tools, the graph returns blast radius and risk scores, the assistant reads only the affected files" width="80%" /> </p>
<p align="center"> <img src="diagrams/diagram2_architecture_pipeline.png" alt="Architecture pipeline: Repository to Tree-sitter parser to SQLite graph to blast radius to minimal review set" width="100%" /> </p>
</details>
Blast-radius analysis
<details> <summary><strong>Every caller, dependent and test a change can affect</strong></summary> <br>
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.
<p align="center"> <img src="diagrams/diagram3_blast_radius.png" alt="Blast radius: a change to login() propagates to callers, dependents, and tests" width="70%" /> </p>
</details>
Incremental updates
<details> <summary><strong>Only changed files are parsed again (about 2.5 s for a two-file edit)</strong></summary> <br>
Editor hooks, 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.
<p align="center"> <img src="diagrams/diagram4_incremental_update.png" alt="Incremental update flow: a hook or watch update triggers a git diff, dependents are found through graph edges, and only files whose SHA-256 hash changed are re-parsed" width="90%" /> </p>
</details>
Whole codebase or targeted answer?
<details> <summary><strong>A slice of the graph shaped to the question, not the whole codebase</strong></summary> <br>
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.
<p align="center"> <img src="diagrams/diagram6_monorepo_funnel.png" alt="code-review-graph at the 84bde354 snapshot: 208,821 source tokens funnel down to ~3,190 token graph responses, about 65x fewer tokens per question" width="80%" /> </p>
</details>
Language coverage and notebooks
<details> <summary><strong>Python, JavaScript, TypeScript, Go, Rust, Java, C/C++, C# and many more, plus notebooks: the full list</strong></summary> <br>
<p align="center"> <img src="diagrams/diagram9_language_coverage.png" alt="Language coverage by category: Web, Backend, Systems, Mobile, Scripting, Shells, Domain, Config and Other, plus Jupyter and Databricks notebooks" width="90%" /> </p>
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 (including .mjs, .cjs, .mts and .cts), Go, Rust, Java, C/C++, C#, VB.NET, Ruby, Kotlin (.kt, .kts), 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) and dbt models, Terraform/OpenTofu (.tf, and Terraform blocks in .hcl files; an .hcl file with no Terraform blocks keeps only a file node), 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 (translation files in folders such as locales/ become file nodes only), XSLT stylesheets (.xsl, .xslt), value-free JSON structure (.json; translation, test, docs, example and data files keep only a file node, and lock files are skipped), Vue/Svelte SFCs, HTML pages (.html, .htm; inline scripts, plus div, section and article blocks with an id as DocSection nodes), Astro files (parsed with the TypeScript grammar), Jupyter and Databricks notebooks (.ipynb, plus Databricks .py exports), Perl XS files (.xs), Robot Framework files (.robot, .resource), and Liquid templates (.liquid). 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, Spring AOP advice-to-target 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.
</details>
Add your own language
<details> <summary><strong>Map a file extension to a bundled Tree-sitter grammar in <code>languages.toml</code></strong></summary> <br>
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.
</details>
Risk-scored PR reviews in CI (GitHub Action)
<details> <summary><strong>One pull request comment with risk scores, affected flows and test gaps; see the sample workflow</strong></summary> <br>
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. The optional details input adds more graph context, folded away and capped in size: why each top symbol scored what it did, the communities, hubs and cross-boundary links the change touches, its impact radius, its untested hotspots, and where the graph came from.
# .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.
</details>
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.
<details> <summary><strong>The benchmark board, and how the numbers were made</strong></summary> <br>
<p align="center"> <img src="diagrams/diagram5_benchmark_board.png" alt="Benchmarks across 6 repositories: ~63x median per-question token reduction (358x max), 0.69 average impact F1 against graph-derived ground truth" width="85%" /> </p>
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.
</details>
<details> <summary><strong>Token efficiency: ~63x median per-question reduction (range 35x to 358x; whole-corpus vs graph query)</strong></summary> <br>
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.
| Repo | Snapshot SHA | naive_corpus_tokens | avg graph_tokens | Reduction |
|---|---|---|---|---|
| fastapi | 22381558 | 948,793 | 2,653 | 357.6x |
| flask | a29f88ce | 143,594 | 2,196 | 65.4x |
| code-review-graph | 84bde354 | 208,821 | 3,190 | 65.5x |
| gin | 5c00df8a | 166,868 | 2,766 | 60.3x |
| httpx | b55d4635 | 142,356 | 2,661 | 53.5x |
| express | b4ab7d65 | 136,052 | 3,936 | 34.6x |
Captured 2026-08-02 from clean clones at the pinned SHAs (crg 2.3.7, local
all-MiniLM-L6-v2embeddings). These numbers are lower than the 2026-05-25 capture they replace: node embedding text became richer, soavg graph_tokensrose in every repo. fastapi is measured at its current pin22381558rather than the retired0227991a.The Reduction column is
naive_corpus_tokens / avg graph_tokens, so it divides out from the two columns beside it. The benchmark's ownaverage_reduction_ratioaverages the five per-question ratios instead, which always reads higher; those per-question figures are indocs/REPRODUCING.md.The
code-review-graphrow is a snapshot, not a current measurement. The repository has grown since84bde354, 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).
</details>
<details> <summary><strong>Impact accuracy: 0.69 average F1 against graph-derived ground truth (recall 1.0 is a circular upper bound)</strong></summary> <br>
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.
| Repo | Commits | Avg F1 | Avg Precision | Recall (graph-derived upper bound) |
|---|---|---|---|---|
| httpx | 2 | 0.863 | 0.785 | 1.0 |
| code-review-graph | 2 | 0.734 | 0.584 | 1.0 |
| fastapi | 2 | 0.697 | 0.539 | 1.0 |
| express | 2 | 0.667 | 0.500 | 1.0 |
| flask | 2 | 0.633 | 0.485 | 1.0 |
| gin | 3 | 0.609 | 0.439 | 1.0 |
| Average | 13 | 0.693 | 0.546 | 1.000 |
This table is from the 2026-08-02 capture, taken before the path fix described below. That bug also kept real neighbour files out of the graph-derived ground truth, so these numbers will change when the benchmark is re-run.
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, code seeds included (for example code_review_graph/cli.py and gin's context.go). The cause was a path bug in the benchmark: git diff gives repo-relative paths, the graph stores absolute ones, so the seed never matched a node. That bug is now fixed, but the benchmark has not been re-run yet, so no co-change number is quoted.
</details>
<details> <summary><strong>Build stats</strong></summary> <br>
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.
| Repo | Nodes | Edges | Embeddings |
|---|---|---|---|
| fastapi | 6,287 | 32,036 | 5,159 |
| express | 1,990 | 19,492 | 1,849 |
| gin | 1,589 | 17,237 | 1,491 |
| code-review-graph | 1,446 | 9,094 | 1,354 |
| flask | 1,415 | 8,259 | 1,329 |
| httpx | 1,263 | 8,236 | 1,193 |
</details>
Limitations
<details> <summary><strong>Five known limits: circular recall, small edits, search ranking, flow detection, false positives</strong></summary> <br>
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. Co-change numbers are not quoted until the benchmark is re-run with the path fix.
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.
</details>
Features
Updates, impact analysis, search, visualisation, CI reviews, refactoring and multi-repo support, all kept on your machine.
<details> <summary><strong>The full feature table</strong></summary> <br>
| Feature | Details |
|---|---|
| Incremental updates | Re-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 support | See Language coverage above. |
| Framework-aware PHP parsing | Repository-bounded Composer PSR-4 imports, Blade template references, evidence-gated Laravel Route-to-controller and Eloquent relationship edges |
| Framework-aware Java parsing | Spring dependency-injection call resolution, request endpoints and WebFlux routes, scheduled triggers, application-event publisher-to-listener edges, Spring AOP advice edges, Temporal workflow and activity edges, and Spring Boot config keys indexed without their values |
| Blast-radius analysis | Which functions, classes and files are likely affected by a change |
| Auto-update hooks | Editor hooks, git hooks (before each commit, after checkout, merge and rebase) and watch mode update the graph as you work |
| Semantic search | Optional vector embeddings via sentence-transformers, Google Gemini, MiniMax, Voyage AI, or any OpenAI-compatible endpoint |
| Interactive visualisation | D3.js force-directed graph with search, community legend toggles and degree-scaled nodes, plus a neighbourhood view seeded from a symbol, file, flow or change |
| Hub and bridge detection | Most-connected nodes and chokepoints (betweenness centrality) |
| Surprise scoring | Unexpected coupling: cross-community, cross-language, peripheral-to-hub edges |
| Knowledge gap analysis | Isolated nodes, untested hotspots, thin communities, import cycles |
| Suggested questions | Review questions generated from bridges, hubs and surprises |
| Edge confidence | Four tiers (EXTRACTED, INFERRED, AMBIGUOUS, UNRESOLVED) with float scores on edges, so a call the graph could not bind says so |
| Graph traversal | BFS/DFS from any node with configurable depth and token budget; path_to shows how one symbol reaches another and names the weakest hop |
| Export formats | GraphML, Neo4j Cypher, Obsidian vault, JSON, and SVG (SVG needs matplotlib from the eval extra) |
| Token benchmarking | code_review_graph/token_benchmark.py measures whole-corpus tokens against graph query tokens per question |
| Estimated context savings | context_savings metadata (estimated, saved_tokens, saved_percent) on review, impact, detect-changes and architecture responses |
| Community auto-split | Communities above 25% of the graph are split recursively with Leiden |
| Execution flows | Call chains from entry points, sorted by weighted criticality |
| Community detection | Leiden clustering with resolution scaled to graph size |
| Architecture overview | Community-based architecture map with coupling warnings |
| Risk-scored reviews | detect_changes maps diffs to affected functions, YAML and JSON paths, flows and test gaps |
| Custom languages | New languages via .code-review-graph/languages.toml, no fork needed |
| GitHub Action | Sticky risk-scored PR review comments in CI, with an optional fail-on-risk merge gate |
| Refactoring tools | Rename preview, framework-aware dead code detection, community-driven suggestions |
| Wiki generation | Markdown wiki from community structure |
| Multi-repo registry | Register several repos and search across them |
| Multi-repo daemon | crg-daemon watches several repos as child processes, with health checks and restart |
| MCP prompts | 5 workflow templates: review, architecture, debug, onboard, pre-merge |
| Full-text search | FTS5 hybrid search combining keyword and vector similarity |
| Local storage | One SQLite file in .code-review-graph/; no external database or cloud service |
</details>
Usage
Your assistant uses the graph by itself once it is built. Open a part below for skills, commands, MCP tools and settings.
<details> <summary><strong>Skills</strong></summary> <br>
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.
| Skill | Description |
|---|---|
explore-codebase | Navigate and understand codebase structure using the knowledge graph |
review-changes | Perform a structured code review using change detection and impact |
debug-issue | Systematically debug issues using graph-powered code navigation |
refactor-safely | Plan and execute safe refactoring using dependency analysis |
Qoder also gets build-graph, review-delta and review-pr from the repository's skills/ directory.
</details>
<details> <summary><strong>CLI reference</strong></summary> <br>
code-review-graph install # Detect and configure all platforms
code-review-graph install --platform <name> # One platform
code-review-graph install --steering # Claude Code: graph context beside each search and read
code-review-graph uninstall --dry-run # Preview removal of installed artifacts
code-review-graph build # Parse the whole codebase
code-review-graph build --follow-symlinks # Also index symlinked folders
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 query path_to <from> --to <to> # How one symbol reaches another
code-review-graph impact --detail-level compact # Blast radius as ranked file paths
code-review-graph visualize # Interactive HTML graph
code-review-graph visualize --seed-symbol <name> # Neighbourhood of one symbol
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 detect-changes --details all # Add graph context to the JSON
code-review-graph context-history # Trend of the opt-in savings log (CRG_CONTEXT_HISTORY=1)
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 --all # Run every evaluation benchmark
code-review-graph serve # Start the MCP server (stdio)
code-review-graph serve --http # MCP over Streamable HTTP on localhost:5555
code-review-graph serve --http --multi-repo # One HTTP server for every registered repo
code-review-graph serve --multi-worktree # One child server per linked Git worktreeThis 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.
</details>
<details> <summary><strong>Token Savings panel: <code>detect-changes --brief</code> vs <code>update --brief</code></strong></summary> <br>
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 │
└──────────────────────────────────────────────────────────────┘| Command | What it does | When to use |
|---|---|---|
detect-changes --brief | Read-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 --brief | Re-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.
To see these estimates over time, set CRG_CONTEXT_HISTORY=1 (off by default). Each estimate then adds one line to a local log next to graph.db, holding token counts, tool names, a timestamp, a detail level and file and depth counts, never file names, paths or source text, and code-review-graph context-history prints it per day or per tool. See docs/USAGE.md.
</details>
<details> <summary><strong>Multi-repo daemon</strong></summary> <br>
If install gives your editor no hooks (for example Windsurf or Zed), 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 watchersAlso 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.
</details>
<details> <summary><strong>30 MCP tools</strong></summary> <br>
The assistant uses these once the graph is built. The 25 tools that only read carry readOnlyHint: true, so a client can run them without asking; the five that write (build_or_update_graph_tool, run_postprocess_tool, embed_graph_tool, apply_refactor_tool, generate_wiki_tool) do not.
| Tool | Description |
|---|---|
build_or_update_graph_tool | Build or incrementally update the graph |
run_postprocess_tool | Re-run flow detection, community detection and FTS indexing |
get_minimal_context_tool | Compact context (~100 tokens); call this first |
get_impact_radius_tool | Blast radius of changed files; detail_level="compact" gives ranked file paths |
get_review_context_tool | Review context with structural summary |
query_graph_tool | Callers, callees, tests, imports, inheritance, and path_to between two symbols |
traverse_graph_tool | BFS/DFS traversal from any node with a token budget |
semantic_search_nodes_tool | Search code entities by name or meaning |
embed_graph_tool | Compute vector embeddings for semantic search |
list_graph_stats_tool | Graph size and health |
get_docs_section_tool | Retrieve documentation sections |
find_large_functions_tool | Functions, classes or files above a line-count threshold |
list_flows_tool | Execution flows sorted by criticality |
get_flow_tool | One execution flow |
get_affected_flows_tool | Flows affected by changed files |
list_communities_tool | Detected code communities |
get_community_tool | One community |
get_architecture_overview_tool | Architecture overview from community structure |
detect_changes_tool | Risk-scored change impact analysis |
get_hub_nodes_tool | Most-connected nodes |
get_bridge_nodes_tool | Chokepoints by betweenness centrality |
get_knowledge_gaps_tool | Structural weaknesses, untested hotspots and import cycles |
get_surprising_connections_tool | Unexpected cross-community coupling |
get_suggested_questions_tool | Review questions generated from the analysis |
refactor_tool | Rename preview, dead code detection, suggestions |
apply_refactor_tool | Apply a previously previewed refactoring |
generate_wiki_tool | Markdown wiki from communities |
get_wiki_page_tool | One wiki page |
list_repos_tool | Registered repositories |
cross_repo_search_tool | Search 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
</details>
<details> <summary><strong>Configuration</strong></summary> <br>
To exclude paths from indexing, create a .code-review-graphignore file in the repository root:
generated/**
*.generated.ts
vendor/**
node_modules/**In git repositories a build reads tracked files plus untracked files git does not ignore (git ls-files and git ls-files --others --exclude-standard), so gitignored files are skipped. Use .code-review-graphignore to exclude other 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 with Jedi (then build --enrich)
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 dependenciesEnvironment Variables
| Variable | Description | Default |
|---|---|---|
CRG_GIT_TIMEOUT | Timeout in seconds for Git operations (build, update, watch) | 30 |
CRG_DISCOVERY_TIMEOUT | Timeout 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_DIR | Directory for graph databases and generated artefacts | - |
CRG_HOOK_WORKTREES | Set to 1 to let the generated git hooks run in linked git worktrees | - |
CRG_EMBEDDING_MODEL | Default model for local vector embeddings | all-MiniLM-L6-v2 |
CRG_ACCEPT_CLOUD_EMBEDDINGS | Set to 1 to suppress the cloud embedding egress warning | - |
CRG_ALLOW_REMOTE_CODE | Allow HuggingFace models that require trust_remote_code=True | 0 |
CRG_VECTOR_CACHE | Set 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_NODES | Maximum nodes in impact analysis | 500 |
CRG_MAX_IMPACT_DEPTH | Search depth for blast-radius analysis | 2 |
CRG_MAX_BFS_DEPTH | Maximum depth for graph traversal | 15 |
CRG_MAX_CHANGED_FUNCS | Maximum changed functions analysed in one change report | 500 |
CRG_MAX_DELETION_FILES | Maximum files whose old version is read in one change report, to name the functions and classes a diff deleted | 100 |
CRG_MAX_CHANGED_YAML_PATHS | Maximum changed YAML paths analysed in one change report, and separately the same number of JSON paths | 200 |
CRG_MAX_TRANSITIVE_FRONTIER | Maximum callees followed per hop when tests_for and detect-changes look for tests. The first by name are kept, so one graph always gives one answer | 50 |
CRG_CALLER_TEST_ROUTE_DEPTH | Hops to walk up incoming CALLS when looking for a tested caller of an untested changed symbol. Reported as a note, never as coverage | 2 |
CRG_CALLER_TEST_ROUTE_MAX_CALLERS | Maximum callers examined while looking for that tested caller | 500 |
CRG_TOOL_TIMEOUT | Timeout in seconds for read-only MCP tools (0 disables). Does not bound the tools that write: build, postprocess, embed, wiki and apply-refactor | 0 |
CRG_CHURN_WINDOW_DAYS | Window for detect-changes --churn commit counts | 90 |
CRG_CONTEXT_HISTORY | Set to 1 to keep a local log of each context_savings estimate in .code-review-graph/context-history.jsonl; read it with code-review-graph context-history. Holds token counts, tool names, a timestamp, a detail level and file and depth counts, never file names, paths or source text, and is never sent anywhere | - |
CRG_LEIDEN_SEED | Seed for Leiden community detection | 42 |
CRG_RECURSE_SUBMODULES | Include git submodules when set to 1, true or yes | - |
CRG_FOLLOW_SYMLINKS | Follow symlinked folders, inside or outside the repository, when set to 1, true, yes or on; same as --follow-symlinks. See Symlinked folders | - |
CRG_MAX_FOLLOWED_FILES | Most files taken through followed symlinked folders | 10000 |
CRG_TOOLS | Comma-separated allowlist of MCP tools to expose when serving | - |
GOOGLE_API_KEY | API key for Google Gemini embeddings | - |
MINIMAX_API_KEY | API key for MiniMax embeddings | - |
VOYAGE_API_KEY | API key for Voyage embeddings | - |
CRG_VOYAGE_MODEL | Model for Voyage embeddings | voyage-code-3 |
CRG_VOYAGE_OUTPUT_DIMENSION | Output dimension for Voyage embeddings | 1024 |
CRG_VOYAGE_OUTPUT_DTYPE | Output dtype for Voyage embeddings | float |
CRG_VOYAGE_BASE_URL | Voyage embeddings endpoint | https://api.voyageai.com/v1 |
CRG_VOYAGE_BATCH_SIZE | Batch size for Voyage requests | 100 |
CRG_VOYAGE_MIN_INTERVAL_SEC | Minimum delay between Voyage requests | 0 |
CRG_OPENAI_BASE_URL | OpenAI-compatible embeddings endpoint | - |
CRG_OPENAI_API_KEY | API key for OpenAI-compatible embeddings | - |
CRG_OPENAI_MODEL | Model for OpenAI-compatible embeddings | - |
CRG_OPENAI_DIMENSION | Pin the embedding dimension (v3 models support reduction) | - |
CRG_OPENAI_BATCH_SIZE | Batch size for OpenAI-compatible requests | 100 |
NO_COLOR | Disable ANSI colours in the terminal | - |
CRG_SERIAL_PARSE | Set to 1 to disable parallel parsing (for debugging) | - |
CRG_ENABLE_ENRICHMENT | Set to 1 to resolve Python method calls with Jedi on every build and update (needs the enrichment extra; about a second more per Python file). Same as build --enrich | off |
CRG_DISABLE_ENRICHMENT | Set to 1 to never run Jedi, even when asked for | - |
OpenAI-compatible embeddings 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 limitsThe 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-3Model selection. Avoid
-preview,-betaor-expmodel 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 astext-embedding-3-small/text-embedding-3-large(OpenAI) orgemini-embedding-001(native Gemini provider, which needsGOOGLE_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 buildbefore re-embedding. Routine builds never refresh embeddings; to refresh after a build, pass both--embedding-providerand--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 serveThe 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"]
}
}
}</details>
FAQ and comparisons
Answers in docs/FAQ.md:
<details> <summary><strong>How it compares with LSP, RAG and grep, when not to use it, and more</strong></summary> <br>
vs LSP / language servers: one persistent cross-language graph instead of per-language daemons; LSP stays more precise per symbol.
vs RAG / embeddings: structural edges parsed from the AST, not similarity chunks; embeddings are optional and only assist search.
vs grep / agentic search: grep wins on one-hop lookups; the graph wins on multi-hop questions (impact radius, callers-of-callers, tests-for, affected flows).
When not to use it: small repos, trivial single-file diffs, one-off questions.
Does it phone home?: no telemetry; cloud embeddings are opt-in.
How do I verify it is working?:
status,detect-changes --brief,/mcp.
</details>
Troubleshooting
More cases, including Windows/WSL, are in docs/TROUBLESHOOTING.md.
pip / pipx cannot download hatchling (or Errno 9 / Bad file descriptor to PyPI)
<details> <summary><strong>How to fix it</strong></summary> <br>
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.
Run the same command from a terminal outside the editor, such as Terminal.app.
Install from a checkout with uv, which uses different download machinery:
cd /path/to/code-review-graph uv tool install . --forceFor development in a clone, use
uv syncanduv 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.
</details>
Windows: Invalid JSON: EOF while parsing or MCP error -32000: Connection closed
<details> <summary><strong>How to fix it</strong></summary> <br>
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" }
}</details>
Contributing
Pull requests target staging (the default branch). Changes are promoted
staging → testing → main, and releases are tagged from main. No
promotion is automatic: a person reviews and merges each one. See
CONTRIBUTING.md for the full flow.
<details> <summary><strong>Set up a development copy and run the tests</strong></summary> <br>
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</details>
<details> <summary><strong>Add a built-in language</strong></summary> <br>
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.
</details>
Licence
MIT. See LICENSE.
<p align="center"> <br> <a href="https://code-review-graph.com">code-review-graph.com</a><br><br> <code>pip install code-review-graph && code-review-graph install</code> </p>
README.ko-KR.md
<h1 align="center">code-review-graph</h1>
<p align="center"> <a href="https://trendshift.io/repositories/23329?utm_source=repository-badge&utm_medium=badge&utm_campaign=badge-repository-23329" target="_blank" rel="noopener noreferrer"> <img src="https://trendshift.io/api/badge/repositories/23329" alt="tirth8205%2Fcode-review-graph | Trendshift" width="250" height="55" /> </a> </p>
<p align="center"> <strong>MCP로 AI 코딩 도구에 정확한 리뷰 맥락을 전달하는 로컬 코드 지식 그래프.</strong> </p> <p align="center"> <a href="README.md">English</a> | <a href="README.zh-CN.md">简体中文</a> | <a href="README.ja-JP.md">日本語</a> | <a href="README.ko-KR.md">한국어</a> | <a href="README.hi-IN.md">हिन्दी</a> </p>
<p align="center"> <a href="https://pypi.org/project/code-review-graph/"><img src="https://img.shields.io/pypi/v/code-review-graph?style=flat-square&color=blue" alt="PyPI"></a> <a href="https://pepy.tech/project/code-review-graph"><img src="https://img.shields.io/pepy/dt/code-review-graph?style=flat-square" alt="Downloads"></a> <a href="https://github.com/tirth8205/code-review-graph/stargazers"><img src="https://img.shields.io/github/stars/tirth8205/code-review-graph?style=flat-square" alt="Stars"></a> <a href="https://opensource.org/licenses/MIT"><img src="https://img.shields.io/badge/License-MIT-yellow.svg?style=flat-square" alt="MIT Licence"></a> <a href="https://github.com/tirth8205/code-review-graph/actions/workflows/ci.yml"><img src="https://github.com/tirth8205/code-review-graph/actions/workflows/ci.yml/badge.svg?branch=staging" alt="CI"></a> <a href="https://www.python.org/"><img src="https://img.shields.io/badge/python-3.10%2B-blue.svg?style=flat-square" alt="Python 3.10+"></a> <a href="https://modelcontextprotocol.io/"><img src="https://img.shields.io/badge/MCP-compatible-green.svg?style=flat-square" alt="MCP"></a> <a href="https://code-review-graph.com"><img src="https://img.shields.io/badge/website-code--review--graph.com-blue?style=flat-square" alt="Website"></a> <a href="https://discord.gg/3p58KXqGFN"><img src="https://img.shields.io/badge/discord-join-5865F2?style=flat-square&logo=discord&logoColor=white" alt="Discord"></a> </p>
<p align="center"> <a href="docs/USAGE.md">사용법</a> · <a href="docs/COMMANDS.md">명령어</a> · <a href="docs/FAQ.md">FAQ</a> · <a href="docs/TROUBLESHOOTING.md">문제 해결</a> · <a href="docs/GITHUB_ACTION.md">GitHub Action</a> · <a href="docs/REPRODUCING.md">벤치마크 재현</a> · <a href="docs/ROADMAP.md">로드맵</a> </p>
<br>
AI 코딩 도구는 변경 하나를 리뷰하려고 코드베이스의 많은 부분을 다시 읽곤 합니다. code-review-graph는 Tree-sitter로 코드의 구조 지도를 만들고, 증분으로 최신 상태를 유지하며, MCP를 통해 작은 맥락을 제공합니다. 그래서 어시스턴트는 변경이 건드리는 파일만 읽습니다.
<p align="center"> <img src="diagrams/diagram1_before_vs_after.png" alt="토큰 문제: flask 전체 코퍼스를 읽으면 143,594 토큰, 그래프 응답은 2,196 토큰(65배 적음)" width="85%" /> </p>
하는 일
코드를 지도로 만듭니다. 함수, 클래스, 임포트, 호출, 테스트가 그래프 하나가 됩니다.
변경이 무엇을 깨뜨릴 수 있는지 보여 줍니다. 변경이 닿을 수 있는 호출자, 의존 대상, 테스트를 위험 점수와 함께 보여 줍니다.
늘 최신으로 유지됩니다. 훅과 watch 모드가 바뀐 파일만 다시 파싱합니다.
AI 도구와 함께 동작합니다.
install한 번으로 찾은 도구를 하나하나 설정합니다.내 컴퓨터에만 머뭅니다. SQLite 파일 하나, 클라우드 서비스 없음. 클라우드 임베딩은 직접 켜야 합니다.
빠른 시작
Python 3.10+가 필요합니다.
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<details> <summary><strong><code>install</code>이 바꾸는 것과 먼저 미리 보는 방법</strong></summary> <br>
install은 설치된 AI 코딩 도구를 찾아 각각에 MCP 서버 항목을 쓰고, 플랫폼이 지원하면 훅과 스킬을 설치하며, 플랫폼의 규칙 파일에 그래프 안내를 추가합니다. MCP 항목은 Poetry나 uv 프로젝트 환경에서는 poetry run 또는 uv run을, PATH에 uvx가 있으면 uvx code-review-graph serve를, 그 밖에는 현재 Python 인터프리터를 사용합니다. install은 바꿀 파일 목록을 보여 주고 안내 파일에 대한 질문에 답할 때까지 아무것도 쓰지 않습니다. install --dry-run은 바뀌는 내용을 파일마다 diff로 보여 주고 아무것도 쓰지 않습니다. 실행 후 편집기나 도구를 다시 시작하세요.
.claude/, .mcp.json처럼 install이 쓰는 파일은 팀이 커밋할 수도 있으므로 git에서 계속 보입니다. install --gitignore는 그 실행에서 새로 만든 파일을 .gitignore의 표시된 블록에 추가하고, uninstall은 그 블록을 지웁니다.
Codex의 경우 설치 프로그램은 전역 code-review-graph 스킬도
$CODEX_HOME/skills/code-review-graph/(기본값:
~/.codex/skills/code-review-graph/)에 둡니다. 이 스킬은 CRG MCP 도구를 먼저 쓰고,
MCP를 쓸 수 없을 때는 함께 들어 있는 읽기 전용 CLI로 넘어갑니다. 그래프가 없거나, 비어 있거나,
오래되었어도 빌드나 업데이트를 몰래 실행하지 않습니다. WSL과 Windows의 Codex
런타임은 CODEX_HOME 디렉터리와 도구 목록이 서로 다르므로, 작업을 실행할 런타임에
설치하고 갱신하세요.
</details>
<details> <summary><strong>지원하는 모든 플랫폼과 하나만 설정하는 방법</strong></summary> <br>
<p align="center"> <img src="diagrams/diagram8_supported_platforms.png" alt="한 번의 설치로 모든 플랫폼 지원: Codex, Claude Code, CodeBuddy Code, Cursor, Windsurf, Zed, Continue, OpenCode, MiMo Code, Antigravity, Gemini CLI, Qwen Code, Qoder, Kiro, GitHub Copilot, GitHub Copilot CLI, Hermes Agent, DeepSeek Harness를 감지" width="85%" /> </p>
플랫폼 하나만 설정하려면 --platform에 codex, claude-code, cursor, windsurf, zed, continue, opencode, mimo, antigravity, gemini-cli, qwen, kiro, qoder, copilot, copilot-cli, codebuddy, hermes, dsh 중 하나를 넘기세요.
code-review-graph install --platform cursor
code-review-graph install --platform codebuddy설정 파일 위치는 docs/USAGE.md에 있습니다. Python 3.10+가 필요합니다.
</details>
<details> <summary><strong><code>uninstall</code>로 다시 제거하기</strong></summary> <br>
uninstall은 Git 또는 SVN 작업 트리에서 CRG가 만든 파일과 항목을 제거하고, 다른 MCP 서버, 훅, 스킬, JSONC 주석은 건드리지 않습니다. 트리 안 어디에서든 실행할 수 있습니다. 공유 설정 파일은 원자적으로 교체되므로 쓰기가 실패해도 원본은 그대로 남습니다.
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</details>
install 뒤에는 편집기나 도구를 다시 시작하세요.
그런 다음 프로젝트를 열고 어시스턴트에게 이렇게 요청하세요.
Build the code review graph for this project<details> <summary><strong>빌드에 걸리는 시간과 부분 빌드의 뜻</strong></summary> <br>
빌드 시간은 저장소 크기에 비례합니다. 파일이 약 3,000개인 저장소의 콜드 빌드는 약 40초가 걸렸습니다(측정값). 그 뒤로는 훅과 watch 모드가 그래프를 최신으로 유지합니다. 일부 파일의 파싱이 실패하면 결과 상태가 partial이 되고 요약에 해당 파일이 나열됩니다. CLI는 stderr에 Warning: 줄도 출력하며, 그 파일들은 기존 그래프 행을 유지합니다.
</details>
Docker 또는 Podman으로 실행하기
<details> <summary><strong>이미지를 빌드한 뒤 저장소에서 실행하기</strong></summary> <br>
저장소 루트에서 이미지를 빌드합니다.
docker build -t code-review-graph:local .분석할 저장소의 디렉터리에서 다음 명령을 실행합니다.
docker run --rm \
--user "$(id -u):$(id -g)" \
--env HOME=/tmp \
--volume "$PWD:/workspace" \
code-review-graph:local build마운트한 저장소에는 쓰기 권한이 있어야 합니다.
위 명령은 현재 사용자의 사용자 ID와 그룹 ID를 사용하므로,
생성된 .code-review-graph/ 디렉터리의 소유권이 현재 사용자에게 유지됩니다.
호스트에서 root가 아닌 사용자로 이 명령들을 실행하세요.
Podman에서는 같은 Dockerfile을 빌드하고 사용자 매핑을 유지합니다.
podman build -t code-review-graph:local .
podman run --rm \
--userns=keep-id \
--env HOME=/tmp \
--volume "$PWD:/workspace" \
code-review-graph:local build그래프는 마운트한 저장소의 .code-review-graph/에 저장되며,
/workspace/app.py와 같은 컨테이너 내부의 절대 경로를 기록합니다.
update와 detect-changes는 동일한 /workspace 마운트를 사용하여 Docker 또는 Podman으로 실행하세요.
이 그래프에 대해 호스트에서 update를 실행하면 "built with a different repository root"
오류가 발생할 수 있습니다. 호스트 명령으로 전환하려면 호스트에서
code-review-graph build를 실행하여 호스트 경로로 그래프를 다시 빌드하세요.
저장된 그래프를 확인하려면 build를 status로 바꾸세요.
이미지에는 Git이 포함되어 있으며, 기본적으로 root가 아닌 사용자로 실행됩니다.
이미지를 빌드하는 동안에는 그래프를 생성하지 않습니다.
이 예제들은 macOS/Linux 셸 문법을 사용합니다.
macOS에서는 실행하기 전에 Docker 호환 엔진 또는 Podman 가상 머신을 시작하세요.
Fedora처럼 SELinux가 켜진 호스트에서는 마운트에 :z를 추가하세요("$PWD:/workspace:z"). 그렇지 않으면 컨테이너가 저장소에 접근할 수 없습니다.
</details>
동작 방식
저장소는 Tree-sitter로 AST로 파싱되어 노드(함수, 클래스, 임포트)와 엣지(호출, 상속, 테스트 커버리지)의 그래프로 저장됩니다. 리뷰 시점에는 어시스턴트가 읽어야 할 최소 파일 집합을 그래프에 질의합니다.
<details> <summary><strong>다이어그램 두 개: 어시스턴트가 그래프를 쓰는 방식과 빌드 파이프라인</strong></summary> <br>
<p align="center"> <img src="diagrams/diagram7_mcp_integration_flow.png" alt="어시스턴트가 그래프를 쓰는 흐름: 사용자가 리뷰를 요청하고, 어시스턴트가 MCP 도구를 호출하고, 그래프가 영향 범위와 위험 점수를 돌려주고, 어시스턴트는 영향받은 파일만 읽는다" width="80%" /> </p>
<p align="center"> <img src="diagrams/diagram2_architecture_pipeline.png" alt="아키텍처 파이프라인: 저장소 → Tree-sitter 파서 → SQLite 그래프 → 영향 범위 → 최소 리뷰 집합" width="100%" /> </p>
</details>
영향 범위 분석
<details> <summary><strong>변경이 영향을 줄 수 있는 모든 호출자, 의존 대상, 테스트</strong></summary> <br>
파일이 바뀌면 그래프는 영향을 받을 수 있는 모든 호출자, 의존 대상, 테스트를 추적합니다. 어시스턴트는 프로젝트 전체를 훑는 대신 그 파일들을 읽습니다.
<p align="center"> <img src="diagrams/diagram3_blast_radius.png" alt="영향 범위: login() 변경이 호출자, 의존 대상, 테스트로 퍼진다" width="70%" /> </p>
</details>
증분 업데이트
<details> <summary><strong>바뀐 파일만 다시 파싱합니다(파일 두 개 편집에 약 2.5초)</strong></summary> <br>
편집기 훅, git 훅(pre-commit, post-checkout, post-merge, post-rewrite), watch 모드가 증분 업데이트를 실행합니다. 업데이트는 변경된 파일의 diff를 구하고, 그래프의 임포트 엣지와 호출 엣지를 따라 의존 대상을 찾은 뒤, SHA-256 해시가 바뀐 파일만 다시 파싱합니다. 파일이 약 3,000개인 프로젝트(django)에서 파일 두 개를 고치면 훅 경로에서 약 2.5초 만에 재색인되며, 그중 약 1.4초는 프로세스 시작 시간입니다. 바뀐 것이 없으면 그 시작 시간만 듭니다. 증분 업데이트 지연을 참고하세요.
<p align="center"> <img src="diagrams/diagram4_incremental_update.png" alt="증분 업데이트 흐름: 훅이나 watch 업데이트가 git diff를 실행하고, 그래프 엣지로 의존 대상을 찾고, SHA-256 해시가 바뀐 파일만 다시 파싱한다" width="90%" /> </p>
</details>
코드베이스 전체인가, 겨냥한 답인가?
<details> <summary><strong>코드베이스 전체가 아니라 질문에 맞춘 그래프 조각</strong></summary> <br>
그래프는 코퍼스 전체를 모델에 넘기는 대신 질문에 맞춰 잘라낸 조각을 돌려줍니다. 이 저장소의 84bde354에 대한 2026-08-02 측정에서는 208,821개의 소스 토큰이 질문당 약 3,190 토큰이 되었습니다. 그 스냅샷 이후 저장소가 많이 커져서 오늘은 두 숫자 모두 더 큽니다.
<p align="center"> <img src="diagrams/diagram6_monorepo_funnel.png" alt="code-review-graph의 84bde354 스냅샷: 208,821개의 소스 토큰이 약 3,190 토큰의 그래프 응답으로 좁혀져, 질문당 토큰이 약 65배 줄어든다" width="80%" /> </p>
</details>
언어 지원과 노트북
<details> <summary><strong>Python, JavaScript, TypeScript, Go, Rust, Java, C/C++, C# 등 많은 언어와 노트북: 전체 목록</strong></summary> <br>
<p align="center"> <img src="diagrams/diagram9_language_coverage.png" alt="분류별 언어 지원: 웹, 백엔드, 시스템, 모바일, 스크립팅, 셸, 도메인, 설정, 기타, 그리고 Jupyter와 Databricks 노트북" width="90%" /> </p>
파서는 함수, 클래스, 임포트, 호출 지점, 상속, 테스트를 추출합니다. 문법이 있는 곳에서는 Tree-sitter를, 그 밖에는 목적에 맞춘 폴백을 씁니다. 지원: Python, JavaScript/TypeScript/TSX(.mjs, .cjs, .mts, .cts 포함), Go, Rust, Java, C/C++, C#, VB.NET, Ruby, Kotlin(.kt, .kts), Swift, PHP, Scala, Solidity, Dart, R, Perl, Lua/Luau, Objective-C, 셸 스크립트, Elixir, Zig, PowerShell, Julia, ReScript, GDScript, Nix, Verilog/SystemVerilog, SQL/PL/SQL(Oracle)과 dbt 모델, Terraform/OpenTofu(.tf, 그리고 .hcl 파일 안의 Terraform 블록. Terraform 블록이 없는 .hcl 파일은 파일 노드만 남김), Ansible YAML(플레이북, 롤, 태스크), Spring Boot 애플리케이션 설정(application.properties, application.yml, application.yaml과 그 application-<profile> 변형. 키 이름과 값의 타입만 기록하고 값은 절대 기록하지 않음), 값 없이 구조만 담는 일반 YAML(locales/ 같은 폴더의 번역 파일은 파일 노드만 생성), XSLT 스타일시트(.xsl, .xslt), 값 없이 구조만 담는 JSON(.json. 번역, 테스트, 문서, 예제, 데이터 파일은 파일 노드만 남기고 lock 파일은 건너뜀), Vue/Svelte SFC, HTML 페이지(.html, .htm. 인라인 스크립트, 그리고 id가 있는 div, section, article 블록을 DocSection 노드로), Astro 파일(TypeScript 문법으로 파싱), Jupyter와 Databricks 노트북(.ipynb, 그리고 Databricks .py 내보내기), Perl XS 파일(.xs), Robot Framework 파일(.robot, .resource), Liquid 템플릿(.liquid). 다른 .properties 파일은 소스 코드로 취급하지 않습니다.
PHP 프로젝트에는 저장소 범위로 제한된 Composer PSR-4 해석, Blade 템플릿 참조, 그리고 소스에 명시적인 프레임워크 임포트, 모델 상속, 수신자 근거가 드러날 때의 Laravel Route 및 Eloquent 엣지가 추가됩니다. routes/*.php의 정적 Laravel 라우트는 리터럴 그룹 접두사까지 포함해 Endpoint 노드와 컨트롤러로 가는 HANDLES 엣지를 만듭니다.
Java 프로젝트에는 Spring 의존성 주입 호출 해석, 요청 엔드포인트와 WebFlux 라우트, 스케줄 트리거, 애플리케이션 이벤트의 발행자에서 리스너로 가는 엣지, Spring AOP 어드바이스에서 대상으로 가는 엣지, Temporal 워크플로와 액티비티 엣지가 추가됩니다. 각 리졸버는 파싱 이후에 실행되며, 주입된 필드나 발행된 이벤트, 워크플로 스텁이 저장소 안에서 보여야 합니다.
</details>
직접 언어 추가하기
<details> <summary><strong><code>languages.toml</code>에서 파일 확장자를 함께 들어 있는 Tree-sitter 문법에 연결하기</strong></summary> <br>
파서가 다루지 않는 언어를 저장소에서 쓴다면 .code-review-graph/에 languages.toml을 추가해, 파일 확장자를 tree_sitter_language_pack에 들어 있는 아무 문법에 연결하고 함수, 클래스, 임포트, 호출의 노드 타입을 적으세요.
[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"]추출은 범용 tree-sitter 워커가 합니다. 내장 언어는 덮어쓸 수 없습니다. 스키마, 검증 규칙, 실제 예시는 docs/CUSTOM_LANGUAGES.md를 보세요.
</details>
CI에서의 위험 점수 PR 리뷰(GitHub Action)
<details> <summary><strong>위험 점수, 영향받는 흐름, 테스트 공백을 담은 풀 리퀘스트 댓글 하나. 예시 워크플로 보기</strong></summary> <br>
같은 분석이 composite GitHub Action으로도 동작합니다. 그래프는 사용자의 CI 러너에서 만들어지고 질의되며, 소스 코드가 외부 서비스로 전송되지 않습니다. 풀 리퀘스트마다 위험 점수가 매겨진 함수, 영향받는 실행 흐름, 테스트 공백을 담은 고정 댓글 하나를 남기고, 푸시할 때마다 그 자리에서 갱신합니다. 선택 입력 fail-on-risk를 쓰면 머지 게이트가 됩니다. 선택 입력 details는 그래프 맥락을 더 보여 주며, 접힌 채로 크기도 제한됩니다. 상위 심벌마다 그 점수가 나온 이유, 변경이 닿는 커뮤니티와 허브와 경계를 넘는 연결, 영향 범위, 테스트 없는 핫스팟, 그리고 그래프의 출처를 담습니다.
# .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 }}입력값, 위험 등급, 캐싱은 docs/GITHUB_ACTION.md를, 이 저장소가 스스로에게 돌리는 워크플로는 .github/workflows/pr-review.yml을 보세요.
</details>
벤치마크
저장소 6곳에서 질문당 토큰 감소의 중앙값은 약 63배입니다(코퍼스 전체 기준선 대 그래프 질의). 358배라는 최댓값은 저장소 하나(fastapi, 가장 큰 코퍼스)의 값이지 일반적인 결과가 아닙니다.
<details> <summary><strong>벤치마크 보드와 숫자를 얻은 방법</strong></summary> <br>
<p align="center"> <img src="diagrams/diagram5_benchmark_board.png" alt="저장소 6곳 벤치마크: 질문당 토큰 감소 중앙값 약 63배(최대 358배), 그래프에서 유도한 정답에 대한 영향 분석 평균 F1 0.69" width="85%" /> </p>
모든 숫자는 오픈소스 저장소 6곳(커밋 13개)에 대한 평가 러너에서 나옵니다. 모든 설정이 업스트림 SHA를 고정하고, Leiden은 고정 시드로 돌며, 임베딩은 CPU에서 결정적이므로 다른 기기에서 두 번 실행해도 같은 숫자가 나옵니다. 재현 방법은 docs/REPRODUCING.md에 있습니다. 가장 작은 설정 두 개에 대한 주간 보고 전용 실행은 .github/workflows/eval.yml에 있습니다.
</details>
<details> <summary><strong>토큰 효율: 질문당 감소 중앙값 약 63배(범위 35배에서 358배. 코퍼스 전체 대 그래프 질의)</strong></summary> <br>
전형적인 에이전트 질문("how does authentication work", "what is the main entry point" 등)에 대해 그래프는 모든 소스 파일 대신 검색 결과와 이웃 엣지로 이루어진 약 2,200에서 3,900 토큰을 돌려줍니다. 표는 code_review_graph/token_benchmark.py에 정의된 샘플 질문 5개를 평균한 값입니다.
| 저장소 | 스냅샷 SHA | naive_corpus_tokens | avg graph_tokens | 감소 배수 |
|---|---|---|---|---|
| fastapi | 22381558 | 948,793 | 2,653 | 357.6x |
| flask | a29f88ce | 143,594 | 2,196 | 65.4x |
| code-review-graph | 84bde354 | 208,821 | 3,190 | 65.5x |
| gin | 5c00df8a | 166,868 | 2,766 | 60.3x |
| httpx | b55d4635 | 142,356 | 2,661 | 53.5x |
| express | b4ab7d65 | 136,052 | 3,936 | 34.6x |
2026-08-02에 고정된 SHA의 깨끗한 클론에서 측정했습니다(crg 2.3.7, 로컬
all-MiniLM-L6-v2임베딩). 이 숫자들은 이전의 2026-05-25 측정보다 낮습니다. 노드 임베딩 텍스트가 풍부해지면서 모든 저장소에서avg graph_tokens가 올라갔기 때문입니다. fastapi는 폐기된0227991a가 아니라 현재 핀인22381558에서 측정했습니다.감소 배수 열은
naive_corpus_tokens / avg graph_tokens이므로 옆의 두 열에서 그대로 나눗셈으로 얻을 수 있습니다. 벤치마크 자체의average_reduction_ratio는 질문별 비율을 평균한 값이라 언제나 더 크게 나옵니다. 질문별 숫자는docs/REPRODUCING.md에 있습니다.
code-review-graph행은 스냅샷이며 현재 측정값이 아닙니다.84bde354이후 저장소가 커져서 코퍼스도 그래프도 오늘은 훨씬 큽니다.
코퍼스 전체 기준선은 실제 에이전트가 치르지 않는 상한입니다. 에이전트는 식별자를 grep하고 가장 잘 맞는 파일을 읽습니다. agent_baseline 평가 벤치마크가 바로 그 경우를 측정합니다(순수 파이썬으로 코퍼스를 grep하고, 일치 수 기준 상위 3개 파일을 골라, 그래프 질의 비용과 토큰을 비교). 이 현실적인 기준선에 대해 6개 저장소 18개 질문의 중앙값은 6.65x입니다(평균 14.8x, 범위 4.2x~72.6x). 2026-09-22 측정은 검색과 이 기준선이 테스트 파일의 순위를 낮추기 전의 것이므로, 다시 측정하기 전까지 code-review-graph eval --benchmark agent_baseline --embed의 결과는 이 수치와 다릅니다. 전체 표는 docs/REPRODUCING.md의 "Canonical capture, 2026-09-22" 절에 있습니다.
이 비율은 저장소 크기를 따라갑니다. 그래프 응답은 일정하게 유지되는 반면(이번에 측정한 모든 저장소에서 2,432~4,021 토큰) grep 기준선은 코퍼스와 함께 커지기 때문입니다. express는 4.5x, fastapi는 52x였습니다. 두 수치 모두 검색 비용, 즉 답을 찾는 데 필요한 토큰을 측정합니다. 에이전트가 그래프가 지목한 파일을 그다음에 연다면 그래프 비용은 대체가 아니라 추가입니다. semantic_search_nodes_tool(include_source=True)는 위치와 함께 코드를 반환해 그럴 필요를 없애지만, 이 경로를 종단 간으로 측정하는 일은 남아 있습니다.
공식 token_efficiency 벤치마크는 다른 상황을 측정합니다. 커밋의 변경 파일 내용만을 상대로 get_review_context() JSON 전체를 비교하며, 응답에 영향 범위 엣지와 소스 조각이 들어 있어 작은 커밋에서는 비율이 1보다 작게 나옵니다. 두 벤치마크는 서로 다른 질문에 답합니다. docs/REPRODUCING.md를 보세요.
리뷰와 영향 분석 도구는 응답에 작은 context_savings 추정치를 붙입니다. CLI는 같은 숫자를 Token Savings 패널에 보여 주고(아래 사용법 참고), --verify는 그 값을 OpenAI의 cl100k_base 토크나이저와 비교합니다. 샘플 파일 222개에 대한 보정 결과, 합산 기준 추정값은 실제 토큰과 약 1% 이내로 일치했습니다(데이터).
</details>
<details> <summary><strong>영향 분석 정확도: 그래프에서 유도한 정답에 대한 평균 F1 0.69(재현율 1.0은 순환 논리에 의한 상한)</strong></summary> <br>
영향 범위 분석은 평가 대상 커밋 13개 모두에서 정답에 있는 파일을 전부 찾아냈습니다. 이를 "재현율 100%"가 아니라 상한으로 읽으세요. 정답(변경된 파일과 그것을 향해 호출 엣지나 임포트 엣지를 가진 파일)은 예측기가 훑는 바로 그 그래프에서 나옵니다. 정밀도가 낮은 것은 의도한 결과입니다. 파일 하나를 더 표시하는 비용이 깨진 의존을 놓치는 비용보다 작기 때문입니다.
| 저장소 | 커밋 수 | 평균 F1 | 평균 정밀도 | 재현율(그래프에서 유도한 상한) |
|---|---|---|---|---|
| httpx | 2 | 0.863 | 0.785 | 1.0 |
| code-review-graph | 2 | 0.734 | 0.584 | 1.0 |
| fastapi | 2 | 0.697 | 0.539 | 1.0 |
| express | 2 | 0.667 | 0.500 | 1.0 |
| flask | 2 | 0.633 | 0.485 | 1.0 |
| gin | 3 | 0.609 | 0.439 | 1.0 |
| 평균 | 13 | 0.693 | 0.546 | 1.000 |
이 표는 아래에서 설명하는 경로 수정 이전에 측정한 2026-08-02 결과입니다. 그 버그는 그래프에서 유도한 정답에서도 실제 이웃 파일을 빠뜨렸으므로, 벤치마크를 다시 돌리면 이 숫자는 바뀝니다.
이 벤치마크는 동시 변경 모드도 돌립니다. 예측기에 변경 파일 하나를 주고, 같은 커밋에서 작성자가 함께 고친 다른 파일로 채점하는 방식으로, 근거가 그래프가 아니라 git 이력입니다. 두 모드 모두 결과 CSV에 나옵니다(ground_truth_mode 열). 2026-08-02 측정에서 동시 변경 모드는 코드 시드(예: code_review_graph/cli.py, gin의 context.go)를 포함해 채점한 모든 커밋에서 predicted_files = 0을 돌려주었습니다. 원인은 벤치마크의 경로 버그였습니다. git diff는 저장소 기준 상대 경로를 주는데 그래프는 절대 경로를 저장하므로, 시드가 어떤 노드와도 맞지 않았습니다. 이 버그는 이제 고쳤지만 벤치마크를 아직 다시 돌리지 않았으므로 동시 변경 수치는 인용하지 않습니다.
</details>
<details> <summary><strong>빌드 통계</strong></summary> <br>
위에 고정된 SHA에서의 같은 2026-08-02 클린 빌드 결과입니다. File 노드는 임베딩하지 않으므로 임베딩 수가 노드 수보다 적습니다. code-review-graph 행은 그 스냅샷이며 지금의 저장소 상태가 아닙니다.
| 저장소 | 노드 | 엣지 | 임베딩 |
|---|---|---|---|
| fastapi | 6,287 | 32,036 | 5,159 |
| express | 1,990 | 19,492 | 1,849 |
| gin | 1,589 | 17,237 | 1,491 |
| code-review-graph | 1,446 | 9,094 | 1,354 |
| flask | 1,415 | 8,259 | 1,329 |
| httpx | 1,263 | 8,236 | 1,193 |
</details>
한계
<details> <summary><strong>알려진 한계 다섯 가지: 순환 재현율, 작은 편집, 검색 순위, 흐름 탐지, 거짓 양성</strong></summary> <br>
영향 분석의 "재현율 1.0"은 순환 논리입니다. 과거 정답이 예측기가 따라가는 바로 그 그래프 엣지에서 나오므로, 구성상 상한일 수밖에 없습니다. 경로 수정을 반영해 벤치마크를 다시 돌릴 때까지 동시 변경 수치는 인용하지 않습니다.
작은 단일 파일 변경. 사소한 편집에서는 그래프 맥락이 파일을 그냥 읽는 것보다 클 수 있습니다. 그 차이는 여러 파일 분석을 가능하게 하는 구조 메타데이터입니다.
검색 순위. 키워드 검색은 보통 맞는 결과를 위쪽에 두지만 순위 매기기는 더 손봐야 합니다. 모듈 패턴 명명 때문에 Express 질의는 결과가 없을 수 있습니다.
흐름 탐지. 진입점 탐지는 Python과 PHP/Laravel에서 가장 강합니다. JavaScript와 Go의 흐름 탐지는 더 손봐야 합니다.
정밀도와 재현율. 영향 분석은 보수적입니다. 영향을 받을 수 있는 파일을 표시하므로 큰 의존 그래프에서는 거짓 양성이 생깁니다.
</details>
기능
업데이트, 영향 분석, 검색, 시각화, CI 리뷰, 리팩터링, 다중 저장소 지원을 모두 내 컴퓨터에서 제공합니다.
<details> <summary><strong>전체 기능 표</strong></summary> <br>
| 기능 | 내용 |
|---|---|
| 증분 업데이트 | 해시가 바뀐 파일만 다시 파싱합니다. 파일이 약 3,000개인 저장소에서 파일 두 개 편집은 훅 경로로 약 2.5초입니다(측정값). |
| 언어와 노트북 지원 | 위의 언어 지원을 보세요. |
| 프레임워크를 아는 PHP 파싱 | 저장소 범위로 제한된 Composer PSR-4 임포트, Blade 템플릿 참조, 근거에 기반한 Laravel Route에서 컨트롤러로 가는 엣지와 Eloquent 관계 엣지 |
| 프레임워크를 아는 Java 파싱 | Spring 의존성 주입 호출 해석, 요청 엔드포인트와 WebFlux 라우트, 스케줄 트리거, 애플리케이션 이벤트의 발행자에서 리스너로 가는 엣지, Spring AOP 어드바이스 엣지, Temporal 워크플로와 액티비티 엣지, 그리고 값 없이 색인되는 Spring Boot 설정 키 |
| 영향 범위 분석 | 변경으로 영향을 받을 법한 함수, 클래스, 파일 |
| 자동 업데이트 훅 | 편집기 훅, git 훅(커밋 전, 그리고 checkout, merge, rebase 후), watch 모드가 작업 중에 그래프를 갱신 |
| 시맨틱 검색 | 선택적 벡터 임베딩. sentence-transformers, Google Gemini, MiniMax, Voyage AI 또는 OpenAI 호환 엔드포인트 |
| 대화형 시각화 | D3.js force-directed 그래프. 검색, 커뮤니티 범례 토글, 차수에 따른 노드 크기, 그리고 심벌, 파일, 흐름, 변경에서 시작하는 이웃 보기 |
| 허브와 브리지 탐지 | 가장 많이 연결된 노드와 병목(매개 중심성) |
| 의외성 점수 | 예상 밖 결합: 커뮤니티 간, 언어 간, 주변부에서 허브로 가는 엣지 |
| 지식 공백 분석 | 고립 노드, 테스트 없는 핫스팟, 얇은 커뮤니티, 임포트 순환 |
| 추천 질문 | 브리지, 허브, 의외의 결합에서 만든 리뷰 질문 |
| 엣지 신뢰도 | 4단계(EXTRACTED, INFERRED, AMBIGUOUS, UNRESOLVED)와 엣지의 실수 점수. 그래프가 연결하지 못한 호출은 그렇다고 표시 |
| 그래프 순회 | 아무 노드에서 시작하는 BFS/DFS. 깊이와 토큰 예산 설정 가능. path_to는 한 심벌이 다른 심벌에 어떻게 닿는지 보여 주고 가장 약한 홉을 알려 줌 |
| 내보내기 형식 | GraphML, Neo4j Cypher, Obsidian 볼트, JSON, 그리고 SVG(SVG는 eval 엑스트라의 matplotlib 필요) |
| 토큰 벤치마크 | code_review_graph/token_benchmark.py가 질문마다 코퍼스 전체 토큰과 그래프 질의 토큰을 측정 |
| 맥락 절감 추정치 | 리뷰, 영향 분석, detect-changes, 아키텍처 응답에 붙는 context_savings 메타데이터(estimated, saved_tokens, saved_percent) |
| 커뮤니티 자동 분할 | 그래프의 25%를 넘는 커뮤니티를 Leiden으로 재귀 분할 |
| 실행 흐름 | 진입점에서 이어지는 호출 사슬을 가중 중요도로 정렬 |
| 커뮤니티 탐지 | 그래프 크기에 맞춰 해상도를 조절하는 Leiden 클러스터링 |
| 아키텍처 개요 | 커뮤니티 구조 기반 아키텍처 지도와 결합 경고 |
| 위험 점수 리뷰 | detect_changes가 diff를 영향받는 함수, YAML과 JSON 경로, 흐름, 테스트 공백에 대응 |
| 사용자 정의 언어 | .code-review-graph/languages.toml로 새 언어 추가. 포크 불필요 |
| GitHub Action | CI에서 위험 점수가 매겨진 고정 PR 리뷰 댓글. 선택적 fail-on-risk 머지 게이트 |
| 리팩터링 도구 | 이름 변경 미리보기, 프레임워크를 아는 데드 코드 탐지, 커뮤니티 기반 제안 |
| 위키 생성 | 커뮤니티 구조에서 Markdown 위키 생성 |
| 다중 저장소 레지스트리 | 여러 저장소를 등록하고 가로질러 검색 |
| 다중 저장소 데몬 | crg-daemon이 여러 저장소를 자식 프로세스로 감시. 헬스 체크와 재시작 포함 |
| MCP 프롬프트 | 워크플로 템플릿 5개: 리뷰, 아키텍처, 디버그, 온보딩, 머지 전 점검 |
| 전문 검색 | 키워드와 벡터 유사도를 결합한 FTS5 하이브리드 검색 |
| 로컬 저장 | .code-review-graph/ 안의 SQLite 파일 하나. 외부 데이터베이스나 클라우드 서비스 없음 |
</details>
사용법
그래프를 만들고 나면 어시스턴트가 알아서 씁니다. 스킬, 명령, MCP 도구, 설정은 아래 항목을 펼쳐 보세요.
<details> <summary><strong>스킬</strong></summary> <br>
install은 스킬을 지원하는 플랫폼(Claude Code, Gemini CLI, CodeBuddy Code, Hermes Agent, Qoder)에 다음 네 가지 스킬을 씁니다. 이름으로 불러 쓰세요.
| 스킬 | 내용 |
|---|---|
explore-codebase | 지식 그래프로 코드베이스 구조를 탐색하고 이해 |
review-changes | 변경 탐지와 영향 분석으로 구조화된 코드 리뷰 수행 |
debug-issue | 그래프 기반 코드 탐색으로 문제를 체계적으로 디버깅 |
refactor-safely | 의존성 분석으로 안전한 리팩터링을 계획하고 실행 |
Qoder에는 이 저장소의 skills/ 디렉터리에서 build-graph, review-delta, review-pr도 들어갑니다.
</details>
<details> <summary><strong>CLI 레퍼런스</strong></summary> <br>
code-review-graph install # Detect and configure all platforms
code-review-graph install --platform <name> # One platform
code-review-graph install --steering # Claude Code: graph context beside each search and read
code-review-graph uninstall --dry-run # Preview removal of installed artifacts
code-review-graph build # Parse the whole codebase
code-review-graph build --follow-symlinks # Also index symlinked folders
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 query path_to <from> --to <to> # How one symbol reaches another
code-review-graph impact --detail-level compact # Blast radius as ranked file paths
code-review-graph visualize # Interactive HTML graph
code-review-graph visualize --seed-symbol <name> # Neighbourhood of one symbol
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 detect-changes --details all # Add graph context to the JSON
code-review-graph context-history # Trend of the opt-in savings log (CRG_CONTEXT_HISTORY=1)
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 --all # Run every evaluation benchmark
code-review-graph serve # Start the MCP server (stdio)
code-review-graph serve --http # MCP over Streamable HTTP on localhost:5555
code-review-graph serve --http --multi-repo # One HTTP server for every registered repo
code-review-graph serve --multi-worktree # One child server per linked Git worktree이것은 일부만 고른 목록입니다. code-review-graph --help가 모든 명령을 보여 주고, docs/COMMANDS.md가 각 플래그를 설명합니다.
detect-changes --base에 브랜치 이름을 주면 diff는 그 브랜치와 HEAD의 머지 베이스를 기준으로 실행됩니다. 커밋 해시와 그 밖의 리비전은 준 그대로 쓰입니다.
visualize --format svg에는 matplotlib이 필요하며, eval 엑스트라에 들어 있습니다(pip install "code-review-graph[eval]"). 다른 내보내기 형식에는 추가 설치가 필요 없습니다.
JSON 내보내기는 로컬 그래프 데이터 디렉터리에 기록되며, 이 디렉터리는 기본으로 Git이 무시합니다. 절대 경로와 코드 구조 메타데이터가 들어갈 수 있으니 공개하기 전에 내용을 확인하세요.
</details>
<details> <summary><strong>Token Savings 패널: <code>detect-changes --brief</code>와 <code>update --brief</code></strong></summary> <br>
두 명령 모두, 변경 파일을 에이전트에게 그대로 넘길 때와 비교해 그래프가 토큰을 얼마나 아꼈는지 보여 주는 같은 패널을 출력합니다. 차이는 한 가지, 그래프를 먼저 갱신하는지 여부입니다.
┌─────────────────────── 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 │
└──────────────────────────────────────────────────────────────┘| 명령 | 하는 일 | 쓸 때 |
|---|---|---|
detect-changes --brief | 읽기 전용. 현재 변경에 대해 기존 그래프에 질의하고 패널을 출력합니다. | 대부분의 경우. 훅이나 crg-daemon이 그래프를 최신으로 유지합니다. |
update --brief | 변경 파일을 먼저 그래프에 다시 파싱한 다음 같은 패널을 출력합니다. | 리베이스 뒤, 변경 폭이 클 때, 그래프가 오래됐을 수 있을 때. |
두 명령 중 아무 쪽에나 --verify를 붙이면 숫자를 OpenAI의 cl100k_base 토크나이저와 비교합니다(pip install tiktoken 필요). 합산 기준 추정값은 실제 토큰과 약 1% 이내로 일치합니다. docs/REPRODUCING.md를 보세요.
같은 context_savings 메타데이터가 get_impact_radius, get_review_context, detect_changes, get_architecture_overview MCP 도구의 JSON 응답에도 붙습니다.
이 추정치를 시간에 따라 보려면 CRG_CONTEXT_HISTORY=1을 설정하세요(기본값은 꺼짐). 추정치마다 graph.db 옆의 로컬 로그에 한 줄이 추가되며, 토큰 수, 도구 이름, 타임스탬프, 상세 수준, 파일 수와 깊이를 담고 파일 이름, 경로, 소스 코드는 담지 않습니다. code-review-graph context-history가 날짜별 또는 도구별로 보여 줍니다. docs/USAGE.md를 참고하세요.
</details>
<details> <summary><strong>다중 저장소 데몬</strong></summary> <br>
install이 편집기에 훅을 넣어 주지 않거나(예: Windsurf, Zed) 편집기 연동 없이 그래프를 최신으로 두고 싶다면, 데몬이 저장소를 감시하며 그래프를 갱신합니다. code-review-graph에 함께 들어 있어 따로 설치할 필요가 없습니다.
# 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 watcherscode-review-graph daemon start|stop|status|...로도 쓸 수 있습니다.
crg-daemon add는 ~/.code-review-graph/watch.toml에 기록하며, 이 파일은 직접 편집해도 됩니다.
[[repos]]
path = "/home/user/project-a"
alias = "proj-a"
[[repos]]
path = "/home/user/project-b"
alias = "project-b"데몬은 이 파일을 감시하며 저장소가 추가되거나 빠질 때 감시 프로세스를 켜고 끕니다. 30초마다 도는 헬스 체크가 죽은 감시 프로세스를 다시 띄웁니다.
전체 설정 레퍼런스는 docs/COMMANDS.md를 보세요.
</details>
<details> <summary><strong>MCP 도구 30개</strong></summary> <br>
그래프를 만들고 나면 어시스턴트가 이 도구들을 씁니다. 읽기만 하는 도구 25개에는 readOnlyHint: true가 붙어 있어 클라이언트가 묻지 않고 실행할 수 있습니다. 쓰기를 하는 도구 5개(build_or_update_graph_tool, run_postprocess_tool, embed_graph_tool, apply_refactor_tool, generate_wiki_tool)에는 붙어 있지 않습니다.
| 도구 | 내용 |
|---|---|
build_or_update_graph_tool | 그래프 생성 또는 증분 갱신 |
run_postprocess_tool | 흐름 탐지, 커뮤니티 탐지, FTS 색인 재실행 |
get_minimal_context_tool | 작은 맥락(약 100 토큰). 이것을 먼저 호출 |
get_impact_radius_tool | 변경 파일의 영향 범위. detail_level="compact"는 순위를 매긴 파일 경로를 반환 |
get_review_context_tool | 구조 요약이 붙은 리뷰 맥락 |
query_graph_tool | 호출자, 피호출자, 테스트, 임포트, 상속, 그리고 두 심벌 사이의 path_to 질의 |
traverse_graph_tool | 아무 노드에서 시작하는 BFS/DFS 순회. 토큰 예산 포함 |
semantic_search_nodes_tool | 이름이나 의미로 코드 개체 검색 |
embed_graph_tool | 시맨틱 검색용 벡터 임베딩 계산 |
list_graph_stats_tool | 그래프 크기와 상태 |
get_docs_section_tool | 문서 절 가져오기 |
find_large_functions_tool | 줄 수 기준을 넘는 함수, 클래스, 파일 |
list_flows_tool | 중요도순으로 정렬한 실행 흐름 |
get_flow_tool | 실행 흐름 하나 |
get_affected_flows_tool | 변경 파일이 영향을 주는 흐름 |
list_communities_tool | 탐지된 코드 커뮤니티 |
get_community_tool | 커뮤니티 하나 |
get_architecture_overview_tool | 커뮤니티 구조 기반 아키텍처 개요 |
detect_changes_tool | 위험 점수가 매겨진 변경 영향 분석 |
get_hub_nodes_tool | 가장 많이 연결된 노드 |
get_bridge_nodes_tool | 매개 중심성 기준 병목 |
get_knowledge_gaps_tool | 구조적 약점, 테스트 없는 핫스팟, 임포트 순환 |
get_surprising_connections_tool | 예상 밖의 커뮤니티 간 결합 |
get_suggested_questions_tool | 분석에서 만든 리뷰 질문 |
refactor_tool | 이름 변경 미리보기, 데드 코드 탐지, 제안 |
apply_refactor_tool | 미리 본 리팩터링 적용 |
generate_wiki_tool | 커뮤니티에서 Markdown 위키 생성 |
get_wiki_page_tool | 위키 페이지 하나 |
list_repos_tool | 등록된 저장소 |
cross_repo_search_tool | 등록된 저장소 검색. repos로 대상을 좁힐 수 있음 |
MCP 프롬프트(워크플로 템플릿 5개):
review_changes, architecture_map, debug_issue, onboard_developer, pre_merge_check
</details>
<details> <summary><strong>설정</strong></summary> <br>
색인에서 빼고 싶은 경로가 있으면 저장소 루트에 .code-review-graphignore 파일을 만드세요.
generated/**
*.generated.ts
vendor/**
node_modules/**git 저장소에서 빌드는 추적되는 파일과, git이 무시하지 않는 추적되지 않은 파일을 읽으므로(git ls-files와 git ls-files --others --exclude-standard) gitignore된 파일은 건너뜁니다. 다른 파일을 빼거나 git을 쓸 수 없을 때 .code-review-graphignore를 쓰세요. 기본 무시 목록은 docs/USAGE.md에 있습니다.
선택적 의존성 그룹:
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 with Jedi (then build --enrich)
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환경 변수
| 변수 | 내용 | 기본값 |
|---|---|---|
CRG_GIT_TIMEOUT | Git 작업의 제한 시간(초, build / update / watch) | 30 |
CRG_DISCOVERY_TIMEOUT | 리뷰 도구나 명령에 파일 목록이 주어지지 않았을 때 변경 내용을 찾는 각 Git 명령의 제한 시간(초). 초과하면 오류를 반환하며 '변경 없음'으로 보고하지 않음 | 5(CRG_GIT_TIMEOUT을 직접 설정하면 그 값) |
CRG_DATA_DIR | 그래프 데이터베이스와 생성물이 놓이는 디렉터리 | - |
CRG_HOOK_WORKTREES | 1로 두면 생성된 git 훅이 연결된 git worktree에서도 실행 | - |
CRG_EMBEDDING_MODEL | 로컬 벡터 임베딩의 기본 모델 | all-MiniLM-L6-v2 |
CRG_ACCEPT_CLOUD_EMBEDDINGS | 1로 두면 클라우드 임베딩 전송 경고를 숨김 | - |
CRG_ALLOW_REMOTE_CODE | trust_remote_code=True가 필요한 HuggingFace 모델 허용 | 0 |
CRG_VECTOR_CACHE | 1로 두면 디코딩한 임베딩 벡터를 시맨틱 검색 사이에도 메모리에 유지해, 쿼리마다 SQLite에서 전부 다시 읽지 않음. 대신 RAM(캐시한 인덱스마다 벡터 수 × 차원 수 × 4바이트)과, 캐시한 데이터베이스마다 프로세스가 끝날 때까지 열려 있는 읽기 연결 1개를 사용함. Windows에서는 열려 있는 동안 graph.db를 삭제하거나 교체할 수 없음 | - |
CRG_MAX_IMPACT_NODES | 영향 분석에 넣는 최대 노드 수 | 500 |
CRG_MAX_IMPACT_DEPTH | 영향 범위 분석의 탐색 깊이 | 2 |
CRG_MAX_BFS_DEPTH | 그래프 순회의 최대 깊이 | 15 |
CRG_MAX_CHANGED_FUNCS | 변경 보고 하나에서 분석하는 변경 함수의 최대 수 | 500 |
CRG_MAX_DELETION_FILES | diff가 삭제한 함수와 클래스를 알려 주려고 변경 보고 하나에서 이전 버전을 읽는 파일의 최대 수 | 100 |
CRG_MAX_CHANGED_YAML_PATHS | 변경 보고 하나에서 분석하는 변경 YAML 경로의 최대 수. JSON 경로에도 따로 같은 한도가 적용됨 | 200 |
CRG_MAX_TRANSITIVE_FRONTIER | tests_for와 detect-changes가 테스트를 찾을 때 홉마다 따라가는 피호출자의 최대 수. 이름순으로 앞의 것을 남기므로 같은 그래프는 언제나 같은 답을 줌 | 50 |
CRG_CALLER_TEST_ROUTE_DEPTH | 테스트가 없는 변경 심벌에 대해 테스트된 호출자를 찾으며 들어오는 CALLS를 거슬러 올라갈 홉 수. 커버리지가 아니라 참고 정보로 보고됩니다 | 2 |
CRG_CALLER_TEST_ROUTE_MAX_CALLERS | 그 테스트된 호출자를 찾는 동안 검사할 최대 호출자 수 | 500 |
CRG_TOOL_TIMEOUT | 읽기 전용 MCP 도구의 제한 시간(초. 0이면 해제). 쓰기 작업(build / postprocess / embed / wiki / apply-refactor)에는 적용되지 않음 | 0 |
CRG_CHURN_WINDOW_DAYS | detect-changes --churn의 커밋 수를 세는 기간 | 90 |
CRG_CONTEXT_HISTORY | 1로 설정하면 각 context_savings 추정치를 로컬 로그 .code-review-graph/context-history.jsonl에 기록합니다. code-review-graph context-history로 확인합니다. 토큰 수, 도구 이름, 타임스탬프, 상세 수준, 파일 수와 깊이를 남기며 파일 이름, 경로, 소스 코드는 남기지 않고 외부로 보내지 않습니다 | - |
CRG_LEIDEN_SEED | Leiden 커뮤니티 탐지의 시드 | 42 |
CRG_RECURSE_SUBMODULES | 1, true, yes일 때 git 서브모듈 포함 | - |
CRG_FOLLOW_SYMLINKS | 1, true, yes, on일 때 심볼릭 링크 폴더(저장소 안팎)를 따라감. --follow-symlinks와 같음. 심볼릭 링크 폴더 참고 | - |
CRG_MAX_FOLLOWED_FILES | 심볼릭 링크 폴더로 가져오는 파일의 최대 수 | 10000 |
CRG_TOOLS | 서버로 띄울 때 노출할 MCP 도구의 쉼표 구분 허용 목록 | - |
GOOGLE_API_KEY | Google Gemini 임베딩의 API 키 | - |
MINIMAX_API_KEY | MiniMax 임베딩의 API 키 | - |
VOYAGE_API_KEY | Voyage 임베딩의 API 키 | - |
CRG_VOYAGE_MODEL | Voyage 임베딩의 모델 | voyage-code-3 |
CRG_VOYAGE_OUTPUT_DIMENSION | Voyage 임베딩의 출력 차원 | 1024 |
CRG_VOYAGE_OUTPUT_DTYPE | Voyage 임베딩의 출력 dtype | float |
CRG_VOYAGE_BASE_URL | Voyage 임베딩 엔드포인트 | https://api.voyageai.com/v1 |
CRG_VOYAGE_BATCH_SIZE | Voyage 요청의 배치 크기 | 100 |
CRG_VOYAGE_MIN_INTERVAL_SEC | Voyage 요청 사이의 최소 간격 | 0 |
CRG_OPENAI_BASE_URL | OpenAI 호환 임베딩 엔드포인트 | - |
CRG_OPENAI_API_KEY | OpenAI 호환 임베딩의 API 키 | - |
CRG_OPENAI_MODEL | OpenAI 호환 임베딩의 모델 | - |
CRG_OPENAI_DIMENSION | 임베딩 차원 고정(v3 모델은 축소 지원) | - |
CRG_OPENAI_BATCH_SIZE | OpenAI 호환 요청의 배치 크기 | 100 |
NO_COLOR | 터미널의 ANSI 색 끄기 | - |
CRG_SERIAL_PARSE | 1로 두면 병렬 파싱 끄기(디버깅용) | - |
CRG_ENABLE_ENRICHMENT | 1로 두면 build와 update마다 Jedi로 Python 메서드 호출 해석(enrichment 추가 기능 필요, Python 파일당 약 1초 추가). build --enrich와 같음 | 꺼짐 |
CRG_DISABLE_ENRICHMENT | 1로 두면 요청이 있어도 Jedi를 실행하지 않음 | - |
OpenAI 호환 임베딩에는 추가 설치가 필요 없습니다. 변수를 설정하고 embed_graph에 provider="openai"를 넘기세요.
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베이스 URL이 localhost(127.0.0.1, localhost, 0.0.0.0, ::1)를 가리키면 클라우드 전송 경고를 건너뜁니다.
Voyage 임베딩에도 추가 설치가 필요 없습니다. VOYAGE_API_KEY를 설정하고 embed_graph에 provider="voyage"를 넘기세요. 기본 모델은 voyage-code-3입니다.
export VOYAGE_API_KEY=pa-...
export CRG_ACCEPT_CLOUD_EMBEDDINGS=1
code-review-graph embed --provider voyage --model voyage-code-3모델 선택. 오래 유지할 색인이라면
-preview,-beta,-exp모델 ID는 피하세요. 프리뷰 모델은 가중치가 바뀌거나(차원이 달라지면 전체를 다시 임베딩해야 합니다) 내려갈 수 있습니다.text-embedding-3-small/text-embedding-3-large(OpenAI)나gemini-embedding-001(GOOGLE_API_KEY가 필요한 네이티브 Gemini 제공자) 같은 정식 출시(GA) 모델을 쓰세요.임베딩 텍스트는 식별자, 시그니처, 구조 맥락, 그리고 길이를 제한한 첫 문단의 docstring이나 문서 주석 요약입니다. 함수 본문은 보내지 않습니다. 문서 추출 기능이 들어오기 전에 만든 그래프는 다시 임베딩하기 전에
code-review-graph build를 한 번 완전히 돌려야 합니다. 일반 빌드는 임베딩을 갱신하지 않습니다. 빌드 뒤에 갱신하려면--embedding-provider와--embedding-model을 모두 넘기세요. 클라우드 제공자는 이 소스 기반 텍스트를 받고 그에 대해 요금을 매길 수 있습니다.
도구 필터링
CRG는 기본으로 MCP 도구 30개를 노출합니다. 서버를 일부로 제한하려면 --tools나 CRG_TOOLS 환경 변수를 쓰세요.
# 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플래그가 환경 변수보다 우선합니다. 둘 다 설정하지 않으면 모든 도구를 쓸 수 있습니다. MCP 클라이언트 설정에서는 이렇게 씁니다.
{
"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"]
}
}
}</details>
FAQ와 비교
답은 docs/FAQ.md에 있습니다.
<details> <summary><strong>LSP, RAG, grep과의 비교, 쓰지 않는 게 나을 때, 그 밖의 질문</strong></summary> <br>
LSP / 언어 서버와의 차이: 언어별 데몬 대신 언어를 가로지르는 영구 그래프 하나. 심볼 단위 정확도는 LSP가 더 낫습니다.
RAG / 임베딩과의 차이: 유사도 청크가 아니라 AST에서 파싱한 구조 엣지. 임베딩은 선택이고 검색을 돕는 역할만 합니다.
grep / 에이전트 검색과의 차이: 한 홉 조회는 grep이 낫고, 여러 홉 질문(영향 범위, 호출자의 호출자, tests-for, 영향받는 흐름)은 그래프가 낫습니다.
쓰지 않는 게 나을 때: 작은 저장소, 사소한 단일 파일 diff, 일회성 질문.
외부로 데이터를 보내나요?: 텔레메트리 없음. 클라우드 임베딩은 직접 켜야 합니다.
동작하는지 어떻게 확인하나요?:
status,detect-changes --brief,/mcp.
</details>
문제 해결
Windows/WSL을 포함한 더 많은 사례는 docs/TROUBLESHOOTING.md에 있습니다.
pip / pipx가 hatchling을 내려받지 못함(또는 PyPI에 대한 Errno 9 / Bad file descriptor)
<details> <summary><strong>해결 방법</strong></summary> <br>
소스 트리에서 설치할 때(예: pipx install .)는 PyPI에서 빌드 의존성을 받아야 합니다. 연결 경고 뒤에 Could not find a version that satisfies the requirement hatchling이 보인다면, 그 터미널의 Python이 pypi.org로 HTTPS 연결을 열지 못하는 것일 수 있습니다. 편집기의 통합 터미널에서 가장 자주 보이며, VPN, 방화벽, 프록시가 원인일 때도 있습니다.
편집기 밖의 터미널(예: Terminal.app)에서 같은 명령을 실행하세요.
내려받는 방식이 다른 uv로 체크아웃에서 설치하세요.
cd /path/to/code-review-graph uv tool install . --force클론에서 개발할 때는
uv sync와uv run code-review-graph ...를 쓰세요.
원인을 가리려면 python3 scripts/diagnose_pypi_connectivity.py를 실행하세요. FAILED가 나오면 문제는 패키지 이름이 아니라 네트워크 환경입니다.
</details>
Windows: Invalid JSON: EOF while parsing 또는 MCP error -32000: Connection closed
<details> <summary><strong>해결 방법</strong></summary> <br>
Claude Code 설정에서 cmd /c 래퍼를 쓰지 마세요. ~/.claude.json이 .exe를 바로 가리키게 하고 UTF-8은 설정으로 넘기세요.
"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" }
}</details>
기여하기
풀 리퀘스트는 staging(기본 브랜치)으로 보내 주세요. 변경은
staging → testing → main 순으로 올라가고, 릴리스는 main에서 태그합니다. 자동으로
올라가는 단계는 없으며, 사람이 하나하나 검토하고 머지합니다. 전체 흐름은
CONTRIBUTING.md를 보세요.
<details> <summary><strong>개발용 사본을 준비하고 테스트 실행하기</strong></summary> <br>
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</details>
<details> <summary><strong>내장 언어 추가하기</strong></summary> <br>
내장 언어를 추가하려면 code_review_graph/parser.py를 고치세요. 확장자를 EXTENSION_TO_LANGUAGE에, 노드 타입 매핑을 _CLASS_TYPES, _FUNCTION_TYPES, _IMPORT_TYPES, _CALL_TYPES에 추가하면 됩니다. 테스트 픽스처를 함께 넣어 PR을 보내 주세요. 저장소 하나에서만 필요한 언어라면 대신 languages.toml을 쓰세요.
</details>
라이선스
MIT. LICENSE를 보세요.
<p align="center"> <br> <a href="https://code-review-graph.com">code-review-graph.com</a><br><br> <code>pip install code-review-graph && code-review-graph install</code> </p>
512 files · 480 not served here
- .beads/.gitignore (not served here)
- .beads/README.md (not served here)
- .beads/config.yaml (not served here)
- .beads/hooks/post-checkout (not served here)
- .beads/hooks/post-merge (not served here)
- .beads/hooks/pre-commit (not served here)
- .beads/hooks/pre-push (not served here)
- .beads/hooks/prepare-commit-msg (not served here)
- .beads/metadata.json (not served here)
- .gitattributes (not served here)
- .github/ISSUE_TEMPLATE/bug_report.yml (not served here)
- .github/ISSUE_TEMPLATE/config.yml (not served here)
- .github/ISSUE_TEMPLATE/feature_request.yml (not served here)
- .github/ISSUE_TEMPLATE/platform_request.yml (not served here)
- .github/PULL_REQUEST_TEMPLATE.md (not served here)
- .github/copilot-instructions.md
- .github/dependabot.yml (not served here)
- .github/requirements-minimum.txt (not served here)
- .github/workflows/ci.yml (not served here)
- .github/workflows/eval.yml (not served here)
- .github/workflows/pr-review-comment.yml (not served here)
- .github/workflows/pr-review.yml (not served here)
- .github/workflows/promote.yml (not served here)
- .github/workflows/promotion-gate.yml (not served here)
- .github/workflows/publish.yml (not served here)
- .gitignore (not served here)
- .mcp.json
- AGENTS.md
- ATTRIBUTION.md
- AUTOGINEER-RUNS.md
- CHANGELOG.md
- CLAUDE.md
- CODE_OF_CONDUCT.md
- CONTRIBUTING.md
- Dockerfile (not served here)
- GEMINI.md
- LICENSE
- README.hi-IN.md
- README.ja-JP.md
- README.ko-KR.md
- README.md
- README.zh-CN.md
- SECURITY.md
- action.yml (not served here)
- code-review-graph-vscode/.gitignore (not served here)
- code-review-graph-vscode/.vscodeignore (not served here)
- code-review-graph-vscode/CHANGELOG.md (not served here)
- code-review-graph-vscode/LICENSE
- code-review-graph-vscode/README.md (not served here)
- code-review-graph-vscode/esbuild.mjs (not served here)
- code-review-graph-vscode/media/icons/graph.svg (not served here)
- code-review-graph-vscode/media/icons/icon.png (not served here)
- code-review-graph-vscode/media/walkthrough/build.md (not served here)
- code-review-graph-vscode/media/walkthrough/explore.md (not served here)
- code-review-graph-vscode/media/walkthrough/install.md (not served here)
- code-review-graph-vscode/package-lock.json (not served here)
- code-review-graph-vscode/package.json (not served here)
- code-review-graph-vscode/src/backend/cli.ts (not served here)
- code-review-graph-vscode/src/backend/sqlite.ts (not served here)
- code-review-graph-vscode/src/backend/watcher.ts (not served here)
- code-review-graph-vscode/src/extension.ts (not served here)
- code-review-graph-vscode/src/features/blastRadius.ts (not served here)
- code-review-graph-vscode/src/features/cursorResolver.ts (not served here)
- code-review-graph-vscode/src/features/navigation.ts (not served here)
- code-review-graph-vscode/src/features/reviewAssistant.ts (not served here)
- code-review-graph-vscode/src/features/scmDecorations.ts (not served here)
- code-review-graph-vscode/src/features/search.ts (not served here)
- code-review-graph-vscode/src/onboarding/installer.ts (not served here)
- code-review-graph-vscode/src/onboarding/welcome.ts (not served here)
- code-review-graph-vscode/src/views/graphWebview.ts (not served here)
- code-review-graph-vscode/src/views/statusBar.ts (not served here)
- code-review-graph-vscode/src/views/treeItems.ts (not served here)
- code-review-graph-vscode/src/views/treeView.ts (not served here)
- code-review-graph-vscode/src/webview/graph.ts (not served here)
- code-review-graph-vscode/test/sqlite.test.ts (not served here)
- code-review-graph-vscode/tsconfig.json (not served here)
- code_review_graph/__init__.py (not served here)
- code_review_graph/__main__.py (not served here)
- code_review_graph/_legacy_instructions.py (not served here)
- code_review_graph/analysis.py (not served here)
- code_review_graph/aop_resolver.py (not served here)
- code_review_graph/assets/code-review-graph/SKILL.md (not served here)
- code_review_graph/assets/code-review-graph/agents/openai.yaml (not served here)
- code_review_graph/assets/code-review-graph/scripts/crg_readonly.py (not served here)
- code_review_graph/assets/d3.v7.min.js (not served here)
- code_review_graph/build_state.py (not served here)
- code_review_graph/change_details.py (not served here)
- code_review_graph/changes.py (not served here)
- code_review_graph/cli.py (not served here)
- code_review_graph/codex_skill.py (not served here)
- code_review_graph/communities.py (not served here)
- code_review_graph/config_keys.py (not served here)
- code_review_graph/constants.py (not served here)
- code_review_graph/context_history.py (not served here)
- code_review_graph/context_savings.py (not served here)
- code_review_graph/csharp_resolver.py (not served here)
- code_review_graph/custom_languages.py (not served here)
- code_review_graph/daemon.py (not served here)
- code_review_graph/daemon_cli.py (not served here)
- code_review_graph/docs/LLM-OPTIMIZED-REFERENCE.md (not served here)
- code_review_graph/dsh.py (not served here)
- code_review_graph/embeddings.py (not served here)
- code_review_graph/enrich.py (not served here)
- code_review_graph/errors.py (not served here)
- code_review_graph/eval/__init__.py (not served here)
- code_review_graph/eval/benchmarks/__init__.py (not served here)
- code_review_graph/eval/benchmarks/agent_baseline.py (not served here)
- code_review_graph/eval/benchmarks/build_performance.py (not served here)
- code_review_graph/eval/benchmarks/flow_completeness.py (not served here)
- code_review_graph/eval/benchmarks/impact_accuracy.py (not served here)
- code_review_graph/eval/benchmarks/incremental_fidelity.py (not served here)
- code_review_graph/eval/benchmarks/multi_hop_retrieval.py (not served here)
- code_review_graph/eval/benchmarks/search_quality.py (not served here)
- code_review_graph/eval/benchmarks/token_efficiency.py (not served here)
- code_review_graph/eval/configs/code-review-graph.yaml (not served here)
- code_review_graph/eval/configs/express.yaml (not served here)
- code_review_graph/eval/configs/fastapi.yaml (not served here)
- code_review_graph/eval/configs/flask.yaml (not served here)
- code_review_graph/eval/configs/gin.yaml (not served here)
- code_review_graph/eval/configs/httpx.yaml (not served here)
- code_review_graph/eval/reporter.py (not served here)
- code_review_graph/eval/runner.py (not served here)
- code_review_graph/eval/scorer.py (not served here)
- code_review_graph/eval/token_benchmark.py (not served here)
- code_review_graph/event_resolver.py (not served here)
- code_review_graph/exports.py (not served here)
- code_review_graph/flows.py (not served here)
- code_review_graph/forget.py (not served here)
- code_review_graph/graph.py (not served here)
- code_review_graph/graph_diff.py (not served here)
- code_review_graph/hcl_resolver.py (not served here)
- code_review_graph/hints.py (not served here)
- code_review_graph/hook_update.py (not served here)
- code_review_graph/http_origin_guard.py (not served here)
- code_review_graph/incremental.py (not served here)
- code_review_graph/inheritance.py (not served here)
- code_review_graph/install_gitignore.py (not served here)
- code_review_graph/install_plan.py (not served here)
- code_review_graph/jedi_resolver.py (not served here)
- code_review_graph/jsonc.py (not served here)
- code_review_graph/locking.py (not served here)
- code_review_graph/main.py (not served here)
- code_review_graph/memory.py (not served here)
- code_review_graph/migrations.py (not served here)
- code_review_graph/multi_worktree.py (not served here)
- code_review_graph/neighbourhood.py (not served here)
- code_review_graph/npm_alias_resolver.py (not served here)
- code_review_graph/parser.py (not served here)
- code_review_graph/postprocessing.py (not served here)
- code_review_graph/prompts.py (not served here)
- code_review_graph/python_resolver.py (not served here)
- code_review_graph/refactor.py (not served here)
- code_review_graph/registry.py (not served here)
- code_review_graph/rescript_resolver.py (not served here)
- code_review_graph/scoped_resolver.py (not served here)
- code_review_graph/search.py (not served here)
- code_review_graph/skills.py (not served here)
- code_review_graph/spring_resolver.py (not served here)
- code_review_graph/stdio.py (not served here)
- code_review_graph/temporal_resolver.py (not served here)
- code_review_graph/token_benchmark.py (not served here)
- code_review_graph/tools/__init__.py (not served here)
- code_review_graph/tools/_common.py (not served here)
- code_review_graph/tools/analysis_tools.py (not served here)
- code_review_graph/tools/build.py (not served here)
- code_review_graph/tools/community_tools.py (not served here)
- code_review_graph/tools/context.py (not served here)
- code_review_graph/tools/docs.py (not served here)
- code_review_graph/tools/flows_tools.py (not served here)
- code_review_graph/tools/query.py (not served here)
- code_review_graph/tools/refactor_tools.py (not served here)
- code_review_graph/tools/registry_tools.py (not served here)
- code_review_graph/tools/review.py (not served here)
- code_review_graph/tsconfig_resolver.py (not served here)
- code_review_graph/uncertainty.py (not served here)
- code_review_graph/uninstall.py (not served here)
- code_review_graph/visualization.py (not served here)
- code_review_graph/wiki.py (not served here)
- code_review_graph/workspace_resolver.py (not served here)
- diagrams/context-savings-demo.gif (not served here)
- diagrams/context-savings-demo.tape (not served here)
- diagrams/diagram1_before_vs_after.png (not served here)
- diagrams/diagram2_architecture_pipeline.png (not served here)
- diagrams/diagram3_blast_radius.png (not served here)
- diagrams/diagram4_incremental_update.png (not served here)
- diagrams/diagram5_benchmark_board.png (not served here)
- diagrams/diagram6_monorepo_funnel.png (not served here)
- diagrams/diagram7_mcp_integration_flow.png (not served here)
- diagrams/diagram8_supported_platforms.png (not served here)
- diagrams/diagram9_language_coverage.png (not served here)
- diagrams/generate_diagrams.py (not served here)
- docs/COMMANDS.md
- docs/CUSTOM_LANGUAGES.md
- docs/FAQ.md
- docs/FEATURES.md
- docs/GITHUB_ACTION.md
- docs/INDEX.md
- docs/LEGAL.md
- docs/REPRODUCING.md
- docs/ROADMAP.md
- docs/TROUBLESHOOTING.md
- docs/USAGE.md
- docs/architecture.md
- docs/schema.md
- evaluate/results/code-review-graph_agent_baseline_2026-09-22.csv (not served here)
- evaluate/results/code-review-graph_impact_accuracy_2026-08-02.csv (not served here)
- evaluate/results/code-review-graph_multi_hop_retrieval_2026-05-25.csv (not served here)
- evaluate/results/code-review-graph_token_efficiency_2026-05-25.csv (not served here)
- evaluate/results/express_agent_baseline_2026-09-22.csv (not served here)
- evaluate/results/express_impact_accuracy_2026-08-02.csv (not served here)
- evaluate/results/express_multi_hop_retrieval_2026-05-25.csv (not served here)
- evaluate/results/express_token_efficiency_2026-05-25.csv (not served here)
- evaluate/results/fastapi_agent_baseline_2026-09-22.csv (not served here)
- evaluate/results/fastapi_impact_accuracy_2026-08-02.csv (not served here)
- evaluate/results/fastapi_multi_hop_retrieval_2026-05-25.csv (not served here)
- evaluate/results/fastapi_token_efficiency_2026-05-25.csv (not served here)
- evaluate/results/flask_agent_baseline_2026-09-22.csv (not served here)
- evaluate/results/flask_impact_accuracy_2026-08-02.csv (not served here)
- evaluate/results/flask_multi_hop_retrieval_2026-05-25.csv (not served here)
- evaluate/results/flask_token_efficiency_2026-05-25.csv (not served here)
- evaluate/results/gin_agent_baseline_2026-09-22.csv (not served here)
- evaluate/results/gin_impact_accuracy_2026-08-02.csv (not served here)
- evaluate/results/gin_multi_hop_retrieval_2026-05-25.csv (not served here)
- evaluate/results/gin_token_efficiency_2026-05-25.csv (not served here)
- evaluate/results/httpx_agent_baseline_2026-09-22.csv (not served here)
- evaluate/results/httpx_impact_accuracy_2026-08-02.csv (not served here)
- evaluate/results/httpx_multi_hop_retrieval_2026-05-25.csv (not served here)
- evaluate/results/httpx_token_efficiency_2026-05-25.csv (not served here)
- hooks/hooks.json
- hooks/session-start.sh (not served here)
- pyproject.toml (not served here)
- scripts/audit_python_imports.py (not served here)
- scripts/diagnose_pypi_connectivity.py (not served here)
- scripts/generate_documentary_skills.py (not served here)
- scripts/print_minimum_dependencies.py (not served here)
- scripts/promotion_gate.py (not served here)
- scripts/render_pr_comment.py (not served here)
- scripts/smoke_google_embeddings.py (not served here)
- skills/build-graph/SKILL.md (not served here)
- skills/debug-issue/SKILL.md (not served here)
- skills/explore-codebase/SKILL.md (not served here)
- skills/refactor-safely/SKILL.md (not served here)
- skills/review-changes/SKILL.md (not served here)
- skills/review-delta/SKILL.md (not served here)
- skills/review-pr/SKILL.md (not served here)
- tests/__init__.py (not served here)
- tests/conftest.py (not served here)
- tests/corpus_baselines.json (not served here)
- tests/determinism_build_runner.py (not served here)
- tests/determinism_dump.py (not served here)
- tests/fixtures/KafkaPatterns.java (not served here)
- tests/fixtures/MarkdownMsg.tsx (not served here)
- tests/fixtures/Sample.cs (not served here)
- tests/fixtures/SampleJava.java (not served here)
- tests/fixtures/SpringDI.java (not served here)
- tests/fixtures/TemporalWorkflow.java (not served here)
- tests/fixtures/__tests__/UserService.ts (not served here)
- tests/fixtures/alias_importer.ts (not served here)
- tests/fixtures/caller_example.py (not served here)
- tests/fixtures/cpp_qt_headers/MyWidget.cpp (not served here)
- tests/fixtures/cpp_qt_headers/MyWidget.h (not served here)
- tests/fixtures/cpp_qt_headers/MyWidgetPlain.cpp (not served here)
- tests/fixtures/cpp_qt_headers/MyWidgetPlain.h (not served here)
- tests/fixtures/detect_changes_sample.json (not served here)
- tests/fixtures/graphml_xsd/SOURCE.txt (not served here)
- tests/fixtures/graphml_xsd/graphml-attributes.xsd (not served here)
- tests/fixtures/graphml_xsd/graphml-parseinfo.xsd (not served here)
- tests/fixtures/graphml_xsd/graphml-structure.xsd (not served here)
- tests/fixtures/graphml_xsd/graphml.xsd (not served here)
- tests/fixtures/graphml_xsd/xlink.xsd (not served here)
- tests/fixtures/multi_call_example.py (not served here)
- tests/fixtures/playbooks/sample_ansible_playbook.yml (not served here)
- tests/fixtures/roles/myrole/meta/main.yml (not served here)
- tests/fixtures/sample.R (not served here)
- tests/fixtures/sample.c (not served here)
- tests/fixtures/sample.cpp (not served here)
- tests/fixtures/sample.dart (not served here)
- tests/fixtures/sample.ex (not served here)
- tests/fixtures/sample.gd (not served here)
- tests/fixtures/sample.hh (not served here)
- tests/fixtures/sample.jl (not served here)
- tests/fixtures/sample.kt (not served here)
- tests/fixtures/sample.liquid (not served here)
- tests/fixtures/sample.lua (not served here)
- tests/fixtures/sample.luau (not served here)
- tests/fixtures/sample.m (not served here)
- tests/fixtures/sample.nix (not served here)
- tests/fixtures/sample.php (not served here)
- tests/fixtures/sample.pl (not served here)
- tests/fixtures/sample.rb (not served here)
- tests/fixtures/sample.res (not served here)
- tests/fixtures/sample.resi (not served here)
- tests/fixtures/sample.scala (not served here)
- tests/fixtures/sample.sh (not served here)
- tests/fixtures/sample.sol (not served here)
- tests/fixtures/sample.sql (not served here)
- tests/fixtures/sample.sv (not served here)
- tests/fixtures/sample.swift (not served here)
- tests/fixtures/sample.tf (not served here)
- tests/fixtures/sample.xs (not served here)
- tests/fixtures/sample_bun.test.ts (not served here)
- tests/fixtures/sample_callback_refs.py (not served here)
- tests/fixtures/sample_config.json (not served here)
- tests/fixtures/sample_databricks_export.py (not served here)
- tests/fixtures/sample_databricks_notebook.ipynb (not served here)
- tests/fixtures/sample_dead_guard.c (not served here)
- tests/fixtures/sample_dead_guard.go (not served here)
- tests/fixtures/sample_dead_guard.rs (not served here)
- tests/fixtures/sample_dead_guard.ts (not served here)
- tests/fixtures/sample_dead_guard_impl.rs (not served here)
- tests/fixtures/sample_go.go (not served here)
- tests/fixtures/sample_html.html (not served here)
- tests/fixtures/sample_lib.sh (not served here)
- tests/fixtures/sample_map_dispatch.py (not served here)
- tests/fixtures/sample_map_dispatch.ts (not served here)
- tests/fixtures/sample_mocha.test.ts (not served here)
- tests/fixtures/sample_module.nix (not served here)
- tests/fixtures/sample_notebook.ipynb (not served here)
- tests/fixtures/sample_plsql.sql (not served here)
- tests/fixtures/sample_python.py (not served here)
- tests/fixtures/sample_rust.rs (not served here)
- tests/fixtures/sample_typescript.ts (not served here)
- tests/fixtures/sample_vitest.test.ts (not served here)
- tests/fixtures/sample_vue.vue (not served here)
- tests/fixtures/sample_xslt.xsl (not served here)
- tests/fixtures/sample_xslt_common.xsl (not served here)
- tests/fixtures/sample_zig.zig (not served here)
- tests/fixtures/sample_zig_util.zig (not served here)
- tests/fixtures/src/lib/utils.ts (not served here)
- tests/fixtures/tasks/sample_ansible_tasks.yml (not served here)
- tests/fixtures/test_sample.R (not served here)
- tests/fixtures/test_sample.py (not served here)
- tests/fixtures/tsconfig.json (not served here)
- tests/import_audit.py (not served here)
- tests/mcp_client_compat.py (not served here)
- tests/real_repo_corpus.py (not served here)
- tests/test_action_e2e.py (not served here)
- tests/test_action_render.py (not served here)
- tests/test_affected_flows_limits.py (not served here)
- tests/test_agent_transparency.py (not served here)
- tests/test_ansible_parser.py (not served here)
- tests/test_aop_resolution_edge_cases.py (not served here)
- tests/test_aop_resolver.py (not served here)
- tests/test_build_tool_errors.py (not served here)
- tests/test_call_site_provenance.py (not served here)
- tests/test_callback_context_preservation.py (not served here)
- tests/test_change_details.py (not served here)
- tests/test_changes.py (not served here)
- tests/test_changes_path_normalization.py (not served here)
- tests/test_churn_runtime.py (not served here)
- tests/test_cjs_and_kts_extensions.py (not served here)
- tests/test_cli.py (not served here)
- tests/test_cli_install.py (not served here)
- tests/test_cli_reconciliation.py (not served here)
- tests/test_cli_stdio_encoding.py (not served here)
- tests/test_cli_surface.py (not served here)
- tests/test_cli_tool_commands.py (not served here)
- tests/test_codeql_url_substring.py (not served here)
- tests/test_codex_skill_wrapper.py (not served here)
- tests/test_commonjs_imports.py (not served here)
- tests/test_communities.py (not served here)
- tests/test_compact_impact.py (not served here)
- tests/test_composer_vendor_ignore.py (not served here)
- tests/test_concurrency_and_daemon.py (not served here)
- tests/test_conftest_gates.py (not served here)
- tests/test_context_history.py (not served here)
- tests/test_context_savings.py (not served here)
- tests/test_cpp_header_prefilter.py (not served here)
- tests/test_cpp_overload_identity.py (not served here)
- tests/test_cpp_qt_headers.py (not served here)
- tests/test_csharp_dead_code_overrides.py (not served here)
- tests/test_csharp_dotted_query_targets.py (not served here)
- tests/test_csharp_namespace_binding_edges.py (not served here)
- tests/test_csharp_namespaces.py (not served here)
- tests/test_custom_languages.py (not served here)
- tests/test_d3_asset_line_endings.py (not served here)
- tests/test_daemon.py (not served here)
- tests/test_daemon_cli_followups.py (not served here)
- tests/test_daemon_stop_confirmation.py (not served here)
- tests/test_daemon_stop_escalation.py (not served here)
- tests/test_dbt_parser.py (not served here)
- tests/test_dead_code_edge_evidence.py (not served here)
- tests/test_dead_code_query_scaling.py (not served here)
- tests/test_dependency_floors.py (not served here)
- tests/test_derived_data_fallbacks.py (not served here)
- tests/test_determinism.py (not served here)
- tests/test_diagnose_pypi_connectivity.py (not served here)
- tests/test_docstring_embeddings.py (not served here)
- tests/test_document_skills.py (not served here)
- tests/test_documentation.py (not served here)
- tests/test_dsh.py (not served here)
- tests/test_e2e_mcp_client.py (not served here)
- tests/test_e2e_real_repo.py (not served here)
- tests/test_edit_hook_follows_the_edited_file.py (not served here)
- tests/test_elixir_multi_clause.py (not served here)
- tests/test_embedding_initialization.py (not served here)
- tests/test_embedding_refresh.py (not served here)
- tests/test_embedding_refresh_skip_notice.py (not served here)
- tests/test_embeddings.py (not served here)
- tests/test_enrich.py (not served here)
- tests/test_env_config.py (not served here)
- tests/test_eval.py (not served here)
- tests/test_export_formats.py (not served here)
- tests/test_failure_reporting.py (not served here)
- tests/test_flow_source_stays_in_repo.py (not served here)
- tests/test_flows.py (not served here)
- tests/test_follow_symlinks.py (not served here)
- tests/test_forget.py (not served here)
- tests/test_forget_legacy_db.py (not served here)
- tests/test_forget_parity.py (not served here)
- tests/test_freshness_metadata.py (not served here)
- tests/test_fts_delta.py (not served here)
- tests/test_fts_sync.py (not served here)
- tests/test_genai_packaging.py (not served here)
- tests/test_generic_yaml_edge_cases.py (not served here)
- tests/test_git_hook_block_helpers.py (not served here)
- tests/test_git_hook_worktree.py (not served here)
- tests/test_git_sync_hooks.py (not served here)
- tests/test_go_embeddings.py (not served here)
- tests/test_go_imports.py (not served here)
- tests/test_go_receiver_resolution.py (not served here)
- tests/test_graph.py (not served here)
- tests/test_graph_update_contracts.py (not served here)
- tests/test_hcl_parser.py (not served here)
- tests/test_hcl_provider_aliases.py (not served here)
- tests/test_header_dead_branch_scan.py (not served here)
- tests/test_hermes_install.py (not served here)
- tests/test_hermes_yaml_preservation.py (not served here)
- tests/test_hints.py (not served here)
- tests/test_hook_update.py (not served here)
- tests/test_html_parser.py (not served here)
- tests/test_http_multi_repo.py (not served here)
- tests/test_http_origin_guard.py (not served here)
- tests/test_identity_pending_ignored.py (not served here)
- tests/test_identity_retry.py (not served here)
- tests/test_import_cycles.py (not served here)
- tests/test_import_scope.py (not served here)
- tests/test_import_target_integrity.py (not served here)
- tests/test_incremental.py (not served here)
- tests/test_incremental_dependent_derived_state.py (not served here)
- tests/test_incremental_fidelity.py (not served here)
- tests/test_incremental_flow_lifecycle.py (not served here)
- tests/test_incremental_reexport_regression.py (not served here)
- tests/test_incremental_unindexed_change_memory.py (not served here)
- tests/test_inherited_calls.py (not served here)
- tests/test_install_gitignore_block.py (not served here)
- tests/test_install_outputs_are_ignored.py (not served here)
- tests/test_install_preview.py (not served here)
- tests/test_installer_ownership.py (not served here)
- tests/test_integration_git.py (not served here)
- tests/test_integration_v2.py (not served here)
- tests/test_java_call_references.py (not served here)
- tests/test_java_name_extraction.py (not served here)
- tests/test_js_module_resolution.py (not served here)
- tests/test_js_wrapped_functions.py (not served here)
- tests/test_json_parser.py (not served here)
- tests/test_jsonc_removals.py (not served here)
- tests/test_julia_reconciliation.py (not served here)
- tests/test_jvm_implementors.py (not served here)
- tests/test_keyword_argument_callbacks.py (not served here)
- tests/test_kotlin_import_comments.py (not served here)
- tests/test_kotlin_imports.py (not served here)
- tests/test_language_reconciliation.py (not served here)
- tests/test_legacy_graph_paths.py (not served here)
- tests/test_liquid.py (not served here)
- tests/test_main.py (not served here)
- tests/test_main_lazy_tool_imports.py (not served here)
- tests/test_mcp_auto_watch.py (not served here)
- tests/test_mcp_auto_watch_startup_window.py (not served here)
- tests/test_mcp_stdio_shutdown.py (not served here)
- tests/test_mcp_surface.py (not served here)
- tests/test_mcp_watch_store_shutdown.py (not served here)
- tests/test_memory.py (not served here)
- tests/test_migrations.py (not served here)
- tests/test_missing_registered_data_dir.py (not served here)
- tests/test_multi_worktree.py (not served here)
- tests/test_multilang.py (not served here)
- tests/test_neighbourhood.py (not served here)
- tests/test_neighbourhood_bounded_reads.py (not served here)
- tests/test_neighbourhood_browser.py (not served here)
- tests/test_nested_method_identities.py (not served here)
- tests/test_nested_scope_upgrade.py (not served here)
- tests/test_notebook.py (not served here)
- tests/test_npm_alias_resolver.py (not served here)
- tests/test_opencode_v1_plugin_contract.py (not served here)
- tests/test_opencode_v2_plugin_contract.py (not served here)
- tests/test_optional_dependencies.py (not served here)
- tests/test_packaging.py (not served here)
- tests/test_parser.py (not served here)
- tests/test_parser_grammar_contract.py (not served here)
- tests/test_parser_load_probe.py (not served here)
- tests/test_php_guessed_test_links.py (not served here)
- tests/test_php_includes.py (not served here)
- tests/test_php_laravel.py (not served here)
- tests/test_php_scoped_calls.py (not served here)
- tests/test_platform_lifecycle.py (not served here)
- tests/test_postprocessing.py (not served here)
- tests/test_powershell_extraction.py (not served here)
- tests/test_pr803_poisoned_graph_recovery.py (not served here)
- tests/test_pr_review_workflows.py (not served here)
- tests/test_promotion_gate.py (not served here)
- tests/test_promotion_is_manual.py (not served here)
- tests/test_prompts.py (not served here)
- tests/test_public_tool_hints.py (not served here)
- tests/test_pure_deletion_review.py (not served here)
- tests/test_python_module_alias_shims.py (not served here)
- tests/test_python_property_reads.py (not served here)
- tests/test_python_reachability.py (not served here)
- tests/test_python_receiver_evidence.py (not served here)
- tests/test_python_receiver_shapes.py (not served here)
- tests/test_python_relative_imports.py (not served here)
- tests/test_python_star_imports.py (not served here)
Advantages
- Drastically reduces token usage by providing only the relevant code context for a specific change. evidence: README.md
- Maintains data privacy by storing the knowledge graph locally in a SQLite file without requiring cloud services. evidence: README.md
Limitations
- The graph may become stale if the background update process is interrupted or fails to detect changes. evidence: .github/copilot-instructions.md
- Requires Python 3.10+ and may need manual configuration for environments where MCP is not natively supported. evidence: README.md
Security
Risk level: Medium risk
This brain runs
MCP servers (2)
.mcp.json(code-review-graph):uvx code-review-graph serveREADME.md(code-review-graph):code-review-graph serve --tools query_graph_tool,semantic_search_nodes_tool,detect_changes_tool,get_review_context_tool
Agent instructions that run or fetch something (38)
AGENTS.md:Other commands that may prompt: `scp` and `ssh` (`-o BatchMode=yes`), `apt-get` (`-y`), `brew` (`HOMEBREW_NO_AUTO_UPDATE=1`).· uses the networkCLAUDE.md:`locking.py`: the cross-process lock that lets one graph write run at a time.CLAUDE.md:`skills.py`: `install` (platform MCP configs, hooks, skills, instruction blocks).CLAUDE.md:`install_plan.py`: every install read and write goes through it, so `install --dry-run` can show each change as a diff and a real install writes nothing before its question is answered.CLAUDE.md:`jsonc.py`: comment-preserving JSONC tokenising and splices, shared by install and uninstall so neither flattens a commented config.CLAUDE.md:`install_gitignore.py`: the opt-in `install --gitignore` block listing the files a run created.CLAUDE.md:`uninstall.py`: reverses `install`.CLAUDE.md:uv run pytest tests/ --tb=short -qCLAUDE.md:uv run ruff check code_review_graph/CLAUDE.md:uv run mypy code_review_graph/ --ignore-missing-imports --no-strict-optionalCLAUDE.md:uv run code-review-graph build # full buildCLAUDE.md:uv run code-review-graph update # incremental updateCLAUDE.md:uv run code-review-graph status # graph statisticsCLAUDE.md:uv run code-review-graph detect-changes # risk-scored change analysis (read-only)CLAUDE.md:uv run code-review-graph forget PATH # drop files from the graphCLAUDE.md:uv run code-review-graph serve # MCP server (stdio; --http for localhost)CLAUDE.md:uv run code-review-graph wiki # Markdown wikiCLAUDE.md:uv run code-review-graph register <path> # add a repo to the multi-repo registryCLAUDE.md:uv run code-review-graph eval --all # benchmarksCLAUDE.md:uv run code-review-graph --help # full command listCLAUDE.md:Install and platforms: `test_skills.py`, `test_cli_install.py`, `test_uninstall.py`, `test_git_hook_worktree.py`, `test_hermes_install.py`, `test_qoder_bundled_skills.py`, `test_installer_ownership.py` (what install may rewrite and what belongs to the user), `test_install_gitignore_blo …[+283 chars]CLAUDE.md:Builds a wheel and an sdist with `python -m build`, installs each into its own virtual environment, and drives the installed program with the checkout out of reach.CLAUDE.md:Run it before a release with `uv run --python 3.13 python -m pytest tests/test_packaging.py -m packaging`.CLAUDE.md:upgrade-path: manual run only.code_review_graph/assets/code-review-graph/SKILL.md:Resolve the active repository root from the workspace or `git rev-parse --show-toplevel`.code_review_graph/assets/code-review-graph/SKILL.md:Without MCP, run the bundled helper’s `status` command (it forwards `--json` to the CLI).code_review_graph/assets/code-review-graph/SKILL.md:python3 <skill-root>/scripts/crg_readonly.py status --repo "<repo-root>"code_review_graph/assets/code-review-graph/SKILL.md:python3 <skill-root>/scripts/crg_readonly.py architecture --repo "<repo-root>"code_review_graph/assets/code-review-graph/SKILL.md:python3 <skill-root>/scripts/crg_readonly.py search "<query>" --repo "<repo-root>"code_review_graph/assets/code-review-graph/SKILL.md:python3 <skill-root>/scripts/crg_readonly.py query callers_of "<symbol>" --repo "<repo-root>"code_review_graph/assets/code-review-graph/SKILL.md:python3 <skill-root>/scripts/crg_readonly.py query path_to "<symbol>" --to "<other>" --repo "<repo-root>"code_review_graph/assets/code-review-graph/SKILL.md:python3 <skill-root>/scripts/crg_readonly.py impact --repo "<repo-root>"code_review_graph/assets/code-review-graph/SKILL.md:python3 <skill-root>/scripts/crg_readonly.py detect-changes --brief --repo "<repo-root>"code_review_graph/assets/code-review-graph/SKILL.md:A Windows-mounted path such as `/mnt/e/...` is not by itself a failure: verify that the selected runtime can execute the CLI and access that path.skills/build-graph/SKILL.md:Hooks installed by `code-review-graph install` run an update after each edit, before each commit and after a branch switch, merge or rebase, so manual builds are rarely needed.skills/review-delta/SKILL.md:Changes come from `git diff` against `HEAD~1`;skills/review-pr/SKILL.md:The graph tools read the files on disk, so check out what you review first: `git switch <branch>`, or for a PR `git fetch origin pull/<n>/head:pr-<n>` then `git switch pr-<n>`, then call `build_or_update_graph_tool()`.· uses the networkskills/review-pr/SKILL.md:Diff it against `main` (or `master`) with `git diff --name-only main...HEAD`, and use that ref as `base` below.
Hooks (3)
hooks/hooks.json(SessionStart):cat >/dev/null || true; command -v code-review-graph >/dev/null 2>&1 || exit 0; git rev-parse --git-dir >/dev/null 2>&1 && code-review-graph status --repo "$(git rev-parse --show-toplevel 2>/dev/null)" || echo 'Not a git repo, skipping'hooks/hooks.json(PostToolUse):cat >/dev/null || true; code-review-graph build >/dev/null 2>&1 &hooks/hooks.json(PostToolUse):command -v code-review-graph >/dev/null 2>&1 && code-review-graph hook-update; cat >/dev/null || true
- Medium risk: runs-mcp-server-unpinned-runner (.mcp.json)
- Medium risk: runs-instruction-instruction-network (AGENTS.md:17)
- Medium risk: runs-instruction-instruction-network (skills/review-pr/SKILL.md:13)
Attribution and licence
- Created by
- Tirth
- Declared authors
- Tirth (declared in pyproject.toml)
- Publisher
- Tirth Kanani (Community)
- Source
- tirth8205/code-review-graph · commit e7f2fb2
- Licence
- MIT License (files served here)
- ATTRIBUTION.md (written by AutoGineer)
- Synced
AutoGineer is not affiliated with or endorsed by Tirth.
Install from source
480 of its files are not served here, so there is no ZIP. tirth8205/code-review-graph at e7f2fb2