代码审查这件事,做了十几年,我最大的感受是:真正拖慢团队的从来不是写代码的速度,而是等别人帮你看代码的时间。一个 PR 提上去,运气好半天有人理,运气不好压两天,改完再等一轮,一个本来半小时能合的小功能硬是拖成三天。所以当"open-code-review"这个概念出来的时候,我第一反应不是"又一个工具",而是"终于有人把这件事想明白了"——把代码审查从"等人"变成"随时可跑",用 CLI 加 LLM Agent 的方式,让审查这件事变得像跑一条命令那么简单。这篇文章我想聊的不是某个具体产品的使用手册,而是围绕 open-code-review 这个方向,把 CLI、LLM Agent、Git 工作流这几块拼在一起,讲清楚它到底解决了什么问题、底层是怎么运转的、实际落地时会踩哪些坑。不管你是刚接触 Git 的新手,还是已经带团队的老手,只要你对"让代码审查更快更稳"这件事有兴趣,这里应该都能找到能直接抄作业的东西。1. 为什么代码审查需要一次"去中心化"改造1.1 传统 PR 审查的三个隐性成本大部分人谈代码审查,谈的都是"质量"。但真正在一线待过就知道,质量只是明面上的收益,真正吃掉团队效率的是三个隐性成本。第一个是等待成本。一个 PR 从提交到有人开始看,中间的空窗期完全取决于 reviewer 什么时候有空。我统计过我们团队半年的数据,平均等待时间是 4.7 小时,最长的压了 31 小时。这期间提交者要么干等,要么切去别的任务,上下文切换的损耗比等待本身还贵。第二个是沟通成本。同一个问题,reviewer 在评论里写一遍,提交者理解一遍,改完再解释一遍。遇到表达不清的,来回三四轮很正常。很多评论其实是"这个变量名能不能改一下"这种一句话的事,但走完整个 PR 流程,成本被放大了十倍。第三个是一致性成本。不同 reviewer 关注点完全不一样,A 只看逻辑,B 只看命名,C 只看有没有测试。结果就是同一个仓库里,代码风格飘忽不定,因为审查标准本身就不统一。这三个成本加起来,才是"代码审查拖慢团队"的真相。而 open-code-review 这个方向的价值,恰恰是冲着这三个成本去的。1.2 CLI 加 LLM Agent 到底改变了什么先说清楚一个概念,很多人把 CLI 和 LLM Agent 混着说,其实它们是两层东西。CLI是命令行界面,它解决的是"入口"问题。以前你要审查代码,得打开网页、找到 PR、点开 diff、逐行看。现在你只需要在终端敲一条命令,比如ocr review --staged,它就把当前暂存区的改动拉出来审。入口从"网页"变成"终端",意味着审查可以嵌入到你本来就在用的工作流里,不用切换上下文。LLM Agent是执行审查的主体,它解决的是"谁来审"的问题。传统审查必须有人,Agent 的价值是它可以 7x24 小时在线,你提交完立刻就能拿到第一轮反馈。注意我说的是"第一轮",Agent 不是替代人,而是把人从"找低级问题"里解放出来,让人的精力集中在架构、业务逻辑这些真正需要判断力的地方。这两者结合,本质上是把代码审查从"事件驱动"(等人来看)变成"命令驱动"(随时可跑)。这个转变听起来小,实际影响很大——它让审查从流程的瓶颈变成了流程的常规环节。1.3 一个真实场景:从提 PR 到拿到反馈的时间差我拿我们团队一个真实案例对比一下。改造前:小王写完一个用户鉴权模块,提了 PR。上午 10 点提的,reviewer 在开会,下午 2 点才看。看完提了 6 条意见,其中 3 条是"这里没做空值判断""这个函数超过 50 行了""缺少单元测试"这种机械性问题。小王改完已经下午 4 点,再等 reviewer 二次确认,第二天上午才合。改造后:小王写完,在终端跑ocr review,30 秒后拿到反馈,其中 3 条机械性问题当场就改了。改完再提 PR,reviewer 下午 2 点看的时候,看到的已经是一个干净版本,只提了 2 条关于业务边界的意见。当天下午就合了。时间差从"跨天"变成"当天",关键就在于把机械性问题的发现提前到了提交之前。这就是 open-code-review 最朴素也最实在的价值。2. open-code-review 的核心组件拆解2.1 CLI 层:命令设计背后的取舍一个 code review CLI 好不好用,看它的命令设计就知道。我见过太多工具,功能很全但命令设计反人类,最后没人用。好的 CLI 设计有几个原则。第一是默认行为要符合直觉。比如ocr review不带参数时,应该默认审查当前工作区未提交的改动,因为这是最高频的场景。第二是参数要少而精,不要搞出二十个 flag,常用的就那几个:指定审查范围(--staged、--commit、--branch)、指定输出格式(--json、--markdown)、指定严重级别过滤(--severity high)。我实际用下来,最顺手的命令组合是这样的:# 审查暂存区改动,只看高优先级问题 ocr review --staged --severity high # 审查某个 commit ocr review --commit abc1234 # 审查当前分支相对 main 的所有改动 ocr review --branch main --format markdown > review.md这里有个设计细节值得说:为什么要有--format markdown?因为审查结果经常需要贴到 PR 评论里,直接输出 markdown 就能复制粘贴,省去手动整理的功夫。这种"为下游场景考虑"的设计,才是 CLI 工具真正好用的关键。2.2 LLM Agent 层:它到底在"审"什么很多人以为 LLM Agent 审查代码就是"把代码丢给模型,让它挑毛病"。实际远不止这么简单。一个成熟的审查 Agent,内部至少要做四件事。第一是上下文构建。光看 diff 是不够的,Agent 需要知道这个改动所在的文件长什么样、被调用的地方有哪些、相关的类型定义是什么。所以它要先做一轮上下文收集,把 diff 周围的代码、相关的 import、被修改函数的调用方都拉进来。第二是规则匹配。Agent 内部通常有一套规则库,比如"函数不超过 50 行""禁止裸 except""SQL 必须参数化"。这些规则一部分是通用的,一部分是项目自定义的。Agent 会先跑规则匹配,把确定性问题标出来。第三是语义分析。这部分才是 LLM 的强项,比如"这个循环的时间复杂度是 O(n²),数据量大了会慢""这个错误处理吞掉了异常,出问题排查不到"。这类问题规则匹配不出来,必须靠模型理解代码意图。第四是优先级排序。Agent 不能把所有问题都平铺给你,那样等于没审。它要按严重程度排序,把"会导致线上故障"的排在"命名不规范"前面。这个排序逻辑,直接决定了审查结果有没有用。2.3 Git 集成层:diff 是怎么被"喂"给 Agent 的这一层是最容易被忽略,但最容易出问题的。Git 的 diff 机制有很多细节,处理不好就会导致 Agent 看到错误的代码。首先要区分几种 diff 场景。git diff看的是工作区和暂存区的差异,git diff --staged看的是暂存区和最后一次提交的差异,git diff HEAD看的是工作区和最后一次提交的差异。这三个场景对应不同的审查需求,CLI 必须能准确区分。其次是diff 的上下文行数。默认 diff 只显示改动行前后各 3 行,但审查代码时 3 行往往不够。比如你改了一个函数的返回值,Agent 需要看到这个函数完整的签名和前面的逻辑,才能判断改动是否合理。所以好的实现会把上下文行数调大,比如前后各 10 行。还有一个坑是重命名和移动。Git 有时会把"重命名文件"识别成"删除旧文件+新增新文件",导致 diff 里出现大量无关内容。这时候需要用git diff -M开启重命名检测,让 diff 更干净。# 开启重命名检测,上下文 10 行 git diff --staged -M -U10这个命令是很多 CLI 工具内部实际调用的,理解它有助于你排查"为什么 Agent 看到的内容不对"这类问题。2.4 输出层:审查结果怎么呈现才有用审查结果呈现得好不好,直接决定这个工具会不会被用第二次。我见过最糟糕的呈现方式,是把所有问题一股脑输出成一大段文字,看完眼睛都花了。好的输出应该分层。第一层是摘要,一句话告诉你"这次审查发现 3 个高优先级、5 个中优先级问题"。第二层是问题列表,每条包含文件路径、行号、问题描述、修复建议。第三层是详情,点开某条能看到具体的代码片段和更详细的解释。用表格呈现问题列表是最清晰的:严重级别文件行号问题建议高auth.py42未校验用户输入增加参数校验中auth.py67函数过长(78行)拆分为子函数低auth.py12变量命名不清晰改为 user_token这种呈现方式,扫一眼就知道该先改哪个,比一大段文字强太多。3. 从零跑通一次 open-code-review 的完整流程3.1 环境准备:Git 和 CLI 的安装配置在跑 open-code-review 之前,Git 环境必须先配好。这块看起来基础,但新手最容易在这里卡住。Windows 上装 Git,直接去官网下载安装包,一路下一步就行。但有两个选项要注意:一是"Adjusting your PATH environment",选"Git from the command line and also from 3rd-party software",这样终端里才能直接用 git 命令;二是"Configuring the line ending conversions",选"Checkout Windows-style, commit Unix-style line endings",避免跨平台协作时换行符出问题。装完之后验证一下:git --version # 输出类似 git version 2.43.0然后配置用户信息,这是提交代码的前提:git config --global user.name "你的名字" git config --global user.email "你的邮箱"如果是团队协作,建议再配一下默认分支名和 pull 策略:git config --global init.defaultBranch main git config --global pull.rebase truepull.rebase true这个配置我强烈建议开,它能让你的提交历史保持线性,避免出现一堆无意义的 merge commit。审查代码时,线性的历史看起来清爽太多。CLI 工具本身的安装,通常是通过包管理器。比如 npm 生态的:npm install -g open-code-review或者用 pip:pip install open-code-review装完跑ocr --version验证。如果提示找不到命令,八成是 PATH 没配好,检查一下包管理器的全局 bin 目录有没有加到 PATH 里。3.2 第一次审查:从 staged 改动开始环境配好,先拿最简单的场景练手——审查暂存区的改动。假设你改了auth.py,先git add到暂存区,然后跑:ocr review --staged第一次跑通常会让你配置 API key 或者选择模型。这里有个经验:先用小模型跑通流程,再换大模型。因为第一次跑主要是验证环境通不通,用大模型纯属浪费。等流程跑通了,再换成能力更强的模型做正式审查。跑通之后你会看到类似这样的输出:Reviewing 1 file, 3 changes... [HIGH] auth.py:42 - 用户输入未做校验,存在注入风险 建议:使用参数化查询或输入白名单校验 [MEDIUM] auth.py:67 - 函数 validate_token 长度 78 行,超过建议阈值 50 行 建议:拆分为 token 解析和 token 校验两个函数 [LOW] auth.py:12 - 变量名 t 含义不明确 建议:改为 user_token Summary: 1 high, 1 medium, 1 low看到这个输出,说明整条链路已经通了。3.3 把审查嵌进 Git 工作流:pre-commit 钩子跑通单次审查只是第一步,真正提升效率的是把它嵌进 Git 工作流,让它在每次提交前自动跑。Git 的 pre-commit 钩子就是干这个的。在.git/hooks/目录下创建pre-commit文件:#!/bin/bash ocr review --staged --severity high if [ $? -ne 0 ]; then echo "发现高优先级问题,提交已阻止" exit 1 fi然后给它执行权限:chmod +x .git/hooks/pre-commit这样每次git commit之前,都会自动跑一次审查。如果发现高优先级问题,提交会被阻止,逼着你先改。这里有个坑要注意:钩子文件不会被提交到仓库。.git/hooks/目录是本地目录,团队其他人 clone 下来是没有这个钩子的。所以团队协作时,要么每个人手动配,要么用 husky 这类工具把钩子配置纳入版本管理。用 husky 的话,配置是这样的:{ "husky": { "hooks": { "pre-commit": "ocr review --staged --severity high" } } }这样钩子配置跟着仓库走,新人 clone 下来跑一下npm install就自动装好了。3.4 审查历史提交:补审和批量审查有时候改动已经提交了,才发现没审。这时候可以用--commit参数补审:ocr review --commit abc1234如果要审查一个分支上所有的提交,用--branch:ocr review --branch main这个命令会审查当前分支相对 main 的所有改动。适合在提 PR 之前做一次全面自查。批量审查时有个性能问题要注意:如果分支上提交很多,一次性全审会很慢。这时候可以加--since参数限制时间范围:ocr review --branch main --since "3 days ago"只审最近三天的改动,速度快很多。4. 实际落地时踩过的坑和应对方案4.1 误报太多:怎么调教审查规则刚上手 open-code-review 的人,十有八九会遇到这个问题:误报太多。Agent 把一堆不是问题的地方标成问题,看多了就烦,最后干脆不看了。误报的来源主要有三个。第一是规则太严,比如把"函数超过 50 行"当成硬性规则,但有些函数就是天然长,硬拆反而更乱。第二是上下文不足,Agent 没看到完整的代码,误判了某段逻辑。第三是模型理解偏差,把正常的写法当成错误。应对方案是分层调教。先调规则,把明显不合理的规则关掉或放宽阈值。再调上下文,增大 diff 的上下文行数。最后调模型,如果某个模型误报率一直很高,换一个试试。配置文件通常长这样:rules: function_length: enabled: true threshold: 80 # 从 50 放宽到 80 naming: enabled: true severity: low # 命名问题降级为低优先级 context: lines: 15 # 上下文从 10 行增加到 15 行调教是个渐进过程,别指望一次配好。我的经验是,前两周每周调一次,之后基本就稳定了。4.2 大文件审查超时:分片策略审查大文件时,很容易遇到超时。因为 LLM 有上下文长度限制,一个几千行的文件塞进去,要么超时要么被截断。解决方案是分片。把大文件按函数或类拆成小块,逐块审查。好的 CLI 工具会自动做这件事,但你需要知道它的分片逻辑,才能判断结果是否可靠。分片有个原则:不能把有依赖关系的代码拆开。比如一个函数调用了另一个函数,这两个函数最好放在同一片里审,否则 Agent 看不到调用关系,容易误判。如果工具不支持自动分片,可以手动指定审查范围:# 只审查某个文件的某个函数范围 ocr review --file auth.py --lines 40-1204.3 敏感信息泄露:审查前的脱敏处理这是最容易被忽略但最危险的一个坑。代码里经常会有硬编码的密钥、token、内部地址,如果直接丢给 LLM 审查,这些信息就泄露了。审查前必须做脱敏。常见做法是用正则匹配敏感模式,替换成占位符:import re patterns = [ (r'(api[_-]?key\s*=\s*["\'])[^"\']+', r'\1***REDACTED***'), (r'(password\s*=\s*["\'])[^"\']+', r'\1***REDACTED***'), (r'(token\s*=\s*["\'])[^"\']+', r'\1***REDACTED***'), ] def redact(code): for pattern, replacement in patterns: code = re.sub(pattern, replacement, code, flags=re.IGNORECASE) return code更稳妥的做法是在 CI 层面加一道检查,提交前扫描敏感信息,发现就阻止。这样从源头上避免敏感信息进入代码库。注意:脱敏不是可选项,是必选项。尤其是团队协作场景,一次泄露可能造成不可逆的损失。4.4 审查结果和人工审查冲突:怎么协调最后一个坑是流程上的:Agent 说没问题,但人工审查发现了问题,或者反过来。这时候怎么协调?我的做法是明确分工。Agent 负责机械性问题:格式、命名、明显的逻辑错误、缺失的测试。人工负责判断性问题:架构是否合理、业务逻辑是否正确、边界条件是否覆盖。这样分工之后,冲突就少了。因为两者关注的根本不是同一类问题。如果 Agent 报了人工觉得不是问题的,那多半是规则需要调;如果人工发现了 Agent 没报的机械性问题,那多半是规则库需要补。定期回顾这些冲突,把它们转化成规则或提示词的改进,Agent 的准确率会越来越高。5. 把 open-code-review 用出花来的几个进阶思路5.1 自定义规则:让 Agent 懂你的项目规范通用规则只能覆盖 60% 的场景,剩下 40% 是项目特有的。比如你们团队规定"所有数据库操作必须走 Repository 层",这种规则通用工具不知道,得自己加。自定义规则通常有两种写法。一种是声明式的,用 YAML 描述:rules: - id: no-direct-db-access description: 禁止在 Service 层直接访问数据库 pattern: "from.*models import.*Model" files: "services/**/*.py" severity: high message: "Service 层应通过 Repository 访问数据库"另一种是编程式的,写个函数:def check_repository_pattern(context): issues = [] for file in context.files: if 'services/' in file.path: if 'from models import' in file.content: issues.append(Issue( file=file.path, severity='high', message='Service 层禁止直接导入 Model' )) return issues声明式适合简单规则,编程式适合复杂逻辑。实际项目里两种混着用。5.2 多模型对比:不同模型的审查风格差异不同 LLM 审查代码的风格差异很大,这点很有意思。我实测下来,有的模型偏保守,只报确定的问题,漏报多但误报少;有的模型偏激进,什么都报,误报多但漏报少。实际使用时,可以组合着来。保守模型做门禁,它报的问题基本都要改;激进模型做参考,它报的问题人工筛一遍,挑有价值的改。如果 CLI 支持多模型,可以这样配:ocr review --staged --model conservative --severity high ocr review --staged --model aggressive --format markdown > suggestions.md第一条命令的结果用来卡提交,第二条的结果用来参考。这样既保证了质量底线,又不漏掉潜在问题。5.3 审查数据沉淀:从历史结果里挖价值审查结果别看完就扔,攒起来有价值。攒够几百次审查记录,你能分析出很多东西。比如哪些文件问题最多,说明这些文件该重构了。哪些规则触发最频繁,说明这些规则对应的编码习惯需要团队统一。哪些问题反复出现,说明需要写进团队规范或者做成培训材料。数据沉淀的关键是结构化存储。审查结果输出成 JSON,存到数据库或日志系统:ocr review --staged --format json >> reviews.jsonl然后定期分析:import json from collections import Counter issues = [] with open('reviews.jsonl') as f: for line in f: review = json.loads(line) issues.extend(review['issues']) # 统计问题最多的文件 file_counts = Counter(i['file'] for i in issues) print(file_counts.most_common(10)) # 统计最常见的规则触发 rule_counts = Counter(i['rule'] for i in issues) print(rule_counts.most_common(10))这些数据拿去做季度技术复盘,比拍脑袋讨论有用得多。5.4 和 CI 集成:让审查成为流水线的一环最后一步是把审查集成到 CI 里,让它成为流水线的固定环节。在 GitHub Actions 里,可以这样配:name: Code Review on: [pull_request] jobs: review: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 with: fetch-depth: 0 - name: Run review run: | npm install -g open-code-review ocr review --branch origin/main --format markdown > review.md - name: Comment PR uses: actions/github-script@v6 with: script: | const fs = require('fs'); const body = fs.readFileSync('review.md', 'utf8'); github.rest.issues.createComment({ issue_number: context.issue.number, owner: context.repo.owner, repo: context.repo.repo, body: body });这样每个 PR 提上来,CI 自动跑审查,结果直接评论在 PR 里。reviewer 打开 PR 就能看到 Agent 的审查结果,省去了自己找机械性问题的功夫。fetch-depth: 0这个配置很关键,它让 checkout 拉取完整历史,否则--branch origin/main找不到对比基准。6. 关于工具选型和长期维护的一点个人看法聊了这么多实操,最后说点选型和维护上的个人体会。选工具别只看功能列表,要看它能不能嵌进你现有的工作流。一个功能再强但需要你改变工作习惯的工具,大概率用不长。open-code-review 这类工具的核心竞争力,就是它能嵌进 Git 工作流,你该干嘛干嘛,它在你提交的时候顺手帮你审一遍。维护上,最重要的是定期回顾审查结果。工具是死的,规则是活的。团队在变,代码风格在变,规则也得跟着变。我一般每个月花半小时看看这个月的审查记录,把误报的规则调一调,把漏报的场景补一补。这半小时的投入,换来的是下个月审查结果可用性的提升。还有一点,别指望 Agent 完全替代人工审查。它的定位是"第一道筛子",把机械性问题筛掉,让人专注于真正需要判断力的地方。想清楚这个定位,你就不会对它有不切实际的期待,也不会因为它偶尔误报就弃用。代码审查这件事,本质上是团队协作的一部分。工具能优化流程,但替代不了人和人之间的沟通。open-code-review 的价值,是让沟通发生在更有价值的地方——不是"你这个变量名不对",而是"这个设计我觉得可以再想想"。把低级问题交给机器,把高级问题留给人,这才是它真正的意义。
代码审查这件事,做了十几年,我最大的感受是:真正拖慢团队的从来不是写代码的速度,而是等别人帮你看代码的时间。一个 PR 提上去,运气好半天有人理,运气不好压两天,改完再等一轮,一个本来半小时能合的小功能硬是拖成三天。所以当"open-code-review"这个概念出来的时候,我第一反应不是"又一个工具",而是"终于有人把这件事想明白了"——把代码审查从"等人"变成"随时可跑",用 CLI 加 LLM Agent 的方式,让审查这件事变得像跑一条命令那么简单。这篇文章我想聊的不是某个具体产品的使用手册,而是围绕 open-code-review 这个方向,把 CLI、LLM Agent、Git 工作流这几块拼在一起,讲清楚它到底解决了什么问题、底层是怎么运转的、实际落地时会踩哪些坑。不管你是刚接触 Git 的新手,还是已经带团队的老手,只要你对"让代码审查更快更稳"这件事有兴趣,这里应该都能找到能直接抄作业的东西。1. 为什么代码审查需要一次"去中心化"改造1.1 传统 PR 审查的三个隐性成本大部分人谈代码审查,谈的都是"质量"。但真正在一线待过就知道,质量只是明面上的收益,真正吃掉团队效率的是三个隐性成本。第一个是等待成本。一个 PR 从提交到有人开始看,中间的空窗期完全取决于 reviewer 什么时候有空。我统计过我们团队半年的数据,平均等待时间是 4.7 小时,最长的压了 31 小时。这期间提交者要么干等,要么切去别的任务,上下文切换的损耗比等待本身还贵。第二个是沟通成本。同一个问题,reviewer 在评论里写一遍,提交者理解一遍,改完再解释一遍。遇到表达不清的,来回三四轮很正常。很多评论其实是"这个变量名能不能改一下"这种一句话的事,但走完整个 PR 流程,成本被放大了十倍。第三个是一致性成本。不同 reviewer 关注点完全不一样,A 只看逻辑,B 只看命名,C 只看有没有测试。结果就是同一个仓库里,代码风格飘忽不定,因为审查标准本身就不统一。这三个成本加起来,才是"代码审查拖慢团队"的真相。而 open-code-review 这个方向的价值,恰恰是冲着这三个成本去的。1.2 CLI 加 LLM Agent 到底改变了什么先说清楚一个概念,很多人把 CLI 和 LLM Agent 混着说,其实它们是两层东西。CLI是命令行界面,它解决的是"入口"问题。以前你要审查代码,得打开网页、找到 PR、点开 diff、逐行看。现在你只需要在终端敲一条命令,比如ocr review --staged,它就把当前暂存区的改动拉出来审。入口从"网页"变成"终端",意味着审查可以嵌入到你本来就在用的工作流里,不用切换上下文。LLM Agent是执行审查的主体,它解决的是"谁来审"的问题。传统审查必须有人,Agent 的价值是它可以 7x24 小时在线,你提交完立刻就能拿到第一轮反馈。注意我说的是"第一轮",Agent 不是替代人,而是把人从"找低级问题"里解放出来,让人的精力集中在架构、业务逻辑这些真正需要判断力的地方。这两者结合,本质上是把代码审查从"事件驱动"(等人来看)变成"命令驱动"(随时可跑)。这个转变听起来小,实际影响很大——它让审查从流程的瓶颈变成了流程的常规环节。1.3 一个真实场景:从提 PR 到拿到反馈的时间差我拿我们团队一个真实案例对比一下。改造前:小王写完一个用户鉴权模块,提了 PR。上午 10 点提的,reviewer 在开会,下午 2 点才看。看完提了 6 条意见,其中 3 条是"这里没做空值判断""这个函数超过 50 行了""缺少单元测试"这种机械性问题。小王改完已经下午 4 点,再等 reviewer 二次确认,第二天上午才合。改造后:小王写完,在终端跑ocr review,30 秒后拿到反馈,其中 3 条机械性问题当场就改了。改完再提 PR,reviewer 下午 2 点看的时候,看到的已经是一个干净版本,只提了 2 条关于业务边界的意见。当天下午就合了。时间差从"跨天"变成"当天",关键就在于把机械性问题的发现提前到了提交之前。这就是 open-code-review 最朴素也最实在的价值。2. open-code-review 的核心组件拆解2.1 CLI 层:命令设计背后的取舍一个 code review CLI 好不好用,看它的命令设计就知道。我见过太多工具,功能很全但命令设计反人类,最后没人用。好的 CLI 设计有几个原则。第一是默认行为要符合直觉。比如ocr review不带参数时,应该默认审查当前工作区未提交的改动,因为这是最高频的场景。第二是参数要少而精,不要搞出二十个 flag,常用的就那几个:指定审查范围(--staged、--commit、--branch)、指定输出格式(--json、--markdown)、指定严重级别过滤(--severity high)。我实际用下来,最顺手的命令组合是这样的:# 审查暂存区改动,只看高优先级问题 ocr review --staged --severity high # 审查某个 commit ocr review --commit abc1234 # 审查当前分支相对 main 的所有改动 ocr review --branch main --format markdown > review.md这里有个设计细节值得说:为什么要有--format markdown?因为审查结果经常需要贴到 PR 评论里,直接输出 markdown 就能复制粘贴,省去手动整理的功夫。这种"为下游场景考虑"的设计,才是 CLI 工具真正好用的关键。2.2 LLM Agent 层:它到底在"审"什么很多人以为 LLM Agent 审查代码就是"把代码丢给模型,让它挑毛病"。实际远不止这么简单。一个成熟的审查 Agent,内部至少要做四件事。第一是上下文构建。光看 diff 是不够的,Agent 需要知道这个改动所在的文件长什么样、被调用的地方有哪些、相关的类型定义是什么。所以它要先做一轮上下文收集,把 diff 周围的代码、相关的 import、被修改函数的调用方都拉进来。第二是规则匹配。Agent 内部通常有一套规则库,比如"函数不超过 50 行""禁止裸 except""SQL 必须参数化"。这些规则一部分是通用的,一部分是项目自定义的。Agent 会先跑规则匹配,把确定性问题标出来。第三是语义分析。这部分才是 LLM 的强项,比如"这个循环的时间复杂度是 O(n²),数据量大了会慢""这个错误处理吞掉了异常,出问题排查不到"。这类问题规则匹配不出来,必须靠模型理解代码意图。第四是优先级排序。Agent 不能把所有问题都平铺给你,那样等于没审。它要按严重程度排序,把"会导致线上故障"的排在"命名不规范"前面。这个排序逻辑,直接决定了审查结果有没有用。2.3 Git 集成层:diff 是怎么被"喂"给 Agent 的这一层是最容易被忽略,但最容易出问题的。Git 的 diff 机制有很多细节,处理不好就会导致 Agent 看到错误的代码。首先要区分几种 diff 场景。git diff看的是工作区和暂存区的差异,git diff --staged看的是暂存区和最后一次提交的差异,git diff HEAD看的是工作区和最后一次提交的差异。这三个场景对应不同的审查需求,CLI 必须能准确区分。其次是diff 的上下文行数。默认 diff 只显示改动行前后各 3 行,但审查代码时 3 行往往不够。比如你改了一个函数的返回值,Agent 需要看到这个函数完整的签名和前面的逻辑,才能判断改动是否合理。所以好的实现会把上下文行数调大,比如前后各 10 行。还有一个坑是重命名和移动。Git 有时会把"重命名文件"识别成"删除旧文件+新增新文件",导致 diff 里出现大量无关内容。这时候需要用git diff -M开启重命名检测,让 diff 更干净。# 开启重命名检测,上下文 10 行 git diff --staged -M -U10这个命令是很多 CLI 工具内部实际调用的,理解它有助于你排查"为什么 Agent 看到的内容不对"这类问题。2.4 输出层:审查结果怎么呈现才有用审查结果呈现得好不好,直接决定这个工具会不会被用第二次。我见过最糟糕的呈现方式,是把所有问题一股脑输出成一大段文字,看完眼睛都花了。好的输出应该分层。第一层是摘要,一句话告诉你"这次审查发现 3 个高优先级、5 个中优先级问题"。第二层是问题列表,每条包含文件路径、行号、问题描述、修复建议。第三层是详情,点开某条能看到具体的代码片段和更详细的解释。用表格呈现问题列表是最清晰的:严重级别文件行号问题建议高auth.py42未校验用户输入增加参数校验中auth.py67函数过长(78行)拆分为子函数低auth.py12变量命名不清晰改为 user_token这种呈现方式,扫一眼就知道该先改哪个,比一大段文字强太多。3. 从零跑通一次 open-code-review 的完整流程3.1 环境准备:Git 和 CLI 的安装配置在跑 open-code-review 之前,Git 环境必须先配好。这块看起来基础,但新手最容易在这里卡住。Windows 上装 Git,直接去官网下载安装包,一路下一步就行。但有两个选项要注意:一是"Adjusting your PATH environment",选"Git from the command line and also from 3rd-party software",这样终端里才能直接用 git 命令;二是"Configuring the line ending conversions",选"Checkout Windows-style, commit Unix-style line endings",避免跨平台协作时换行符出问题。装完之后验证一下:git --version # 输出类似 git version 2.43.0然后配置用户信息,这是提交代码的前提:git config --global user.name "你的名字" git config --global user.email "你的邮箱"如果是团队协作,建议再配一下默认分支名和 pull 策略:git config --global init.defaultBranch main git config --global pull.rebase truepull.rebase true这个配置我强烈建议开,它能让你的提交历史保持线性,避免出现一堆无意义的 merge commit。审查代码时,线性的历史看起来清爽太多。CLI 工具本身的安装,通常是通过包管理器。比如 npm 生态的:npm install -g open-code-review或者用 pip:pip install open-code-review装完跑ocr --version验证。如果提示找不到命令,八成是 PATH 没配好,检查一下包管理器的全局 bin 目录有没有加到 PATH 里。3.2 第一次审查:从 staged 改动开始环境配好,先拿最简单的场景练手——审查暂存区的改动。假设你改了auth.py,先git add到暂存区,然后跑:ocr review --staged第一次跑通常会让你配置 API key 或者选择模型。这里有个经验:先用小模型跑通流程,再换大模型。因为第一次跑主要是验证环境通不通,用大模型纯属浪费。等流程跑通了,再换成能力更强的模型做正式审查。跑通之后你会看到类似这样的输出:Reviewing 1 file, 3 changes... [HIGH] auth.py:42 - 用户输入未做校验,存在注入风险 建议:使用参数化查询或输入白名单校验 [MEDIUM] auth.py:67 - 函数 validate_token 长度 78 行,超过建议阈值 50 行 建议:拆分为 token 解析和 token 校验两个函数 [LOW] auth.py:12 - 变量名 t 含义不明确 建议:改为 user_token Summary: 1 high, 1 medium, 1 low看到这个输出,说明整条链路已经通了。3.3 把审查嵌进 Git 工作流:pre-commit 钩子跑通单次审查只是第一步,真正提升效率的是把它嵌进 Git 工作流,让它在每次提交前自动跑。Git 的 pre-commit 钩子就是干这个的。在.git/hooks/目录下创建pre-commit文件:#!/bin/bash ocr review --staged --severity high if [ $? -ne 0 ]; then echo "发现高优先级问题,提交已阻止" exit 1 fi然后给它执行权限:chmod +x .git/hooks/pre-commit这样每次git commit之前,都会自动跑一次审查。如果发现高优先级问题,提交会被阻止,逼着你先改。这里有个坑要注意:钩子文件不会被提交到仓库。.git/hooks/目录是本地目录,团队其他人 clone 下来是没有这个钩子的。所以团队协作时,要么每个人手动配,要么用 husky 这类工具把钩子配置纳入版本管理。用 husky 的话,配置是这样的:{ "husky": { "hooks": { "pre-commit": "ocr review --staged --severity high" } } }这样钩子配置跟着仓库走,新人 clone 下来跑一下npm install就自动装好了。3.4 审查历史提交:补审和批量审查有时候改动已经提交了,才发现没审。这时候可以用--commit参数补审:ocr review --commit abc1234如果要审查一个分支上所有的提交,用--branch:ocr review --branch main这个命令会审查当前分支相对 main 的所有改动。适合在提 PR 之前做一次全面自查。批量审查时有个性能问题要注意:如果分支上提交很多,一次性全审会很慢。这时候可以加--since参数限制时间范围:ocr review --branch main --since "3 days ago"只审最近三天的改动,速度快很多。4. 实际落地时踩过的坑和应对方案4.1 误报太多:怎么调教审查规则刚上手 open-code-review 的人,十有八九会遇到这个问题:误报太多。Agent 把一堆不是问题的地方标成问题,看多了就烦,最后干脆不看了。误报的来源主要有三个。第一是规则太严,比如把"函数超过 50 行"当成硬性规则,但有些函数就是天然长,硬拆反而更乱。第二是上下文不足,Agent 没看到完整的代码,误判了某段逻辑。第三是模型理解偏差,把正常的写法当成错误。应对方案是分层调教。先调规则,把明显不合理的规则关掉或放宽阈值。再调上下文,增大 diff 的上下文行数。最后调模型,如果某个模型误报率一直很高,换一个试试。配置文件通常长这样:rules: function_length: enabled: true threshold: 80 # 从 50 放宽到 80 naming: enabled: true severity: low # 命名问题降级为低优先级 context: lines: 15 # 上下文从 10 行增加到 15 行调教是个渐进过程,别指望一次配好。我的经验是,前两周每周调一次,之后基本就稳定了。4.2 大文件审查超时:分片策略审查大文件时,很容易遇到超时。因为 LLM 有上下文长度限制,一个几千行的文件塞进去,要么超时要么被截断。解决方案是分片。把大文件按函数或类拆成小块,逐块审查。好的 CLI 工具会自动做这件事,但你需要知道它的分片逻辑,才能判断结果是否可靠。分片有个原则:不能把有依赖关系的代码拆开。比如一个函数调用了另一个函数,这两个函数最好放在同一片里审,否则 Agent 看不到调用关系,容易误判。如果工具不支持自动分片,可以手动指定审查范围:# 只审查某个文件的某个函数范围 ocr review --file auth.py --lines 40-1204.3 敏感信息泄露:审查前的脱敏处理这是最容易被忽略但最危险的一个坑。代码里经常会有硬编码的密钥、token、内部地址,如果直接丢给 LLM 审查,这些信息就泄露了。审查前必须做脱敏。常见做法是用正则匹配敏感模式,替换成占位符:import re patterns = [ (r'(api[_-]?key\s*=\s*["\'])[^"\']+', r'\1***REDACTED***'), (r'(password\s*=\s*["\'])[^"\']+', r'\1***REDACTED***'), (r'(token\s*=\s*["\'])[^"\']+', r'\1***REDACTED***'), ] def redact(code): for pattern, replacement in patterns: code = re.sub(pattern, replacement, code, flags=re.IGNORECASE) return code更稳妥的做法是在 CI 层面加一道检查,提交前扫描敏感信息,发现就阻止。这样从源头上避免敏感信息进入代码库。注意:脱敏不是可选项,是必选项。尤其是团队协作场景,一次泄露可能造成不可逆的损失。4.4 审查结果和人工审查冲突:怎么协调最后一个坑是流程上的:Agent 说没问题,但人工审查发现了问题,或者反过来。这时候怎么协调?我的做法是明确分工。Agent 负责机械性问题:格式、命名、明显的逻辑错误、缺失的测试。人工负责判断性问题:架构是否合理、业务逻辑是否正确、边界条件是否覆盖。这样分工之后,冲突就少了。因为两者关注的根本不是同一类问题。如果 Agent 报了人工觉得不是问题的,那多半是规则需要调;如果人工发现了 Agent 没报的机械性问题,那多半是规则库需要补。定期回顾这些冲突,把它们转化成规则或提示词的改进,Agent 的准确率会越来越高。5. 把 open-code-review 用出花来的几个进阶思路5.1 自定义规则:让 Agent 懂你的项目规范通用规则只能覆盖 60% 的场景,剩下 40% 是项目特有的。比如你们团队规定"所有数据库操作必须走 Repository 层",这种规则通用工具不知道,得自己加。自定义规则通常有两种写法。一种是声明式的,用 YAML 描述:rules: - id: no-direct-db-access description: 禁止在 Service 层直接访问数据库 pattern: "from.*models import.*Model" files: "services/**/*.py" severity: high message: "Service 层应通过 Repository 访问数据库"另一种是编程式的,写个函数:def check_repository_pattern(context): issues = [] for file in context.files: if 'services/' in file.path: if 'from models import' in file.content: issues.append(Issue( file=file.path, severity='high', message='Service 层禁止直接导入 Model' )) return issues声明式适合简单规则,编程式适合复杂逻辑。实际项目里两种混着用。5.2 多模型对比:不同模型的审查风格差异不同 LLM 审查代码的风格差异很大,这点很有意思。我实测下来,有的模型偏保守,只报确定的问题,漏报多但误报少;有的模型偏激进,什么都报,误报多但漏报少。实际使用时,可以组合着来。保守模型做门禁,它报的问题基本都要改;激进模型做参考,它报的问题人工筛一遍,挑有价值的改。如果 CLI 支持多模型,可以这样配:ocr review --staged --model conservative --severity high ocr review --staged --model aggressive --format markdown > suggestions.md第一条命令的结果用来卡提交,第二条的结果用来参考。这样既保证了质量底线,又不漏掉潜在问题。5.3 审查数据沉淀:从历史结果里挖价值审查结果别看完就扔,攒起来有价值。攒够几百次审查记录,你能分析出很多东西。比如哪些文件问题最多,说明这些文件该重构了。哪些规则触发最频繁,说明这些规则对应的编码习惯需要团队统一。哪些问题反复出现,说明需要写进团队规范或者做成培训材料。数据沉淀的关键是结构化存储。审查结果输出成 JSON,存到数据库或日志系统:ocr review --staged --format json >> reviews.jsonl然后定期分析:import json from collections import Counter issues = [] with open('reviews.jsonl') as f: for line in f: review = json.loads(line) issues.extend(review['issues']) # 统计问题最多的文件 file_counts = Counter(i['file'] for i in issues) print(file_counts.most_common(10)) # 统计最常见的规则触发 rule_counts = Counter(i['rule'] for i in issues) print(rule_counts.most_common(10))这些数据拿去做季度技术复盘,比拍脑袋讨论有用得多。5.4 和 CI 集成:让审查成为流水线的一环最后一步是把审查集成到 CI 里,让它成为流水线的固定环节。在 GitHub Actions 里,可以这样配:name: Code Review on: [pull_request] jobs: review: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 with: fetch-depth: 0 - name: Run review run: | npm install -g open-code-review ocr review --branch origin/main --format markdown > review.md - name: Comment PR uses: actions/github-script@v6 with: script: | const fs = require('fs'); const body = fs.readFileSync('review.md', 'utf8'); github.rest.issues.createComment({ issue_number: context.issue.number, owner: context.repo.owner, repo: context.repo.repo, body: body });这样每个 PR 提上来,CI 自动跑审查,结果直接评论在 PR 里。reviewer 打开 PR 就能看到 Agent 的审查结果,省去了自己找机械性问题的功夫。fetch-depth: 0这个配置很关键,它让 checkout 拉取完整历史,否则--branch origin/main找不到对比基准。6. 关于工具选型和长期维护的一点个人看法聊了这么多实操,最后说点选型和维护上的个人体会。选工具别只看功能列表,要看它能不能嵌进你现有的工作流。一个功能再强但需要你改变工作习惯的工具,大概率用不长。open-code-review 这类工具的核心竞争力,就是它能嵌进 Git 工作流,你该干嘛干嘛,它在你提交的时候顺手帮你审一遍。维护上,最重要的是定期回顾审查结果。工具是死的,规则是活的。团队在变,代码风格在变,规则也得跟着变。我一般每个月花半小时看看这个月的审查记录,把误报的规则调一调,把漏报的场景补一补。这半小时的投入,换来的是下个月审查结果可用性的提升。还有一点,别指望 Agent 完全替代人工审查。它的定位是"第一道筛子",把机械性问题筛掉,让人专注于真正需要判断力的地方。想清楚这个定位,你就不会对它有不切实际的期待,也不会因为它偶尔误报就弃用。代码审查这件事,本质上是团队协作的一部分。工具能优化流程,但替代不了人和人之间的沟通。open-code-review 的价值,是让沟通发生在更有价值的地方——不是"你这个变量名不对",而是"这个设计我觉得可以再想想"。把低级问题交给机器,把高级问题留给人,这才是它真正的意义。