news 2026/10/19 3:32:25

本地CLI加LLM Agent实现自动化代码审查:open-code-review流程搭建指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
本地CLI加LLM Agent实现自动化代码审查:open-code-review流程搭建指南

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

团队里代码合并前的 review 环节,长期靠人肉盯。项目一多、提交一频繁,review 就变成了走过场——点个 approve 了事。我试过几种现成的托管平台自带审查功能,要么规则太死,要么对上下文理解不够,误报率高得让人直接关掉通知。后来我把目光转向了本地 CLI 加 LLM Agent 的组合,也就是这套 open-code-review 的思路:用命令行工具拉取 Git 变更,把 diff 喂给大模型,让 Agent 按预设规则逐条分析,最后输出结构化的审查意见。

这套东西解决的核心问题很明确:把重复性的代码规范检查、潜在缺陷扫描、提交信息质量评估从人手里接过去,让人只聚焦在架构设计和业务逻辑这些真正需要判断力的地方。它适合有一定 Git 基础、日常在终端里干活的开发者,也适合想给团队引入自动化审查但不想被平台绑死的技术负责人。整套流程不依赖特定托管服务,本地跑、本地出结果,数据不出机器,这一点对代码敏感的项目尤其重要。

我踩过的坑主要集中在两块:一是 LLM 对长 diff 的处理容易丢上下文,二是 Agent 的提示词设计直接决定误报率。下面我把整套设计思路、关键细节、实操步骤和排查经验完整拆开讲,你照着搭一遍基本能跑通。

2. 整体设计与技术选型拆解

2.1 为什么是 CLI 加 LLM Agent 而不是平台插件

平台插件的问题在于它活在别人的规则里。你想改审查维度、想换模型、想调整输出格式,都得看平台开不开这个口子。CLI 方案的好处是每一环都捏在自己手里:Git 命令负责取数据,脚本负责编排,LLM 负责分析,输出格式自己定。Agent 在这里的角色不是简单的“调一次 API”,而是带工具调用能力的执行体——它可以自己决定先看哪些文件、要不要追加上下文、需不需要再跑一次 git diff 拿更细的变更。

从热词里能看到 codex cli、claude cli、trae cli 这类工具最近讨论度很高,它们本质都是把 LLM 能力封装成命令行入口。我选型时的判断标准有三条:能不能在本地终端直接调用、支不支持把文件内容作为上下文传入、有没有可编程的退出码和结构化输出。满足这三条,就能嵌进自动化流程。

2.2 数据流设计:从 Git 到审查意见

整条链路我拆成四段。第一段是变更采集,用git diff拿到目标分支与当前分支的差异,这里要注意区分--staged、--cached和直接对比两个 commit 的场景。第二段是上下文补全,光有 diff 不够,LLM 需要知道被改文件周边的代码长什么样,所以我会把变更涉及文件的完整内容也带上,但要做截断控制。第三段是 Agent 分析,把 diff、文件上下文、审查规则一起塞进提示词,让模型逐文件、逐 hunk 输出意见。第四段是结果聚合,把模型返回的 JSON 解析出来,按严重级别排序,输出到终端或写进文件。

这个设计里最关键的一个取舍是:要不要把整个仓库喂给模型。我的答案是不要。token 成本是一方面,更麻烦的是噪声——无关文件会稀释模型对真正变更的注意力。实测下来,只带变更文件加上其直接依赖的文件,审查准确率明显更高。

2.3 模型选择与成本控制

热词里有人问 agent、llm、embedding 的区别,这里顺带理一下:LLM 是大语言模型本身,负责理解和生成;Agent 是在 LLM 外面套了一层决策和工具调用逻辑的执行体;Embedding 是把文本转成向量用于检索和相似度计算。open-code-review 里主要用的是 LLM 加 Agent 这层,Embedding 可选,用来做历史审查意见的相似匹配,避免重复报同一个问题。

模型选择上,我日常用 DeepSeek 这类性价比高的模型做初筛,把明显的问题先过滤掉,剩下拿不准的再交给更强的模型复核。这样一套下来,单次审查的成本能压到很低。要注意的是不同模型对 JSON 格式的遵循程度不一样,提示词里必须把输出结构写死,否则解析会崩。

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

3.1 Git 变更采集的几种姿势

采集变更看起来简单,实际有好几个坑。最常用的是对比当前分支和目标分支:

git diff origin/main...HEAD --unified=5

这里...和..的区别很关键。三个点表示从共同祖先开始算差异,两个点表示两个提交点的直接差异。做 review 时用三个点更合理,因为它只显示你这个分支引入的变更,不会把目标分支上的新提交也算进来。--unified=5是控制上下文行数,默认 3 行有时候不够模型判断,我一般调到 5 到 8 行。

如果要审查已暂存但未提交的内容,用:

git diff --cached --unified=5

还有一种场景是审查单个 commit,直接git show <commit-hash>就行。我建议把这几种模式做成脚本参数,用的时候按需切换,别每次手敲。

注意:git diff输出里如果包含二进制文件变更,会显示成Binary files differ,这种要单独处理,别直接丢给模型,它分析不了二进制内容。

3.2 上下文补全的截断策略

把变更文件的完整内容带上,token 消耗会飙升。我的做法是分层截断:变更行前后各保留 50 行,文件超过 500 行的只取变更密集区域。具体实现可以用脚本解析 diff 的 hunk 头,拿到变更行号范围,再从文件里按范围抽取。

另一个技巧是把文件的 import 或依赖声明部分也带上,因为很多问题出在依赖引入上。比如新增了一个库但没在依赖文件里声明,模型看到 import 语句就能提示。这部分内容通常不长,带上成本可控。

3.3 提示词设计的核心要素

提示词决定了审查质量的上限。我总结下来必须包含四块内容:角色设定、审查维度、输出格式、边界约束。

角色设定要明确告诉模型它是资深代码审查者,关注可维护性、安全性和性能。审查维度我列了六条:命名规范、错误处理、边界条件、资源泄漏、并发安全、提交信息质量。输出格式强制 JSON,每个问题包含文件路径、行号、严重级别、问题描述、修改建议。边界约束是告诉模型不要对没看到的代码妄加评论,不确定的标为“需人工确认”。

一个实测有效的技巧是让模型先输出一段简短的变更摘要,再逐条列问题。这样即使后面 JSON 解析失败,摘要部分还能用。另外提示词里要明确禁止模型编造行号,行号必须来自 diff 里实际出现的行。

3.4 Agent 工具调用的编排

Agent 和普通 LLM 调用的区别在于它能主动调工具。在 open-code-review 里,我给 Agent 配了三个工具:读文件、跑 git 命令、查历史审查记录。当模型发现 diff 里引用了某个函数但没看到定义时,它可以自己调读文件工具去拿定义。当它不确定某个变更是否之前已经报过时,可以查历史记录。

工具调用的编排要注意死循环问题。我设了最大调用轮次,一般 5 轮足够,超过就强制输出当前结果。另外每个工具的返回内容也要做长度限制,防止某次读取把上下文撑爆。

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

4.1 环境准备与依赖安装

先把基础环境弄好。Git 是必须的,Windows 上装 Git 建议用 Git Bash,命令行体验和 Linux 一致。安装完配置一下用户信息:

git config --global user.name "你的名字" git config --global user.email "你的邮箱"

如果要用 Gitee 之类的托管服务,密钥配置走 SSH 那套,生成密钥后把公钥贴到平台设置里。这些是前置条件,不展开。

然后是 LLM 的 CLI 工具。以 codex cli 为例,安装后先验证版本:

codex --version

能打印版本号说明装好了。如果报unable to locate the codex cli binary,基本是 PATH 没配好,把安装目录加到环境变量里就行。Windows Terminal 里如果命令找不到,检查一下是不是装在了 WSL 里而当前在 PowerShell。

4.2 审查脚本的骨架实现

我用 Python 写编排脚本,核心逻辑分四步。第一步调 git 拿 diff:

import subprocess def get_diff(base="origin/main", unified=5): cmd = ["git", "diff", f"{base}...HEAD", f"--unified={unified}"] result = subprocess.run(cmd, capture_output=True, text=True) return result.stdout

第二步解析 diff,提取变更文件列表和每个文件的变更行范围。第三步组装提示词,把 diff、文件上下文、规则拼在一起。第四步调 LLM CLI,拿返回结果解析。

调 CLI 的方式有两种:一种是直接subprocess调命令行工具,把提示词通过 stdin 传进去;另一种是调 API。CLI 方式的好处是复用工具本身的认证和配置,不用在脚本里管密钥。我一般用 CLI 方式,命令大概长这样:

echo "$PROMPT" | codex exec --output-format json

具体参数看工具文档,不同 CLI 的参数名不一样,但思路一致。

4.3 输出解析与结果呈现

模型返回的 JSON 要健壮地解析。我遇到过模型在 JSON 外面包了 markdown 代码块的情况,所以解析前先做一层清洗,把json 和去掉。解析失败时降级处理,直接把原始文本打出来让人看。

结果呈现我按严重级别分三档:blocker、warning、suggestion。blocker 直接让脚本返回非零退出码,这样能接进 CI 流程,有问题就卡住合并。warning 和 suggestion 只打印不阻断。终端输出用颜色区分,但要注意有些终端不支持颜色,得做兼容。

4.4 接进 Git 钩子与 CI

本地可以用 pre-push 钩子,推送前自动跑一遍审查。钩子脚本放在.git/hooks/pre-push,内容就是调审查脚本,退出码非零就阻止推送。CI 里则在合并请求的流水线里加一步,跑完把结果贴到评论里。

这里有个细节:CI 环境里通常没有交互式终端,LLM CLI 的认证要走环境变量或配置文件。提前把 token 配好,别等到跑的时候才发现认证失败。另外 CI 里跑要注意超时设置,LLM 调用有时候会慢,超时太短会误判失败。

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

5.1 模型返回格式错乱怎么办

最常见的问题是模型不按 JSON 输出,或者在 JSON 里塞了注释。解决办法有三层:提示词里用 few-shot 给一个标准输出示例;解析前做正则清洗;解析失败时重试一次,重试时在提示词里强调“只输出 JSON,不要任何额外文字”。实测下来这三层加上去,解析成功率能到 95% 以上。

5.2 diff 太长导致模型丢上下文

当一次提交涉及几十个文件时,diff 会非常长。我的处理是分批:按文件分组,每组控制在模型上下文窗口的 60% 以内,分批调用后合并结果。合并时注意去重,同一个问题可能在多个批次里被报出来。另外批次之间要有重叠,防止某个文件的变更被切到两批里导致分析不完整。

5.3 误报太多怎么调

误报主要来自提示词太宽泛。比如“检查所有潜在的空指针”会让模型把很多正常代码也标出来。我的做法是把规则具体化,比如“检查函数返回值在使用前是否做了 nil 判断,仅当返回值可能为 nil 时报告”。规则越具体,误报越少。另外可以维护一个忽略列表,把已知的误报模式加进去,下次自动过滤。

5.4 常见问题速查表

问题现象可能原因排查方向
CLI 命令找不到PATH 未配置检查安装目录是否加入环境变量
认证失败token 过期或未配置重新登录或检查配置文件
JSON 解析失败模型输出含额外文字加强提示词约束,增加清洗逻辑
审查结果为空diff 采集范围不对检查分支名和...用法
调用超时模型响应慢或网络问题增加超时时间,加重试机制
行号对不上diff 上下文行数变化统一--unified参数

5.5 几个我踩过的坑

第一个坑是git diff的路径引用。在子目录里跑脚本时,git 命令的相对路径会变,导致找不到文件。解决办法是脚本开头先cd到仓库根目录,用git rev-parse --show-toplevel拿到根路径。

第二个坑是模型对中文注释的处理。如果代码里中文注释多,模型有时候会把注释内容也当成代码分析。提示词里要明确说明注释不参与逻辑审查,只看代码本身。

第三个坑是并发调用。为了提速我试过并发调多个模型,结果触发限流。后来改成串行加缓存,同一个 diff 的审查结果缓存起来,重复跑直接读缓存,速度快很多。

6. 一些扩展思路和我的使用体会

这套流程跑顺之后,我做了几个扩展。一个是把审查结果写进 SQLite,积累一段时间后可以做统计分析,看哪类问题最高频,反过来指导团队规范。另一个是接进飞书之类的协作工具,审查完自动发消息通知,省得人盯着终端。

关于 Agent 和 LLM 的区别,我在实际用下来的体会是:LLM 像是一个知识渊博但只会被动回答的顾问,Agent 则像是一个会自己找资料、自己动手的助手。open-code-review 里真正提升效率的是 Agent 那层工具调用能力,它让模型能主动补全上下文,而不是等着你把所有信息喂给它。

最后分享一个小技巧:审查规则不要一次写太多,先从三条最关键的开始,跑一段时间看误报和漏报情况,再逐步加。规则堆太多,模型注意力会被分散,反而每一条都做不好。我现在的规则集是迭代了十几版才稳定下来的,一开始就想写全,基本不可能。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/19 3:31:38

中文分词服务原理与实战:词典、动态规划与未登录词识别

1. 项目概述1.1 为什么修仙大陆也需要分词服务说实话&#xff0c;我第一次看到"东方仙盟练气期"和"分词服务"这两个词被塞进同一句话时&#xff0c;第一反应是某个师兄又在拿代码写玄幻段子。但真把幽冥大陆这个项目的需求文档翻完之后&#xff0c;才意识到…

作者头像 李华
网站建设 2026/10/19 3:31:38

Cadence高速电路设计与Sigrity仿真:从叠层阻抗到DDR时序与PDN验证全流程

简介&#xff1a;这份资源面向高速电路设计与信号完整性分析方向的工程师及高年级学生&#xff0c;整合了《高速电路设计与仿真分析&#xff1a;Cadence实例设计详解》与《信号电源完整性仿真分析与实践》两套内容&#xff0c;帮助读者掌握Cadence与Sigrity工具在高速系统设计中…

作者头像 李华
网站建设 2026/10/19 3:31:07

open-code-review:开源可扩展的 CLI 代码审查工具

1. 项目概述&#xff1a;一个真正能落地的开源代码审查 CLI 工具到底长什么样&#xff1f;“open-code-review”这个名字乍看平平无奇&#xff0c;但拆开来看——open不是泛指“开源”&#xff0c;而是强调开放可扩展、开放协议接入、开放规则配置&#xff1b;code-review也不是…

作者头像 李华
网站建设 2026/10/19 3:30:24

Qt HTTP POST JSON请求的坑:请求头与序列化实战指南

简介&#xff1a;面向需要掌握Qt网络编程的开发者&#xff0c;该压缩包演示了如何基于QNetworkAccessManager发起HTTP POST请求&#xff0c;并以application/json格式向服务器提交JSON数据。工程完整覆盖数据组装、QJsonDocument与QJsonObject的构建和解析、字符串转UTF-8编码、…

作者头像 李华
网站建设 2026/10/19 3:29:09

Git提交会跑错分支吗?分支、提交、推送关系彻底讲透

我经常在群里看到有人抛出这个问题&#xff1a;“我在A分支修改并commit时&#xff0c;会不会把修改的内容推到B分支上&#xff1f;”说句实话&#xff0c;我最初用Git那两年也被这个事唬住过&#xff0c;总觉得提交和推送之间有某种“自动分发”的机制&#xff0c;把本地分支搞…

作者头像 李华