code-review-graph 开源项目深度解析:让 AI 读更少的代码,做更准的 review

做 AI Coding 的人应该都遇到过这个问题:让 Claude Code 或 Cursor review 一个 PR,它上来就先把整个项目扫一遍,token 哗哗地烧,结果改了 3 行代码,它读了 30 个文件。

我一直在找有没有办法让 AI「精准阅读」而不是「全量扫描」。前几天找到了 code-review-graph,29K+ Star,Python 写的,实测确实有效。

这篇文章讲三件事:它怎么用、它怎么实现的、它到底省了多少。
在这里插入图片描述

它解决什么问题

先说一个真实场景。

你改了 EvaluationAgent.java 里的一个方法,想让 AI review 一下。传统的做法是 AI 把 Controller、Service、Repository、DTO 全读一遍,搞清楚上下文再给你意见。一个中等规模的 Spring Boot 项目,这些文件加起来轻松 5 万 token。

但真正和这次改动相关的可能只有 3 个文件:调用方 AgentOrchestrator、被调用的 NvcKnowledgeRepository、以及对应的测试类。

code-review-graph 的思路就是:先建图,再按图索骥。

它用 Tree-sitter 解析你整个代码库,构建一个函数级别的调用关系图。AI 做 review 时,不再盲读文件,而是从改动点出发,沿着调用链找到真正相关的代码。

安装和使用

整个流程三步搞定。

第一步:全局安装

pip install code-review-graph
# 或者用 pipx
pipx install code-review-graph

要求 Python 3.10+。建议装一下 uv,MCP 配置会自动用 uvx 启动,比直接用 code-review-graph 命令更稳。

第二步:配置 AI 工具

进入你的项目目录,运行:

cd your-project
code-review-graph install --platform claude-code

它会自动做这几件事:

动作 具体操作
写 MCP 配置 在项目根目录生成 .mcp.json
注入 hooks 写入 .claude/settings.json 的 pre-commit hook
更新 .gitignore 添加 .code-review-graph/

支持的平台很多,不只 Claude Code:

code-review-graph install --platform cursor       # Cursor
code-review-graph install --platform codex        # Codex
code-review-graph install --platform windsurf     # Windsurf
code-review-graph install --platform gemini-cli   # Gemini CLI
# 还有 Zed、Continue、OpenCode、Copilot 等十几个

不指定 --platform 会自动检测你装了哪些工具,一次性全配好。

第三步:构建图谱

code-review-graph build

这个命令扫描整个项目,用 Tree-sitter 解析每个文件,把类、函数、调用关系存到 SQLite 里。

我实际跑了一下自己的项目(463 个文件,Spring Boot + Java 21):

INFO: Progress: 463/463 files parsed
INFO: Spring DI resolver: resolved 743 CALLS edges in 372 Java files
INFO: Loaded 2993 unique nodes, 34756 edges
Full build: 463 files, 3550 nodes, 35398 edges (postprocess=full)

不到 20 秒就跑完了。它还识别了 Spring 的依赖注入关系(743 条边),@Autowired 注入的 Bean 关系也在图里。
在这里插入图片描述

日常使用

构建完之后,日常用法就变了。以前让 AI review 代码,直接说「帮我看看这个 PR」。现在用 MCP 工具:

/code-review-graph:review-delta     # review 自上次 commit 以来的改动
/code-review-graph:review-pr        # review 整个 PR 的 diff

AI 会先通过 MCP 查图谱,拿到改动的影响范围,然后只读相关文件,而不是盲扫整个项目。

还有一个 watch 模式,文件保存时自动更新图谱:

code-review-graph watch

底层实现:它是怎么建图的

这部分是我觉得最有价值的。code-review-graph 的架构不复杂,但每一步的设计都有讲究。

整体架构

MCP 协议

解析 AST

检测变更

节点+边

精准上下文

AI 编程工具
Claude Code / Cursor / Codex

MCP Server

Graph Store
SQLite

Parser
Tree-sitter

Incremental Engine
git diff

代码文件

git/svn

影响分析
BFS + 权重衰减

核心就三个组件:Parser(解析器)Graph Store(图存储)MCP Server(协议层)

Parser:Tree-sitter 做语法解析

解析代码用的是 Tree-sitter,不是正则,也不是简单的 grep。

Tree-sitter 是一个增量解析器生成器,能把你写的源代码变成一棵完整的抽象语法树(AST)。它的好处是:

  • 语言无关:一套逻辑处理 Java、Python、Go、Rust、TypeScript 等几十种语言
  • 增量解析:文件改了一行,只重新解析那一行附近的 AST 节点,不用全量重跑
  • 容错性强:代码有语法错误也能解析出大部分结构

Parser 的核心逻辑在 parser.py 里,做的事情是:

  1. 递归遍历 AST 节点
  2. 根据节点类型(_CLASS_TYPES_FUNCTION_TYPES 等语言特定映射)提取类、函数、接口
  3. 从函数体里提取调用关系(谁调用了谁)
  4. 解析 import 语句,把模块路径关联起来
# 伪代码:Parser 的核心逻辑
def parse_file(file_path):
    tree = tree_sitter.parse(file_path)   # Tree-sitter 解析
    nodes = []
    edges = []

    for node in walk_ast(tree):
        if node.type in CLASS_TYPES:
            nodes.append(extract_class(node))
        elif node.type in FUNCTION_TYPES:
            nodes.append(extract_function(node))
            # 提取函数体内的调用
            for call in find_calls(node):
                edges.append(CALLS(source=func, target=call))

    return nodes, edges

对于 Java 项目,它还有一个 Spring DI Resolver,专门解析 @Autowired@Qualifier 这些注解,把 Spring Bean 的注入关系也建到图里。这是它比通用工具好用的关键——不只是语法层面的调用关系,还理解框架层面的依赖注入。

Graph Store:SQLite 存图

图谱存在 SQLite 里,用的是经典的「节点 + 边」模型:

节点表(nodes)

字段 说明
kind 节点类型:File、Class、Function、Type、Test
qualified_name 全限定名,如 src/auth.py::AuthService.login
file_path 所在文件
line_start/end 代码行范围
language 编程语言
community_id 社区检测后的社区 ID

边表(edges)

字段 说明
kind 边类型:CALLS、IMPORTS_FROM、INHERITS、CONTAINS 等
source_qualified 起点节点
target_qualified 终点节点
confidence 置信度(用于模糊匹配的情况)

用 SQLite 而不是 Neo4j 之类的图数据库,是个务实的选择——零依赖、单文件、嵌入式,不需要额外起服务。WAL 模式支持并发读,更新图谱时不影响查询。

还有一个 FTS5 全文搜索表,支持按名称、文件路径、函数签名做关键词搜索,不需要向量化也能做基本的语义查找。

影响分析算法

review 时最核心的逻辑是影响半径分析(Impact Radius)。从改动点出发,沿调用图向外扩展,找到所有受影响的节点。

算法是带权重的 BFS:

def get_impact_radius(seed_nodes, max_depth=2):
    impacted = set()
    frontier = seed_nodes

    for depth in range(max_depth):
        next_frontier = set()
        for node in frontier:
            # 正向:这个节点影响了谁
            for target in get_forward_edges(node):
                score = edge_weight * depth_decay ** depth
                if score >= SCORE_FLOOR:
                    next_frontier.add(target)
            # 反向:谁依赖这个节点
            for source in get_reverse_edges(node):
                score = edge_weight * depth_decay ** depth
                if score >= SCORE_FLOOR:
                    next_frontier.add(source)

        impacted.update(next_frontier)
        frontier = next_frontier

    return impacted

几个设计细节:

  • 深度衰减:每走一步,影响力乘以衰减系数。离改动点越远的节点,影响力越小
  • 边类型权重:不同类型的边权重不同。CALLS(调用关系)比 REFERENCES(引用关系)权重高
  • 双向遍历:既看下游(改动影响了谁),也看上游(谁依赖被改的东西)
  • 阈值截断:影响力低于 SCORE_FLOOR 的节点直接丢掉,避免无意义的扩散

增量更新

全量构建只在第一次跑。之后每次只解析变了的文件:

  1. git diff 找出变更文件
  2. 查询图谱,找到依赖变更文件的其他文件
  3. 只重新解析这两部分文件
  4. 更新 SQLite 里对应的行

通过文件哈希判断是否需要重新解析,没变的文件直接跳过。这就是为什么 watch 模式几乎零开销——保存一个文件,增量更新通常在毫秒级完成。

MCP Server

图谱建好了,AI 怎么用?通过 MCP(Model Context Protocol)

MCP 是 Anthropic 推出的一个标准协议,让 AI 工具能调用外部能力。code-review-graph 把自己注册为一个 MCP Server,暴露了 30 个工具:

工具 功能
build 构建/重建图谱
impact 查某个节点的影响半径
search 按名称搜索代码结构
traverse 沿调用链遍历
review 生成 review 上下文
detect_changes 检测代码变更
hotspots 找高频修改的热点区域
embed 计算语义向量
community 查看代码社区聚类

AI 工具通过 MCP 协议调用这些工具,拿到精准的上下文,而不是自己去读文件。

它到底省了多少

README 里有 6 个开源仓库的基准测试数据,用 5 个典型 Agent 问题测的:

仓库 全量读取 token 图谱查询 token 倍数
fastapi 948,793 2,653 375.6x
flask 143,594 2,196 71.0x
code-review-graph 208,821 3,190 68.1x
gin 166,868 2,766 61.9x
httpx 142,356 2,661 60.6x
express 136,052 3,936 36.0x

中位数大约 65 倍,最好的情况(fastapi)达到 376 倍。

当然,这个「全量读取」是上界——实际的 AI 工具不会真的把整个项目读一遍,它会 grep 关键词然后读最匹配的几个文件。code-review-graph 的 eval 里也测了这个「grep + top-3」的真实基线,图谱方案依然有明显优势,因为它不只找到直接匹配的文件,还能沿调用链找到间接相关的代码。

我的实际体验

在我自己的 Spring Boot 项目上(463 文件、3550 节点、35398 条边),构建完之后重启 Claude Code,确实能感受到变化:

  1. review 时读的文件少了。以前改一个 Service 方法,Claude Code 会把相关的 Controller、DTO、Entity 都读一遍。现在它先查图谱,只读调用链上的文件
  2. Spring DI 关系被识别了。743 条 @Autowired 注入的边,意味着 AI 能理解 Bean 之间的依赖,不只是方法调用
  3. 增量更新快。开启 watch 模式后,改一个文件保存,图谱更新几乎无感

也有一些局限:

  • 对动态语言(Python 的 getattr、JavaScript 的 eval)的支持有限,静态分析搞不定的东西它也搞不定
  • 图谱只建了结构关系,不理解业务语义。它知道 A 调用了 B,但不知道 A 和 B 在业务上是什么关系
  • 首次构建对大项目(10 万+ 文件)可能需要几分钟

适用场景

场景 推荐度 原因
中大型项目的日常 Code Review ⭐⭐⭐⭐⭐ 精准定位影响范围,token 节省最明显
Spring/Java 项目 ⭐⭐⭐⭐⭐ 专门的 Spring DI 解析器
多语言混合项目 ⭐⭐⭐⭐ Tree-sitter 支持几十种语言
小项目(<50 文件) ⭐⭐ 收益不大,AI 盲读也很快
纯动态语言项目 ⭐⭐⭐ 静态分析有局限,但 import 和基本调用还是能解析

总结

code-review-graph 的核心思路其实很简单:用图谱代替盲读,用结构代替猜测

它不做魔法,就是老老实实地用 Tree-sitter 解析代码、建图、存 SQLite,然后通过 MCP 协议暴露给 AI 工具。整个设计很工程化——SQLite 而不是图数据库、增量更新而不是全量重建、权重衰减 BFS 而不是复杂的图算法。

如果你的项目超过几百个文件,AI 做 review 时经常「读了一堆没用的文件」,这个工具值得试试。三步安装,构建一次,之后就是无感使用。

项目地址:https://github.com/tirth8205/code-review-graph


Logo

欢迎加入 MCP 技术社区!与志同道合者携手前行,一同解锁 MCP 技术的无限可能!

更多推荐