ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Open-Code-Review实战:用CLI+Git+LLM Agent搭建自动化代码评审流程

Open-Code-Review实战:用CLI+Git+LLM Agent搭建自动化代码评审流程

1. 为什么我要自己搭一套 open-code-review 流程

团队里做代码评审这件事,痛点其实很集中:人少、提交多、评审意见质量参差不齐。尤其是当项目里同时有前端、后端、脚本工具多种语言混着写的时候,靠人工逐行看 diff,既慢又容易漏。我最早接触open-code-review这个概念,是想把「代码评审」从纯人工动作,变成一条可以本地跑、可以接进 Git 工作流、还能让 LLM Agent 帮忙先过一遍的自动化链路。

说白了,open-code-review不是某一个具体软件的名字,而是一类做法的统称:用开放的工具链,把代码评审这件事拆成「拉取变更 → 静态检查 → LLM 语义审查 → 生成报告 → 回写评论」几个环节,每个环节都可以替换、可以本地跑、可以接进 CI。它解决的核心问题是:让评审从「靠人盯」变成「有工具兜底,人只做最终判断」。

这套东西适合谁?我认为有三类人最值得看:一是小团队里兼做评审的开发者,二是想给自己开源项目加自动评审的个人维护者,三是刚接触CLI、Git、LLM Agent这些概念,想找一个完整场景把它们串起来的新手。下面我会按我实际搭这套流程的顺序,把设计思路、关键细节、实操步骤和踩过的坑都摊开讲。

2. 整体设计与思路拆解

2.1 为什么选 CLI + Git + LLM Agent 这条组合

我一开始也想过用现成的 SaaS 评审工具,但很快放弃了。原因很现实:代码不能随便往外传,而且很多工具对私有仓库的 diff 解析并不友好。于是我把方案收敛到三个本地可控的组件上:Git负责拿到变更,CLI负责调度,LLM Agent负责语义层面的审查。

这里要先厘清几个常被混用的词。Agent和LLM不是一回事:LLM 是模型本身,比如常说的 DeepSeek 属于大语言模型;Agent 是「模型 + 工具调用 + 循环决策」的组合,它能自己决定去读哪个文件、跑哪条命令。Embedding则是把文本转成向量,用于相似度检索,和评审场景里的「找相似历史提交」有关,但不是必须的。把这三个概念分清,后面选型就不会乱。

选CLI而不是 GUI,是因为评审流程要能进 CI、能写脚本、能在服务器上无人值守跑。GUI 适合人看,CLI 适合机器跑。我的做法是:CLI 负责编排,Git 负责数据源,LLM Agent 负责「像人一样读代码」。

2.2 评审链路的分层设计

我把整条链路分成四层,每层职责单一,方便替换:

层级职责可选实现
数据层获取 diff、文件内容、提交历史git diff、git log、git worktree
检查层语法、格式、明显错误语言自带 linter、静态分析工具
语义层逻辑、命名、边界、安全隐患LLM Agent
输出层报告、评论、退出码Markdown、终端输出、CI 注释

这样分层的好处是:静态检查能拦住的,不必浪费 LLM 的 token;LLM 只处理「需要理解意图」的部分。实测下来,这种分工能让评审速度提升明显,成本也可控。

2.3 为什么用 git worktree 而不是直接切分支

评审时最怕污染当前工作区。我试过直接在当前分支上跑 diff,结果脚本一改文件,自己正在写的代码就乱了。后来改用git worktree:为每个待评审的提交单独开一个工作目录,评审完直接删掉,互不干扰。

git worktree add ../review-tmp <commit-hash>

这条命令会在上级目录建一个review-tmp,检出指定提交。评审脚本在里面随便跑,主工作区纹丝不动。这个细节看起来小,但它是整套流程能稳定跑的前提。

3. 核心细节解析与实操要点

3.1 Git 环境准备与常见配置

不管后面接什么 Agent,Git都是地基。Windows 上装 Git 我建议直接下官方安装包,安装时注意两个选项:一是「Use Git from the command line and also from 3rd-party software」,这样 CLI 里能直接调 git;二是换行符选「Checkout as-is, commit as-is」,避免跨平台协作时满屏的换行符 diff。

装完先配身份,这是提交的前提:

git config --global user.name "your-name" git config --global user.email "your-email@example.com"

如果要用 Gitee 这类平台,密钥配置也别漏。生成密钥后把公钥贴到平台后台,再用ssh -T测试连通性。我踩过的坑是:密钥生成了但没加进 ssh-agent,导致每次都要输密码,后来用ssh-add加进去才顺。

提示:git commit --amend只适合修改「还没推送」的提交。一旦推送到远端再 amend,历史就会分叉,队友拉取时会冲突。评审流程里如果要修提交信息,务必确认提交还在本地。

3.2 CLI 工具链的选型与安装

CLI是这套流程的调度中心。我实际用过几类:一类是模型厂商提供的命令行工具,比如 codex cli、claude cli 这类;一类是编辑器配套的 CLI,比如 deveco cli、trae cli;还有一类是通用脚本。选型时我看三点:能不能非交互式跑、能不能读本地文件、能不能输出结构化结果。

安装 codex cli 时我遇到过一个典型报错:unable to locate the codex cli binary。这个报错的意思是 CLI 装是装了,但终端找不到它的可执行文件路径。解决办法是把安装目录加进系统 PATH,或者用绝对路径调用。Windows 上还有个坑:在 PowerShell 里codex --version能出版本号,但换到 Windows Terminal 里就找不到,多半是两个终端的环境变量加载方式不同,重启终端或手动刷新 PATH 即可。

claude cli 安装后有个高频问题:每次操作都要确认,跑批量评审时非常烦。它的权限控制是为了安全,但在受控的本地评审环境里,可以通过配置项放宽。我的建议是:先在小范围目录试,确认 Agent 不会乱改文件,再逐步放开权限,别一上来就给完全访问。

3.3 LLM Agent 在评审中的角色定位

Agent 在评审里干的活,和静态检查完全不同。静态检查能告诉你「这行有个未使用变量」,但说不出「这个函数名和它的实际行为不符」。Agent 的价值在于理解意图。

我让 Agent 重点看四类问题:命名与职责是否一致、边界条件是否处理、错误处理是否吞异常、有没有明显的资源泄漏。为了让输出稳定,我会给它一个固定模板,要求按「文件 → 行号 → 问题等级 → 建议」的结构返回。这样后面解析成评论就很容易。

注意:Agent 会「一本正经地胡说」。它可能指出一个根本不存在的问题,也可能漏掉真正的 bug。所以我的原则是:Agent 的输出只作为「待确认清单」,最终是否采纳由人决定。把它当助手,别当裁判。

4. 实操过程与核心环节实现

4.1 从 Git 拿到干净的 diff

评审的第一步是拿到「这次改了什么」。最直接的是:

git diff main...feature-branch

三个点表示「从共同祖先到 feature-branch 的变更」,比两个点更准确,能避免把 main 上的新提交也算进来。如果只想看某个提交:

git show <commit-hash> --stat git show <commit-hash>

--stat先看改了哪些文件、增删多少行,心里有数再决定要不要全量读。文件多的时候,我会先过滤掉自动生成的产物,比如dist/、*.min.js,这些没必要让 Agent 看。

4.2 用 worktree 隔离评审环境

前面提过 worktree,这里给完整流程:

git fetch origin git worktree add ../review-$(date +%s) origin/feature-branch cd ../review-* # 在这里跑静态检查和 Agent 评审

用时间戳命名目录,避免重复。评审结束后:

git worktree remove ../review-*

这一步能保证每次评审都是干净环境,不会因为本地有未提交改动而误判。

4.3 静态检查先行,减少 LLM 负担

在调 Agent 之前,我先跑语言自带的检查。以 Python 为例:

python -m py_compile $(git diff --name-only main...HEAD | grep '\.py$')

这一步能快速抓出语法错误。语法都不对的代码,没必要浪费 token 让 Agent 读。JavaScript 项目我会跑 eslint,Go 项目跑 go vet。这些工具的输出格式统一,容易合并进最终报告。

4.4 调用 Agent 做语义评审

Agent 调用我封装成一个脚本,核心逻辑是:把 diff 和涉及文件的内容拼成 prompt,调 CLI,拿回结构化结果。伪代码大致是:

DIFF=$(git diff main...HEAD) FILES=$(git diff --name-only main...HEAD) PROMPT="你是代码评审助手。以下是变更:\n$DIFF\n请按 文件|行号|等级|建议 的格式输出问题。" echo -e "$PROMPT" | codex-cli --non-interactive > review-result.txt

关键点是--non-interactive,让它一次跑完不等人。不同 CLI 参数名不一样,装完先看--help。拿到结果后,我用脚本解析成 Markdown 表格,贴到 PR 评论里。

4.5 生成报告与回写

最终报告我固定成三段:概览(改了多少文件、多少问题)、静态检查结果、Agent 语义建议。概览用表格,问题按等级排序,高优先级放最前。回写时我用git commit --amend修过一次提交信息,把评审结论附在 message 里,方便追溯。

提示:如果评审脚本要接进 CI,记得用退出码表达结果。有问题返回非零,CI 就会标红,人一眼能看到。

5. 常见问题与排查技巧实录

5.1 环境类问题速查

现象可能原因解决
unable to locate the codex cli binaryPATH 未包含安装目录加 PATH 或用绝对路径
codex --version 能跑,终端里找不到终端环境变量未刷新重启终端或刷新 PATH
login failed, check api token凭证未配或过期重新配置 token
git 命令找不到Git 未装或未加 PATH重装并勾选命令行选项

5.2 Agent 输出不稳定的处理

Agent 有时返回格式乱、有时漏项。我的做法是:prompt 里给一个「输出示例」,并明确「只输出表格,不要解释」。如果还是乱,就在脚本里加一层正则清洗,把非表格行过滤掉。实测这样能把可用率提到九成以上。

5.3 评审误报的应对

误报主要来自两类:一是 Agent 不理解项目约定,二是 diff 上下文不足。前者我会在 prompt 里加一段「项目规范说明」,后者我会把相关文件的完整内容也喂进去,而不只是 diff。上下文给够,误报明显下降。

5.4 我踩过的几个坑

第一个坑是没做 worktree 隔离,评审脚本改了文件,把自己正在写的代码覆盖了,找回来花了不少时间。第二个坑是 Agent 权限开太大,它顺手「优化」了一个文件,虽然改动无害,但混进了评审提交里,很尴尬。第三个坑是没过滤生成文件,Agent 对着压缩后的 JS 分析半天,输出一堆无意义建议。

注意:评审脚本本身也要纳入版本管理。我一开始把脚本放在本地,换台机器就没了,后来放进仓库的tools/目录,团队都能用。

6. 工具选型与扩展思路

6.1 CLI 工具怎么选

选 CLI 我总结成一句话:能非交互跑、能读文件、能出结构化结果。codex cli、claude cli 这类偏模型调用,deveco cli、trae cli 这类偏编辑器集成。评审场景我更看重前者的脚本化能力。如果团队已经在用某个编辑器生态,配套 CLI 也能省事,但要注意它的输出是否方便解析。

6.2 从单机评审扩展到团队流程

单机跑通后,下一步是接进团队流程。我的做法是:把评审脚本做成一个命令,提交前手动跑一次,CI 里再自动跑一次。手动跑是为了快速反馈,CI 跑是为了兜底。两者用同一套脚本,结果一致,不会出现「本地过了 CI 挂了」的情况。

6.3 后续可以加的东西

这套流程还能往上加:比如用 embedding 建一个历史评审意见库,新问题先检索相似历史,避免重复讨论;比如把 Agent 的建议按文件聚合,生成「本次评审重点」摘要;比如接进飞书这类协作工具,评审完自动发通知。这些都不是必须的,但能让流程更顺。

我个人在实际操作中的体会是:open-code-review 这套东西,价值不在「全自动」,而在「把人的精力集中到真正需要判断的地方」。静态检查拦掉低级问题,Agent 给出待确认清单,人只做最终决策。工具是辅助,判断权始终在人手里。最后再分享一个小技巧:评审脚本第一次跑,先拿一个你熟悉的小提交试,看 Agent 的输出是否符合预期,再逐步放大范围,这样最稳。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进