
1. 为什么我要自己搭一套 open-code-review 流程代码审查这件事做过团队协作的人都有体会。理想状态下每次提交都有人认真看、认真提意见、认真改现实状态往往是提交堆成山审查靠自觉最后变成“看一眼没问题就合并”。尤其是个人项目或者小团队根本没有专职的审查者自己审自己更是形同虚设。open-code-review这个方向说白了就是把代码审查这件事从“靠人”变成“靠流程 工具”。核心思路是用 CLI 把 Git 的变更抓出来交给 LLM Agent 做第一轮分析再由人做最终判断。它不是要替代人而是把人的精力从“找明显问题”转移到“判断复杂逻辑”上。我搭这套东西的起因很简单手上同时维护几个仓库每次提交前自己过一遍 diff时间长了眼睛会疲劳漏掉的问题越来越多。后来试过纯手工检查清单也试过让 AI 直接读整个文件效果都不理想——前者太依赖状态后者上下文太散。最后落到“只审 diff 结构化提示词 CLI 自动化”这个组合上才算跑通。这套流程适合谁适合有一定 Git 基础、想给自己或小团队加一道质量防线的开发者。不需要你懂模型训练也不需要你搭服务会装 Git、会跑命令行、能配一个 API Key 就能上手。下面我按实际搭建顺序把每个环节拆开讲。2. 整体设计思路与方案选型2.1 为什么是 CLI 而不是 IDE 插件一开始我也想过用 IDE 插件点一下就能审。但实际用下来有几个问题插件绑定编辑器换环境就得重装插件对 diff 的获取方式不透明有时候把未暂存的改动也带进去最关键的是插件很难和 CI 或者 Git Hook 串起来。CLI 的好处是“可组合”。git diff输出什么我就审什么审完的结果可以写文件、可以贴到终端、可以塞进提交信息。它不依赖你用什么编辑器VS Code 也好IDEA 也好甚至纯终端也好流程是一样的。而且 CLI 天然适合做自动化——后面接 pre-commit 或者 CI 都是顺手的事。提示如果你平时用 GUI 工具比较多比如 Git 小乌龟这类也不用担心。CLI 流程和 GUI 不冲突你照样可以用 GUI 提交只是在提交前多跑一条命令而已。2.2 为什么用 LLM Agent 而不是传统静态检查传统静态检查工具比如各种 linter擅长的是语法层面、风格层面、已知模式的问题。它们快、稳定、不花钱但有个硬伤不理解意图。一个变量命名不规范它能报但“这段逻辑在并发下会不会出问题”它报不出来。LLM Agent 的价值在于它能读上下文、能推理。你把 diff 给它它能结合周边代码判断“这个改动是不是漏了边界条件”“这个异常处理是不是吞掉了错误”。当然它也会胡说所以定位必须是“第一轮筛查”不是“最终裁决”。这里要区分几个容易混的概念。Agent、LLM、AI 模型不是一回事LLM 是底层的大语言模型比如 DeepSeek 这类属于模型层Agent 是在模型外面套了一层“能调工具、能多步执行”的逻辑AI 模型是个更大的筐机器学习模型、深度学习模型都算。我们这套流程里LLM 负责“读和判断”Agent 负责“按步骤调 Git、调模型、整理输出”。Embedding 则是另一条线主要用在检索和相似度上代码审查里暂时用不到不用被这些名词绕晕。2.3 审查范围怎么定只审 diff 的取舍这是整个设计里最关键的一个决定。我试过三种范围审查范围优点缺点适用场景整个仓库上下文全太贵、太慢、噪音大几乎不用单个文件全文上下文较全无关代码干扰判断小文件重构仅 diff聚焦、便宜、快缺全局上下文日常提交最后我固定用“仅 diff”但做了两个补偿一是把 diff 涉及的文件的周边函数签名一起带上二是让 Agent 在不确定时主动说“需要更多上下文”。这样既控制了成本又不会因为上下文太窄而误判。2.4 工具链的整体串联方式整条链路是这样的Git 负责产出 diff一个脚本负责把 diff 和提示词拼起来CLI 负责调用模型输出结果再回到终端或者文件。中间不引入数据库、不引入服务全部是本地文件和标准输入输出。这样做的好处是排查问题特别简单。哪一步不对就看哪一步的中间产物。diff 不对就看 Git 命令提示词不对就看拼接脚本模型输出不对就调提示词。没有黑盒。3. 核心细节解析与实操要点3.1 Git 侧的准备安装、配置与 diff 的正确取法先把 Git 本身弄利索。Windows 上装 Git直接下安装包一路下一步就行装完在终端里跑git --version能出版本号就算成。装完建议做两件配置一是git config --global user.name和user.email二是如果连的是 Gitee 这类平台配好 SSH 密钥省得每次输密码。取 diff 有几个容易踩的坑。第一个是暂存区和工作区的区别# 只看已暂存的改动推荐因为提交前你会先 add git diff --cached # 看工作区所有未提交改动包含未暂存 git diff HEAD # 看某次提交的改动 git diff HEAD~1 HEAD我推荐用git diff --cached因为你的提交流程通常是“改代码 → add → 审查 → commit”。审查已暂存的内容正好对应你即将提交的东西。如果你习惯不 add 直接 commit那就用git diff HEAD。第二个坑是路径和引号。Windows 下如果文件名带中文或者空格diff 输出可能带转义。可以在命令前加参数git -c core.quotepathfalse diff --cached这个core.quotepathfalse能让中文路径正常显示不然你会看到一堆八进制转义模型读起来也费劲。第三个坑是 diff 太大。一次提交改了三千行直接丢给模型既贵又容易丢重点。我的做法是设一个阈值比如超过 800 行就分段审或者先让模型只看文件列表和改动统计git diff --cached --stat先看统计判断这次改动是不是该拆成多个提交。很多时候 diff 太大本身就是个信号——这次提交做的事太多了。3.2 提示词的设计让模型说人话、说重点提示词决定了输出质量。我踩过的最大坑是提示词太笼统比如“帮我审查这段代码”模型就会给你一堆“建议增加注释”“建议统一命名风格”这种正确的废话。后来我把提示词改成结构化输出要求模型按固定格式回答你是一名资深代码审查者。请审查以下 git diff。 要求 1. 只报告真实存在的问题不要提风格偏好。 2. 每个问题标注严重程度blocker / major / minor。 3. 每个问题必须给出文件、行号范围、问题描述、修改建议。 4. 如果 diff 信息不足以判断明确说“需要更多上下文”不要猜。 5. 最后给一个总体结论可以提交 / 修改后提交 / 需要讨论。 diff 如下 diff这个提示词的关键在于“只报告真实存在的问题”和“不要猜”。前者压掉了大量噪音后者减少了幻觉。严重程度分级则让你能快速判断这次提交能不能过。还有一个细节把 diff 放在提示词最后。有些模型对末尾内容更敏感放最后能提高它认真读的概率。这不是玄学是实测下来输出质量确实更稳。3.3 模型调用的封装一个脚本搞定不需要复杂的框架一个 shell 脚本或者 Python 脚本就够了。核心逻辑是读 diff、拼提示词、调接口、输出结果。import subprocess import sys def get_diff(): result subprocess.run( [git, -c, core.quotepathfalse, diff, --cached], capture_outputTrue, textTrue ) return result.stdout def build_prompt(diff): return f你是一名资深代码审查者。请审查以下 git diff。 要求 1. 只报告真实存在的问题不要提风格偏好。 2. 每个问题标注严重程度blocker / major / minor。 3. 每个问题必须给出文件、行号范围、问题描述、修改建议。 4. 如果 diff 信息不足以判断明确说需要更多上下文不要猜。 5. 最后给一个总体结论可以提交 / 修改后提交 / 需要讨论。 diff 如下 {diff} if __name__ __main__: diff get_diff() if not diff.strip(): print(没有已暂存的改动跳过审查。) sys.exit(0) prompt build_prompt(diff) # 这里接你的模型调用可以是本地模型也可以是 API print(prompt)这个脚本先跑通“拿到 diff 并拼出提示词”模型调用部分单独接。这样做的好处是调试方便——你可以先把 prompt 打出来看看对不对再决定怎么调模型。注意不要把 API Key 硬编码在脚本里。用环境变量或者放在一个不进版本库的配置文件里。这是基本的安全习惯别嫌麻烦。3.4 输出结果的落地终端、文件还是提交信息审查结果有几种用法我一般分场景日常提交前直接打终端看一眼没问题就 commit。重要改动输出到文件比如review-$(date %s).md留档方便回看。团队协作把结论精简成一行塞进 commit message 的末尾比如[review: pass]。不建议把完整审查结果塞进 commit message太长了。commit message 是给人快速扫的不是给机器读的。4. 实操过程与核心环节实现4.1 从零搭起环境准备清单先把要装的东西列清楚避免中途卡壳Git装好并配置 user.name、user.email。Python 3.8用来跑封装脚本。一个模型调用方式可以是本地跑的模型也可以是 API。本地模型对机器有要求API 则要管好 Key。一个终端Windows Terminal、iTerm、普通终端都行。装完先验证git --version python --version两个都能出版本号基础环境就 OK 了。4.2 第一次跑通用一个小改动验证全链路别一上来就拿大改动试。先改一个文件加一行注释然后git add . python review.py看输出的 prompt 里 diff 对不对、格式对不对。确认没问题后再接模型调用。第一次跑通的目标不是“审出问题”而是“链路通”。我当时的做法是先用一个故意写错的改动试比如把if x 0改成if x 0看模型能不能指出边界变化。能指出来说明提示词和调用都到位了。4.3 参数与成本控制怎么让审查不烧钱如果用 API成本主要看输入输出 token 数。控制成本有几个实招只审 diff不审全文这是最大的节省。设 diff 行数上限超过就分段或者先拆提交。提示词尽量精简别写一堆没用的背景。输出要求结构化避免模型长篇大论。我实测下来一个中等规模的提交200 行 diff 以内审查成本是很低的。真正贵的是那种一次改几千行的大提交所以“拆小提交”本身就是省钱手段。4.4 和 Git Hook 结合提交前自动跑想省事的话可以挂到 pre-commit 钩子上。在.git/hooks/pre-commit里写#!/bin/sh python review.py记得给执行权限。这样每次 commit 前会自动跑审查。但有个问题如果审查结果只是打印它不会阻止提交。要阻止的话得让脚本在发现 blocker 时返回非零退出码。我的建议是前期不要自动阻止先让它跑着你人工看结果。跑一段时间确认误报率可接受了再考虑加阻止逻辑。一上来就卡提交很容易因为误报把自己搞烦最后把钩子删了。5. 常见问题与排查技巧实录5.1 diff 为空或者内容不对最常见的原因是改动没 add。git diff --cached只看暂存区你没 add 它当然是空的。先git status看一眼确认改动状态。另一个原因是路径问题。如果你在子目录里跑脚本Git 可能只取当前目录的 diff。要么在仓库根目录跑要么加--指定路径。5.2 模型输出全是废话大概率是提示词太松。检查两点一是有没有明确“只报告真实问题”二是有没有要求结构化输出。如果还不行就在提示词里加一两个反例比如“不要输出‘建议增加注释’这类内容”。5.3 模型说“需要更多上下文”这是好事说明它没瞎猜。这时候你有两个选择一是手动把相关文件的关键部分贴进去二是调整审查范围把整个文件带上。我一般先看它要什么上下文如果只是某个函数就单独贴那个函数。5.4 中文路径乱码前面提过加-c core.quotepathfalse。如果还乱检查终端编码是不是 UTF-8。Windows 老终端默认编码可能不是换成 Windows Terminal 一般就好了。5.5 常见问题速查表现象可能原因处理方式diff 为空没 add / 路径不对git status 确认仓库根目录跑中文乱码quotepath 未关加 -c core.quotepathfalse输出全是套话提示词太松加“只报真实问题”和结构化要求模型瞎猜没要求“不确定就说”提示词加“需要更多上下文”条款成本偏高diff 太大拆提交设行数上限钩子不阻止提交脚本没返回非零发现 blocker 时 sys.exit(1)5.6 几个我踩过的坑第一个坑是拿未暂存的 diff 去审结果审的是半成品改到一半的代码被报了一堆问题。后来固定用--cached世界清净了。第二个坑是提示词里没限定语言模型有时候中英混杂。后来明确要求“用中文输出”统一了。第三个坑是忘了处理空 diff。第一次跑钩子的时候空 diff 也去调模型白花钱。加了个判断空 diff 直接退出。6. 后续可以怎么扩展这套流程跑顺之后能扩展的方向不少。比如把审查结果按严重程度分类存档积累一段时间后看哪类问题最常出现反过来指导自己的编码习惯。再比如把 blocker 级别的问题自动生成待办接到任务管理工具里。还可以做多轮审查第一轮让模型找问题第二轮让另一个模型或者同一模型换个角度复核减少漏报。这个成本会上去适合重要分支合并前用。如果团队里有人用不同的编辑器这套 CLI 流程照样通用因为它不绑定任何编辑器。谁都能在自己环境里跑输出格式统一讨论起来也有共同语言。我个人在实际操作中的体会是这套东西最大的价值不是“审出多少问题”而是“让提交前多一道固定动作”。习惯一旦养成代码质量的下限就被抬高了。至于模型选哪个、提示词怎么调都是在这个习惯之上慢慢磨的事不用一开始就追求完美。