面对智能体产出的海量代码,你该如何进行审查?在 Claude Code 团队,当我们实现了高覆盖率和深入审查之后,就开始着手优化:在不增加回滚或事故的前提下,把人工审查时间降到最低。
原文:How the Claude Code team does code review
作者:Addy Osmani、Morgan Westlee Lunt 和 Qing Wang
分类:工程
原文发布日期:2026 年 10 月 15 日
原文阅读时间:14 分钟
本文根据所提供的英文正文翻译。原文图表中的文字和数据以表格、列表呈现。
我们以前说过,Claude Code 自身大约 90% 的代码由 Claude 编写。那么,面对我们产出代码的规模,该如何进行审查?现在还有人读代码吗?如果出了问题,又由谁发现?
这篇文章介绍了 Claude Code 团队的代码审查流程,以及它是如何演变的。从 6 月到 9 月,Claude Code 代码库中合并的拉取请求数量翻了一倍多,而不得不回滚的比例下降了 40% 以上。
我们没有取消审查。但我们确实把大部分阅读工作交给了机器,围绕人的时间和注意力进行优化,并投入大量精力,让撤销错误变得快捷、容易。
重新思考代码审查的目的
当智能体开始写代码,变更的数量就会迅速增长。在 Anthropic 的单体仓库中,今年每天合入的变更数量,从 5 月的约 2,500 次增长到了 9 月的超过 30,000 次。
Claude Code 使用独立的仓库,与单体仓库分开,但它也承受着很大的压力。当交付速度如此之快时,人工逐行审查代码即使并非不可能,也极其困难。
代码审查承担两项工作:
- 在交付之前发现并修复问题。
- 在团队中建立共享的上下文,以及对代码库的理解。
本文主要关注发现和修复问题,但会在接近结尾时回到第二项工作。
我们认为,“有没有人读过代码?”并不能准确代表真正应该问的问题:“这次变更可能出什么问题,哪一种检查——自动检查还是人工检查——最适合发现它?”
提出这个问题,也改变了审查发生的时机。过去,审查是路尽头的一道关卡:写代码、发起 PR,然后等同事来看。
现在,审查是持续进行的,更像写作时的拼写检查。大多数变更在请人查看之前,已经由 Claude 审查并修复过至少一次。这能发现大多数常规错误,把团队的注意力留给更高层次的问题和审视。
稀缺资源:人的时间和注意力
我们希望把人的时间和注意力留给只有人才能解决的问题,并确保自动检查能发现其余问题。以我们目前的变更速度,仍有大量工作需要人来完成,团队几乎每天都会遇到全新的挑战。
人的时间涵盖了审查成本的两个方面:人们花在审查上的时间,以及修复糟糕代码所造成破坏的时间。如果省下前者,却只是让这些时间出现在后者上,那就没有帮助。
因此,我们的目标是:Claude Code 各个仓库中的大多数拉取请求,包括 CLI、桌面与 Web 应用,以及移动应用,合并时最多只需要一个人参与,这个人也可以是作者本人,同时不增加回滚或事故。为了衡量人的时间,我们跟踪每个 PR 的人工批准次数(中位数和第 95 百分位数)、人工评论,以及 PR 等待人工处理的时长。回滚率和事故率是护栏:如果它们上升,我们就没有节省人的时间,只是把时间转移到了别处。
一次变更的生命周期
一次典型变更,从工程师的笔记本电脑出发,或者从 Slack 中的一次 Claude 会话出发,会经过多层代码审查。
一次变更的生命周期
一次典型的 Claude Code 变更,从作者的机器到用户手中:
| 阶段 | 环节 | 内容 |
|---|---|---|
| 发起拉取请求之前 | 验证工作成果 | Claude 运行测试、构建和 lint 检查;第二个智能体在全新的上下文中审查代码差异。 |
| 每个拉取请求都要经过 | 必须通过的 CI | lint、类型检查、跨平台测试、构建和打包。检查失败会阻止合并。 |
| 每个拉取请求都要经过 | Claude 代码审查 | 多个智能体并行寻找缺陷,验证者对每项发现投票,保留下来的发现按严重程度排序。 |
| 每个拉取请求都要经过 | 安全审查 | 单独进行一轮审查。两种审查中任何尚未解决的发现都会阻止合并。 |
| 每个拉取请求都要经过 | 基于风险的批准 | 分类器确定等级:无需人工、一人或两人。有些路径始终需要人工。 |
| 合并时 | 合并队列 | 将变更应用到最新的 main 分支后,再运行一遍检查。 |
| 合并之后 | 放在功能开关后,先供内部使用 | Anthropic 员工先使用,然后才面向所有人。 |
| 合并之后 | 逐步发布 | 先发布到 latest 通道;stable 通道随后跟进。 |
| 合并之后 | 观察、向前修复或回滚 | 作者和值班人员持续观察;功能开关可以迅速关闭,出问题的构建会被回滚。 |
图例:自动执行;由人决定,参与程度随风险调整;恢复。
图 A:大部分流程是自动化的;人的注意力投向风险所在。
逐层来看
多层防线,而非单一关卡
六层检查,下方还有回滚兜底:
问题进入 → 验证 → 必须通过的 CI → AI 审查 → 安全审查 → 人工批准 → 合并队列与功能开关 → 快速回滚。
图 B:每一层都会发现一些问题,也会漏掉另一些问题。很少有问题能穿过所有层,回滚负责处理剩下的情况。
1. 在其他人查看之前,先验证工作成果
现在,大多数审查发生在 PR 创建之前。我们给 Claude 可以运行的东西,比如测试、构建,或者一张可用来与设计对比的截图,并要求它展示输出,而不只是说已经完成。然后,由一个子智能体在全新的上下文中审查代码差异。这两种习惯都来自我们的最佳实践指南。
在发起 PR 之前,我们中的许多人还会运行几个内部技能:一个寻找缺陷,一个简化代码差异,还有一个从端到端检查行为。UI 变更还会按照我们的设计规范进行检查。
Claude Code 的创建者 Boris Cherny 曾说,为 Claude 提供验证自身工作的方法,可能是获得良好结果最重要的一件事。他估计,这能让最终结果好上两到三倍,并写道:“不同领域的验证方式各不相同。它可能简单到只需运行一条 bash 命令,也可能是运行一套测试,或者在浏览器或手机模拟器中测试应用。”
当自动审查者不断指出同一类问题时,我们就从源头解决:修改技能、增加 lint 规则,或者更新指令文件,例如:
CLAUDE.md告诉 Claude 这个项目是什么:技术栈、约定、目标,以及非目标。每次审查都会加载它,所以在大型代码库中,我们会让它保持简短,并从中链接到其他文档。审查者也会指出违反其中约定的代码,以及使其中某一行内容过时的变更。REVIEW.md由代码负责人编写,告诉审查者,他们负责的代码中哪些事情重要。我们会单独检查审查者是否真的遵循了它。好的REVIEW.md都很短。它们会说明这个仓库中的失败是什么样子(对文档来说是“说错了”,对配置来说是“路由错了”),限制细枝末节意见的数量,列出应当跳过的路径,并要求用文件和行号作为证据,而不是根据名字猜测。它们还要求总结以数量开头,并在没有需要修复的问题时直说。
2. 每个拉取请求都进行 AI 审查
每个拉取请求在人工查看之前,都会先接受一次 Claude 审查。它会结合整个仓库和 PR 声明的意图来阅读代码差异,并提出问题:这个变更解决了它要解决的问题吗?它与系统契合吗?它会破坏其他东西吗?
对于缺陷修复,它会寻找根本原因。公开版本 Code Review for Claude Code 现已在 Team 和 Enterprise 套餐中正式推出,而 /code-review 可以在本地运行一个轻量版本。
当我们推出研究预览版时,收到实质性审查评论的内部 PR 比例从 16% 上升到了 54%。超过 1,000 行的 PR 大多会被发现问题,而大多数小 PR 则会干净地通过。管理员为每个仓库选择 Quick、Standard 或 Deep。当漏掉一个缺陷的代价高于额外审查时间的成本时,Deep 就值得使用。
在人工审阅发现之前,其他智能体会先验证这些发现。几个智能体同时寻找缺陷,然后由另一组智能体对每项发现投票;只有当足够多的智能体同意问题确实存在时,它才会被发布。仅涉及风格、诊断或清理的发现会被丢弃。我们先在自己的 PR 上对这些过滤器进行了 A/B 测试,然后才保留它们。剩下的发现会以行内评论的形式出现,并按严重程度排序。每条评论都会标记为 Important(重要)、Nit(细节)或 Pre-existing(已有问题),这样,PR 没有引入的缺陷就不会看起来像是作者的责任。
每项发现都必须得到回应。要么修复,要么说明理由并将讨论标记为已解决。智能体经常会在夜间接手修复,所以作者回来时,PR 已经又经历了一轮处理。
3. 能够阻止合并的安全审查
安全也有自己独立的自动审查。只要缺陷审查或安全审查中还有任何一项发现未解决,PR 就不能合并。你要么修复问题,要么简要说明理由并关闭讨论;误报就是这样清除的。
如果后续提交修复了问题,这项发现会自动清除。你也可以使用开源的安全审查 GitHub Action,或者 /security-review 命令,配置同样的机制。设置方法见 Claude Code 中的自动安全审查。
4. 能够阻止合并的自动检查
就是那些常见项目:lint、类型检查、各个平台上的测试,以及构建。(我们曾在这里介绍过如何扩展 CI 来应对这样的规模。)一个典型的 CLI 拉取请求,在任何人查看之前,可能已经运行了几十项检查。PR 模板会询问如何测试这次变更,以及如何撤销它。Claude 可以填写这些内容,但提出变更需求的人必须确认。
5. 按风险调整人工批准要求
修正文档和修改自动更新程序的风险不同,因此它们接受的审查也不同。
| 风险 | 示例 | 人工批准 |
|---|---|---|
| 低 | 文档、文案、仅限内部使用的功能、放在功能开关后的新增变更 | 自动审查和安全检查全部通过后,无需人工批准 |
| 中 | 常规产品变更,以及涉及缓存、自动更新程序或系统提示词等敏感区域的变更 | 一人 |
| 高 | 风险最高的代码,以及少数始终需要两人批准的路径 | 两人 |
等级由变更决定,而不是由作者决定。一个分类器阅读变更,选择它的风险等级。第二个分类器会进一步判断:即使等级要求不需要,这个具体变更是否仍然需要另一个人参与。有些路径始终需要人工,包括负责人列为敏感的所有内容,以及任何 CI 工作流文件。
只有受信任的作者才能使用更宽松的流程。只有列在仓库信任名单中的作者才能使用更宽松的流程,主要是负责该仓库的团队。其他人都需要第二个人批准。智能体的批准也永远不能算作人的批准。自动审查可以放行低风险变更,但不能顶替一个明确要求人工参与的名额。
谁发出指令要求进行变更,谁就要为它负责。在智能体编写的 PR 中,指挥智能体的人算作所需审查者中的一位,就像代码是他们亲手敲出来的一样。
一次批准只覆盖一个特定提交。如果又有系统无法担保的新提交加入,例如智能体推送的提交,或有人手动解决冲突后的合并,就必须重新批准。
6. 合并队列、功能开关与逐步发布
合并队列会将变更应用到 main 分支后,重新运行所有检查,这样两个分别通过检查的 PR 就不会组合成一个出问题的 main 分支。新行为通常先放在功能开关后,发布给 Anthropic 员工;我们的高强度使用经常能在用户遇到之前暴露回归问题。公开版本先发布到 latest 通道,stable 通道随后跟进。
7. 快速发现,快速回滚
仍然会有一些错误穿过防线,因此最后一层关注的是迅速发现它们。关闭功能开关不需要部署。Claude Code 实行每周轮换的值班制度,事故复盘会追问:本来应该由哪一层发现这个问题?
发现有问题的合并,仍然依赖作者、值班人员,以及回滚和事故看板。我们还没有能在这些数字变化时自动收紧批准要求的熔断机制;这里的工程师希望,在更多代码转向零人工合并之前,先把它们建立起来。
一位同事说,放慢速度确实能降低出错率,但主要是因为你做的所有事情都变少了。我们更愿意提高发现和修复问题的速度。
我们如何改进审查者
我们的代码审查流程正在一个循环中不断改进。
现在,每一次事故都会成为一项评测。团队收集了过去引发事故的 PR,以及对应的向前修复和回滚,并请熟悉相关代码的工程师确认每个缺陷及其所在位置。审查者每天都会在这套数据集上运行。
我们的事故就是评测集
由过去的事故和回滚构建,每天运行:
| 步骤 | 内容 |
|---|---|
| 事故或回滚 | 某次变更破坏了某些东西。 |
| 经专家核验的案例 | 专家确认缺陷。 |
| 加入数据集 | 每次事故都增加一个案例。 |
| 修改审查者 | 修改它的提示词、工具或模型。 |
| 每日评测运行 | 对每个案例进行评分。 |
| 分数提高了吗? | 提高就保留,否则舍弃。 |
| 下一次变更 | 进入下一轮。 |
图 C:每次事故都会扩充评测集,审查者的每次改动都要在整个评测集上评分。
我们通过观察人们如何处理评论来衡量噪声。如果你不介意把大量并非缺陷的内容也标记出来,那发现更多缺陷并不难,因此我们需要对此进行约束。我们按照 PR 参与者的回应,对审查者留下的每条评论进行分类:修复了问题、认为评论有误、说明该行为是有意为之,或决定这个问题并不重要。我们还会让审查者运行在已知没有问题的 PR 上,统计它多大概率会报告某个问题,而这个报告本来会引导人做出有害的修改。我们明确写下的优先级是:首先发现真正的缺陷,其次减少审查轮次。
当作者是智能体时,噪声的成本更高。人可以在几秒钟内忽略一个无关紧要的小意见。智能体却会去修复它,这意味着又一个提交,以及又一轮审查。
审查必须收敛。智能体作者和智能体审查者可能会让彼此无休止地忙下去。有一个 CLI PR 在一夜之间经历了五十多轮审查和修复,最后才被作者叫停。
当我们对审查者反复指出的内容运行 git blame 时,发现其中约 59% 的代码从审查者第一轮审查时就已经存在。审查者很少是在发现新缺陷,而是在每一轮多找到几个旧缺陷。
我们自己也让情况变得更糟了。因为每一轮都能发现新东西,我们已经习惯默认运行好几轮。对于高风险变更,这可能值得,但不应该对每个 PR 都这么做。团队现在除了跟踪召回率,也会跟踪通过审查所需的轮次,并调整了再次审查的方式:
- 设置轮次上限。三轮之后,审查者会请作者退一步,重新考虑实现方案。
- 前几轮之后,只重新审查代码差异。
- 指出缺陷的类别,让作者修复所有同类实例,而不只是一行。
- 不重复已经发布过的发现。
审查智能体也会每晚扫描现有代码,帮助我们在旧缺陷出现在其他地方之前发现它们。
能够收敛的审查
收敛改进前后的内部拉取请求:
| 指标 | 改进前 | 收敛改进后 |
|---|---|---|
| 一轮审查与修复后通过 | 65% | 78% |
| 需要五轮或更多轮 | 8.9% | 1.5% |
| 通过所需的平均审查次数 | 2.08 | 1.32 |
图 D:收敛改进后,每个内部拉取请求需要的审查轮次更少了。
哪些环节仍然需要人参与
让一位资深工程师从深度工作中抽身,去发现一个常规错误,成本远高于自动审查。在 Anthropic,我们的工作已经从阅读每一份代码差异,转向机器不擅长的决策:
- 我们到底该不该做这件事?方向、品味和范围。有个团队宣布解决了审查瓶颈,却仍然保留对团队外部变更的人工审查,就是为了有人问一句:“我们究竟该不该做这个?”
- 有风险的代码,例如计费、自动更新程序和 CI 工作流。
- 会成为他人效仿范式的架构。
- 阅读证据。测试输出、运行的命令及其返回结果、截图、审查者的发现。如果你说不清检查会漏掉什么,就应该要求一次真正的审查,而不是快速批准。
- 为结果负责。每一项交付的变更都有一个人负责,无论代码是谁敲的。
由人做决定的地方
五项决策留给人;其余地方运行检查:
- 我们该做它吗?
- 有风险的代码。
- 架构。
- 阅读证据。
- 为结果负责。
自动检查围绕整个流程运行。
图例:自动检查;由人决定。
图 E:人们从阅读每一份代码差异,转向机器不擅长的决策。
在团队中共享上下文
代码审查的第二项工作,一直是传播对代码库的理解。阅读同事的代码差异,是你了解改了什么、各个部分如何配合的方式。如果大部分阅读由机器完成,人们又该如何了解代码?
我们没有正式的流程。团队中没有人会在脑中保留一份完整的 Claude Code 心智模型,我们也不认为任何人有必要这样做。当有人想理解代码库中的某一部分时,他们会请 Claude 专门为那个部分写一份讲解。只需要几分钟,而且反映的是代码今天的实际情况。
图示:“如果大部分阅读由机器完成,人们又该如何了解代码?”左侧,一个网格代表代码库,其中几个方格被高亮,表示你想了解的托管设置部分;没有人在脑中保留完整的心智模型。一条标注着“就那个具体部分询问 Claude”的箭头,以“Claude Code 如何获取托管设置?”为例,指向两个结果:Claude 写一份讲解,只需几分钟,反映代码今天的实际情况;对有些人来说,Claude 还会制作一个小型作品,将这部分代码可视化,并按照那个人喜欢的学习方式进行讲解。底部文字:逐行阅读琐碎的代码差异,一行文案修改几乎教不了你什么;对你即将修改的模块所作的讲解,却能让你学到很多。
我们中的一些人还会更进一步,让 Claude 制作一个小型作品,把那部分代码可视化,并按照各自喜欢的学习方式来讲解。
如果目标是把人的注意力用在值得的地方,这就比逐行阅读琐碎的代码差异更好。一行文案修改几乎教不了你什么;对你即将修改的模块所作的讲解,却能让你学到很多。我们默认在开放的 Slack 频道中工作的文化也有帮助,因为你能在别人构建东西的过程中看到他们正在做什么。
“谁合入,谁负责”
如果你合入一个小型或中型变更,结果仍然出了问题,团队的惯例是通常由你来修复。以下几点让这件事不至于变糟:
- 变更很小,因此容易审查、调试和回滚。
- 一切都可以撤销。功能开关、回滚和分阶段发布,可以在几分钟内撤销大多数错误。
- 影响范围决定要求。出问题代价高昂的代码,需要更多人和更多检查。
- 通过遥测和内部使用,回归问题能迅速暴露。
- 这不是追责。由你负责修复,是因为你掌握的上下文最多;事故复盘关注的是系统。
责任也是共享的。团队中的许多人在开放频道工作,任何人都可以看到其他人在做什么,接上某段讨论,或者让 Claude 去补一个缺口,不负责这部分代码的人也会提供反馈。没有对每一行都设一道关卡,质量却依然很高,这种开放性是重要原因。
什么时候改变方向
智能体降低了启动工作的成本,因此有些工作不应该合入。通常,频道里会有人问为什么要做,指出之前的某项决定,或者建议一条更简单的路线,然后作者就会关闭 PR,或者调整它。
因为代码写得很快,关闭 PR 不会让人觉得是一种损失。关键是尽早在讨论中提出不同方向,而不是等 PR 完成之后,再留下一条阻止合并的评论。
你的团队如何采用这套流程
要让你的团队采用这套流程,大多数所需组件今天都已经存在。
发起拉取请求之前
- 为智能体提供它能运行的检查,把它们列在简短的
CLAUDE.md中,并配上运行格式化工具和 lint 工具的钩子。 - 在本地运行
/code-review和/security-review,或者由一个具有全新上下文的子智能体进行审查。 - 添加
REVIEW.md,把反复出现的审查评论转移到其中。
每个拉取请求
- 要求 CI 必须通过,并在 PR 模板中增加“测试”“风险”和“如何回滚”。
- 先在一个仓库中加入 AI 审查者(Code Review for Claude Code,或 Claude Code GitHub Action),用几周时间调整
REVIEW.md,然后再扩大范围。 - 添加自动安全审查,并要求合并前解决所有审查讨论。
- 让审查投入与风险相匹配:常规变更快速审查,漏掉缺陷代价高昂的地方深入审查(Code Review 中的 Quick、Standard 或 Deep)。
- 限制审查轮次;前几轮之后,只重新审查新增的代码差异。
批准
- 写下风险等级,根据变更本身而非作者来定级;一开始严格一些,再根据证据逐步放宽。
- 只为你信任的作者保留更宽松的批准流程。
- 使用
CODEOWNERS和分支保护,确保身份认证、计费、CI 与发布工作流,以及安装程序始终需要人工参与。 - 绝不让机器人的批准替代必需的人工批准;出现新提交时,撤销已有批准。
合并及之后
- 使用合并队列、功能开关、内部先用、分阶段发布,以及一步回滚。
- 把事故和回滚变成评测集,每当审查者的提示词、工具或模型发生变化时,重新评分。
- 衡量人的时间,以回滚率和事故率作为护栏。
接下来会怎样
Code Review 的发布公告说,批准拉取请求仍然由人来决定;产品会发布发现,而不是批准。我们自己的仓库走得更远,让负责人决定哪些低风险变更只凭自动检查就可以合并,而且这条界线还在不断移动。
当一次审查漏掉了某个问题,我们会问:模型当时缺少了什么信息?然后把补救措施加入 CLAUDE.md、某个技能,或者一项新的检查。目标没有改变:每次变更花费更少的人工时间,回滚却不比以前更多。
如果你的团队允许智能体发起拉取请求,我们很想知道:你们把哪些检查自动化了?哪些仍然需要人?你认为我们有哪些地方想错了?
感谢 Emma Webb、Michael Segner 和 Amie Rotherham 的审阅。
// SUBSCRIBE · RSS
新文章发布时,第一时间收到
用任意 RSS 阅读器订阅,不打扰,也不需要留邮箱。