☰
open-code-review:用CLI与LLM Agent实现自动化代码审查
2026/10/19 3:33:11 网站建设 项目流程

代码审查这件事,做久了你会发现一个尴尬的现实:真正有价值的审查意见,往往不是来自"今天有没有空帮我看下这个 PR",而是来自一个稳定、随时在线、不会因为赶进度就敷衍了事的审查者。open-code-review 这个项目,本质上就是在解决这个问题——把代码审查从"依赖人"变成"依赖流程加工具",用 CLI 加 LLM Agent 的方式,让每一次提交都能过一遍结构化的审查逻辑。它适合那些已经在用 Git 做版本管理、团队里有人懂命令行、并且希望把审查标准固化下来的开发者。不管你是刚接触 code review 的新人,还是想给团队搭一套自动化审查流水线的老手,这套思路都值得花时间吃透。

1. 为什么要在命令行里做代码审查

1.1 图形界面审查的隐性成本

大多数人第一次接触 code review,是在 Git 托管平台的网页上:打开 PR、逐行看 diff、留评论、点 approve。这套流程本身没问题,但它有几个被低估的成本。第一是上下文切换,你得从编辑器切到浏览器,找到对应的 PR,等页面加载,再一行行看——这个过程中你的注意力已经被打断了。第二是审查标准不统一,张三觉得命名要改,李四觉得无所谓,最后变成谁声音大听谁的。第三是历史记录散落,审查意见留在平台里,过半年想回溯"当时为什么这么改"基本找不到。

命令行审查的价值就在于把这些环节收拢。你在终端里敲一条命令,diff 直接出来,审查意见直接落到本地文件或者提交记录里,整个过程不离开你熟悉的工作环境。对于习惯用 Vim、Neovim 或者 VS Code 终端的人来说,这种连贯性带来的效率提升是实打实的。

1.2 LLM Agent 在审查环节能补什么

传统的静态检查工具(linter、formatter)能抓语法和风格问题,但它们看不懂"这段逻辑是不是写复杂了""这个函数名是不是误导""这个边界条件是不是漏了"。这些恰恰是 LLM 擅长的。把 LLM 包装成一个 Agent,给它 diff 内容、项目上下文、审查规则,它就能给出接近人类审查者的意见。

但这里有个关键区别:LLM 不是万能的,它会胡说,会漏掉真正的问题,也会对无关紧要的地方过度挑剔。所以 open-code-review 这类项目的核心设计难点,不是"怎么调用 LLM",而是"怎么约束 LLM 的输出,让它只说你关心的、可信的那部分"。这也是为什么它需要一个 Agent 框架,而不是简单地把 diff 丢给模型就完事。

1.3 这套方案适合什么样的团队

不是所有团队都需要这个。如果你的项目一周才提交几次,或者团队只有两三个人,人工审查完全够用。但如果你的项目每天有几十个提交、多个分支并行、审查者经常成为瓶颈,那自动化审查就能明显缓解压力。另外,如果你的团队有明确的编码规范但总是执行不到位,用 LLM Agent 把规范变成可执行的审查规则,比开会强调一百遍都管用。

提示:命令行审查不是要取代人工审查,而是把机械性的、规则明确的部分交给工具,让人专注于架构设计和业务逻辑层面的判断。

2. open-code-review 的核心工作链路拆解

2.1 从 Git diff 到审查输入的转换

整个流程的起点是 Git。open-code-review 需要拿到"这次改了什么",最直接的方式就是解析git diff的输出。但原始 diff 有几个问题:它包含大量上下文行(默认前后各三行),对于大改动来说信息量爆炸;它不包含文件的历史背景;它的格式是给机器看的,不是给模型看的。

所以第一步通常是把 diff 做一次清洗和结构化。常见做法是提取出变更的文件列表、每个文件的变更块(hunk)、每个块的新增和删除行,然后组装成模型能理解的格式。这里有个细节:要不要保留上下文行?我的经验是保留,但要限制数量。上下文太少模型看不懂改动意图,上下文太多又会稀释重点。一般前后各保留 2 到 3 行比较合适。

# 获取当前分支相对于主分支的变更 git diff main...HEAD --unified=3 # 只看变更的文件名 git diff main...HEAD --name-only # 获取某个提交的变更 git show <commit-hash> --unified=3

2.2 Agent 的角色划分与提示词设计

一个能用的审查 Agent,通常不是单个提示词搞定的,而是拆成几个角色。我见过比较合理的划分是:一个"概览 Agent"负责总结这次改动做了什么,一个"细节 Agent"负责逐块审查具体代码,一个"规则 Agent"负责检查是否符合团队规范。每个 Agent 的提示词侧重点不同,输出格式也不同。

概览 Agent 的提示词要引导模型关注"意图"而不是"语法",比如让它回答"这次改动解决了什么问题""有没有引入新的依赖""影响范围有多大"。细节 Agent 的提示词要给出明确的审查维度,比如可读性、边界条件、错误处理、性能隐患。规则 Agent 则需要把团队的编码规范以清单形式喂进去,让它逐条对照。

这里有个容易踩的坑:提示词里如果只说"请审查这段代码",模型会给你一堆无关痛痒的建议,比如"建议添加注释""变量名可以更清晰"。要得到有价值的输出,必须把审查维度具体化,并且明确告诉模型"如果某个维度没有问题,直接说没有问题,不要硬凑"。

2.3 审查结果的落地形式

审查结果生成之后,怎么用是个关键问题。常见的落地形式有三种:输出到终端、写入文件、回写到 Git 平台。输出到终端适合快速查看,但信息一多就刷屏了。写入文件(比如review-report.md)适合存档和分享。回写到 Git 平台(作为 PR 评论)适合团队协作,但需要额外的 API 集成。

我的建议是至少支持前两种。终端输出用颜色区分严重程度(红黄绿),文件输出用 Markdown 方便阅读。如果要做平台回写,注意控制评论数量,不要每个小问题都发一条评论,否则 PR 页面会被刷爆。比较好的做法是把同类问题合并成一条评论,或者只对严重级别以上的问题发评论。

落地形式适用场景优点注意事项
终端输出本地快速审查即时、不打断流程信息多时刷屏
文件输出存档、分享可追溯、格式灵活需要手动清理旧文件
平台回写团队协作集中、可见控制评论数量

3. 搭建环境时最容易忽略的几个细节

3.1 Git 配置与仓库状态检查

在跑审查之前,必须先确认 Git 仓库的状态是干净的。如果工作区有未提交的改动,git diff的结果会混入这些改动,导致审查内容不准确。所以流程的第一步应该是检查git status,如果有未提交的改动,要么先提交,要么明确告诉用户"当前审查的是工作区改动"。

另一个容易忽略的是分支基准。git diff main...HEAD和git diff main..HEAD看起来差不多,但语义不同。三个点表示"从两个分支的共同祖先开始比较",两个点表示"直接比较两个分支的当前状态"。做审查时通常用三个点,因为你想看的是"这个分支相对于主分支引入了什么",而不是"两个分支现在差多少"。

# 检查工作区状态 git status --porcelain # 确认当前分支 git branch --show-current # 确认主分支名称(可能是 main 或 master) git symbolic-ref refs/remotes/origin/HEAD | sed 's@^refs/remotes/origin/@@'

3.2 LLM 接口的调用与超时处理

调用 LLM 接口看起来简单,但实际用起来问题不少。最常见的是超时。大 diff 加上长提示词,请求体可能很大,模型处理时间可能超过默认超时时间。如果不做处理,请求会直接失败,用户看到的就是一个莫名其妙的错误。

我的做法是设置一个合理的超时时间(比如 120 秒),并且在超时后自动重试一次。如果还是失败,就把 diff 拆分成更小的块,分多次请求。另外要注意 token 限制,不同模型的上下文窗口不一样,如果 diff 太大,要么截断,要么分块。截断有风险,可能丢掉关键改动,所以优先选分块。

还有一个细节是错误信息的处理。LLM 接口返回的错误有时候很模糊,比如"请求失败",这时候如果直接把错误抛给用户,用户根本不知道该怎么办。比较好的做法是捕获常见错误(超时、限流、认证失败),给出明确的提示,比如"接口限流,请稍后重试"或者"认证失败,请检查 API Key 配置"。

3.3 审查规则的配置方式

审查规则如果硬编码在代码里,改起来很麻烦。比较好的做法是放在一个独立的配置文件里,比如review-rules.yaml或者review-rules.json。这样团队可以根据自己的规范调整规则,不需要改代码。

规则的结构可以设计成"维度加具体条目"的形式。比如:

rules: - dimension: 可读性 items: - 函数名应该使用动词开头 - 避免超过三层的嵌套 - 魔法数字应该提取为常量 - dimension: 错误处理 items: - 所有外部调用都应该有错误处理 - 错误信息应该包含上下文 - 不要吞掉异常

这种结构的好处是清晰,模型容易理解,人也容易维护。另外,规则不要写太多,一开始控制在 10 到 15 条以内,跑一段时间之后再根据实际效果调整。规则太多模型会顾此失彼,反而抓不住重点。

注意:审查规则不是越多越好。规则过多会导致模型输出冗长且重点不突出,建议从核心规则开始,逐步迭代。

4. 实测中暴露的问题与应对策略

4.1 模型对 diff 上下文的误读

这是我在实测中遇到最多的问题。模型看到一段 diff,有时候会误以为删除的行是新增的,或者把上下文行当成改动行。这会导致它给出完全错误的审查意见,比如"你新增了一个空指针风险",但实际上那行代码是本来就有的。

解决这个问题的关键是让 diff 的格式对模型更友好。一种做法是在每行前面加上明确的标记,比如[新增]、[删除]、[上下文],而不是依赖+和-符号。另一种做法是在提示词里明确说明 diff 的格式约定,告诉模型"以加号开头的行是新增,以减号开头的行是删除,以空格开头的行是上下文"。

还有一种情况是模型对文件路径不敏感。如果 diff 里包含多个文件,模型有时候会把 A 文件的问题归到 B 文件上。解决办法是在每个文件的 diff 块前面加上清晰的文件路径标记,并且在提示词里强调"请针对每个文件分别给出审查意见"。

4.2 审查意见的噪音过滤

模型生成的审查意见,有很大一部分是噪音。比如"建议添加注释""这个变量名可以更清晰""考虑使用更高效的算法"——这些话放在任何代码上都成立,但没有任何实际价值。如果不做过滤,用户看到的就是一堆废话,久而久之就不信任这个工具了。

过滤噪音有几个思路。第一是在提示词里明确要求"只报告具体问题,不要给泛泛的建议"。第二是设置严重程度分级,让模型给每条意见标注严重程度(高、中、低),然后只展示中高严重程度的。第三是后处理,用规则过滤掉包含特定关键词的意见,比如"建议添加注释""可以考虑"这类模糊表述。

我自己的做法是组合使用这三种。提示词里先约束,输出后按严重程度过滤,最后再用一个简单的关键词黑名单兜底。经过这三层过滤,剩下的意见质量会明显提升。

4.3 大改动下的性能与成本控制

当一次改动涉及几十个文件、上千行代码时,直接把整个 diff 丢给模型是不现实的。一方面是 token 限制,另一方面是成本。这时候需要做分块处理。

分块的策略有几种。按文件分块是最简单的,每个文件单独审查,最后汇总。但这样会丢失文件之间的关联,比如 A 文件改了接口,B 文件改了调用,分开看可能看不出问题。按变更块(hunk)分块更细,但会产生大量请求。还有一种做法是先让模型看一遍文件列表和改动摘要,判断哪些文件需要详细审查,哪些可以跳过,然后再对重点文件做详细审查。

成本控制方面,可以在配置里设置一个阈值,比如"改动超过 500 行时只审查新增行,不审查删除行",或者"只审查特定目录下的文件"。另外,缓存也很有用,同一个 diff 不要重复请求,把结果缓存起来,下次直接读缓存。

分块策略适用场景优点缺点
按文件分块文件间关联弱简单、并行容易丢失跨文件关联
按 hunk 分块改动集中粒度细请求数量多
先摘要后详审大改动成本可控实现复杂

5. 把审查能力接入日常工作流

5.1 本地提交前的自动审查

最自然的接入点是 Git 的 pre-commit 钩子。在提交之前自动跑一次审查,如果发现严重问题就阻止提交。这样可以在问题进入仓库之前就拦住它。

但这里有个平衡问题:如果审查太严格,每次提交都被拦住,开发者会很烦,最后可能会用--no-verify跳过钩子。所以 pre-commit 阶段的审查应该只关注严重问题,比如明显的 bug、安全问题、严重的规范违反。风格类的问题可以放到后面,不要在这个阶段拦。

# .git/hooks/pre-commit 示例 #!/bin/bash # 调用 open-code-review 做提交前审查 open-code-review --staged --severity high if [ $? -ne 0 ]; then echo "审查发现严重问题,提交已阻止" exit 1 fi

5.2 与 CI 流水线的结合

CI 流水线是另一个自然的接入点。在 PR 创建或更新时自动触发审查,把结果作为流水线的一部分展示出来。这样审查结果对团队可见,也方便追溯。

在 CI 里跑审查要注意几点。第一是环境准备,CI 环境里可能没有配置 Git 用户信息,需要提前设置。第二是密钥管理,LLM 接口的 API Key 要通过 CI 的密钥管理功能注入,不要硬编码在配置文件里。第三是超时设置,CI 任务通常有超时限制,审查任务要控制在这个限制之内。

5.3 审查结果的追踪与迭代

审查工具本身也需要迭代。哪些规则经常触发、哪些规则从来没触发过、哪些意见被开发者忽略了、哪些意见被采纳了——这些数据可以帮助你优化规则和提示词。

最简单的做法是把每次审查的结果存下来,定期回顾。如果发现某条规则总是产生误报,就把它去掉或者调整。如果发现某个维度的问题总是被漏掉,就加强这个维度的提示词。这个过程不需要很复杂,一个简单的日志文件加定期人工回顾就够了。

提示:审查工具的规则应该随着项目演进不断调整。项目初期可能更关注代码风格,后期可能更关注性能和安全性,规则要跟着变。

6. 几个容易被问到的概念澄清

6.1 Agent、LLM、AI 模型到底是什么关系

这三个词经常被混用,但含义不同。AI 模型是一个宽泛的概念,指任何通过数据训练出来的、能完成特定任务的模型。LLM(大语言模型)是 AI 模型的一种,专门处理文本,比如常见的那些对话模型。Agent 则是一个系统概念,它通常包含一个 LLM 作为核心,再加上工具调用、记忆、规划等能力,能自主完成多步任务。

打个比方:AI 模型像是"会做菜的机器",LLM 是"会做川菜的机器",Agent 是"一个完整的厨房,里面有会做川菜的机器,还有采购、备菜、摆盘的能力"。open-code-review 里的 Agent,就是围绕代码审查这个任务,把 LLM 和 Git 操作、文件读写、结果输出这些能力组合起来。

6.2 CLI 工具相比 GUI 的优势在哪

CLI(命令行界面)和 GUI(图形界面)不是对立的,各有适用场景。CLI 的优势在于可组合、可脚本化、可远程操作。你可以把多个 CLI 工具用管道串起来,可以用脚本批量执行,可以通过 SSH 在远程服务器上操作。GUI 的优势在于直观、易上手、适合可视化展示。

对于代码审查这种需要频繁执行、需要集成到自动化流程里的任务,CLI 更合适。而对于需要展示复杂 diff、需要多人协作讨论的场景,GUI 更合适。open-code-review 选择 CLI 形态,是因为它的目标用户是开发者,使用场景是本地和 CI 环境,这些场景下 CLI 的效率更高。

6.3 Git 在审查流程中扮演的角色

Git 不只是版本控制工具,它还是审查流程的数据源。审查需要知道"改了什么",这个信息只能从 Git 里拿。Git 的 diff、log、blame 等命令,提供了审查所需的基础数据。

理解 Git 的几个关键概念对用好审查工具很重要。HEAD是当前提交,main是主分支,origin是远程仓库。git diff main...HEAD是比较当前分支和主分支的差异。git log可以看提交历史,git blame可以看每一行是谁改的。这些命令在排查审查问题时经常用到。

另外,Git 的钩子机制(hooks)是接入审查的天然入口。pre-commit、pre-push、commit-msg 这些钩子,可以在特定时机自动触发审查。用好钩子,能让审查变成流程的一部分,而不是一个需要额外记得去做的动作。

7. 我在实际使用中总结的几条经验

第一条经验是:不要指望一次配置就能得到理想效果。审查规则和提示词都需要反复调整。我一开始写的提示词,模型输出的意见一半是废话。后来我把审查维度拆细,明确告诉模型"每个维度只报告最严重的一个问题",输出质量才上来。这个过程大概迭代了五六次。

第二条经验是:审查结果要给人看,不要给机器看。我见过一些实现,把审查结果输出成 JSON,然后让用户自己解析。这对开发者来说太麻烦了。好的做法是默认输出人类可读的格式,需要机器处理时再提供 JSON 选项。

第三条经验是:控制审查的频率和范围。不是每次提交都需要全量审查。小改动可以只做快速检查,大改动才做详细审查。另外,审查范围可以按目录或文件类型过滤,比如只审查src/下的代码,不审查测试文件和文档。

第四条经验是:把审查和修复分开。审查工具只负责发现问题,不负责修复问题。有些实现会让模型直接给出修复后的代码,这看起来很美好,但风险很大——模型可能引入新的问题,而且开发者可能不看审查意见就直接用修复代码。审查意见应该是建议性的,最终怎么改由开发者决定。

最后一条经验是:保持工具的可解释性。当审查工具给出一个意见时,用户应该能知道这个意见是基于哪条规则、哪个维度的检查得出的。如果用户不理解为什么会有这个意见,他就不会信任这个工具。所以在输出审查意见时,最好附上规则来源和判断依据。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询