工程 · CLAUDE

CLAUDE发布日期 2026-10-15 · 阅读约 14 分钟

Claude Code 团队如何进行代码审查

当智能体以这种规模产出代码时,如何审查代码?在 Claude Code 团队,当我们实现高覆盖率和深入审查后,就开始优化人工审查时间,目标是在不增加回滚或事故的前提下将人工审查时间降至最低。

原作者/来源:claude.dev

原文链接:https://claude.dev/blog/solving-code-review-at-anthropic/

当智能体以这种规模产出代码时,如何审查代码?在 Claude Code 团队,当我们实现高覆盖率和深入审查后,就开始优化人工审查时间,目标是在不增加回滚或事故的前提下将人工审查时间降至最低。

我们之前说过,Claude 编写了 Claude Code 自身约 90% 的代码。那么,面对我们产出代码的数量,要如何审查代码?现在还有人读代码吗?如果出了问题,谁来发现?

这篇文章介绍 Claude Code 团队的代码审查流程,以及它如何演变。从 6 月到 9 月,合并到 Claude Code 代码库中的拉取请求数量翻了一倍以上,而需要回滚的比例下降了 40% 以上。

我们并没有取消审查。但我们确实把大部分阅读工作转交给了机器,优化了对人类时间和注意力的使用,并投入大量精力,让错误能够快速、轻松地撤销。

重新思考代码审查的目的

当智能体编写代码时,变更数量会迅速增加。在 Anthropic 的单体代码库中,每天落地的变更从今年 5 月的大约 2,500 个,增加到 9 月的 30,000 多个。Claude Code 使用自己的独立代码库,与单体代码库分开,但它也面临很大的压力。当你以这样的速度交付时,手动逐行进行代码审查会非常困难,甚至不可能。

代码审查承担两项工作:

  1. 在问题发布前发现并修复它们
  2. 在团队中建立共享上下文和对代码库的理解

本文主要关注发现和修复问题,但我们会在接近结尾时再回到第二项工作。

我们认为,“是否有真人读过代码?”并不能准确代表“这项变更可能会出什么问题,哪种检查——自动检查还是人工检查——最适合发现它?”

提出这个问题也改变了审查发生的时机。过去,审查是道路尽头的一道关卡:写代码、开一个 PR、然后等同事审查。

现在,审查会持续运行,更像是你写作时的拼写检查。大多数变更在交由人查看之前,至少已经由 Claude 审查并修复过一次。这能发现大多数常见错误,也能把团队的注意力留给更高层面的问题和审视。

稀缺资源:人的时间和注意力

我们希望把人的时间和注意力留给只有人才能解决的问题,并确保自动化检查捕获其余问题。以我们目前的变更速度,人仍有大量工作要做,而且我们的团队几乎每天都会遇到新的、前所未有的挑战。

人的时间涵盖审查成本的两面:人们花在审查上的时间,以及他们花在修复糟糕代码所导致的问题上的时间。如果削减了前者,却只是让时间转移到后者,并没有帮助。

因此,我们的目标是:Claude Code 各代码库(CLI、桌面和 Web 应用,以及移动应用)中的大多数拉取请求,在至多一名人类参与环节的情况下合并,这个人可以是作者本人,同时回滚或事故不增加。为了衡量人的时间,我们跟踪每个 PR 的人工审批数(中位数和第 95 百分位数)、人工评论数,以及 PR 等待某个人处理的时长。回滚率和事故率是护栏:如果它们上升,我们就没有节省人的时间,只是把时间挪到了别处。

一项变更的生命周期

一项典型变更从工程师的笔记本电脑(或 Slack 中的 Claude 会话)开始,会经过多层代码审查。

一项变更的生命周期

原文图 A

一项典型的 Claude Code 变更,从作者的机器一路到达用户

拉取请求之前

  • 验证工作:Claude 运行测试、构建和代码检查器;另一个智能体在全新的上下文中审查差异。

每个拉取请求都要经过

  • 必需的 CI:在各个平台上运行代码检查、类型检查、测试,以及构建和打包。检查失败就会阻止合并。
  • Claude 代码审查:多个智能体并行查找缺陷,验证器对每项发现进行投票,保留下来的发现按严重程度排序。
  • 安全审查:单独进行一轮审查。任一审查中的待处理发现都会阻止合并。
  • 按风险审批:分类器确定风险等级:无需人工、需要一人或需要两人。某些路径始终需要人工审查。

合并时

  • 合并队列:在最新的 main 上应用这项变更后,再次运行检查。

合并之后

  • 先在功能开关后启用,在内部使用:Anthropic 员工先运行它,然后才会向所有人开放。
  • 逐步发布:先进入最新频道;稳定频道稍后跟进。
  • 观察、向前修复或回滚:作者和当班人员负责观察;功能开关可以快速关闭,损坏的构建会被回滚。

自动化检查  由人做决定,按风险扩大覆盖  恢复

图 A 大部分流程都是自动化的;人的注意力会投向风险所在之处。

逐层检查

多层检查,而不是一道关卡

原文图 B

六层检查,底层是回滚

  • 验证中的问题
  • 必需的 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 审查,然后才交给人查看。Claude 会结合整个代码库和 PR 声明的意图阅读差异,并提出问题:这项变更解决了它要解决的问题吗?它符合系统的设计吗?它会破坏其他东西吗?

对于缺陷修复,它会查找根本原因。面向公众的版本“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 员工使用;我们的高频使用往往能在用户之前发现回归问题。公开发布会先进入最新频道。稳定频道会稍后跟进。

7. 快速发现,快速回滚

有些错误仍然会漏过去,因此最后一层的重点是快速发现问题。无需部署就能关闭功能开关。Claude Code 实行每周轮值的当班制度,事故复盘会询问是哪一层本该发现这个问题。

发现糟糕的合并仍然依赖作者和当班人员,也依赖回滚和事故仪表盘。我们还没有能在这些数字发生变化时收紧审批要求的断路器;这里的工程师希望在更多代码转向零人工合并之前实现它们。

一位同事说,放慢速度确实会降低错误率,但这主要是因为你做的所有事情都变少了。我们更愿意提升发现和修复问题的速度。

我们如何改进审查器

我们的代码审查流程会持续循环改进。

现在,任何事故都会成为一个评测样例。团队收集了过去引发事故的 PR,以及对应的向前修复和回滚,并让熟悉相关代码的工程师确认每个缺陷及其所在位置。审查器每天都会在这组样例上运行。

我们的事故就是评测集

原文图 C

由过往事故和回滚构建,每天运行

事故或回滚 → 经专家核实的案例 → 加入集合
导致问题的变更 → 专家确认缺陷 → 每起事故都会增加一个案例

修改审查器 → 每日评测运行 → 分数提高了吗?
修改它的提示、工具或模型 → 对每个案例进行评分 → 如果提高就保留;否则就撤销

下一项变更

图 C 评测集会随着每起事故不断增长,而审查器的每项变更都会在全部样例上评分。

我们通过观察人们如何处理评论来衡量噪声。如果不介意标记大量并非缺陷的内容,就很容易发现更多缺陷,因此我们需要一种检查机制。我们会根据 PR 上的人如何回应,对审查器留下的每条评论进行分类:他们修复了它、表示它不对、表示这是有意为之,或认为它无关紧要。我们还会让审查器检查我们已知没有问题的 PR,并统计它报告可能导致他人做出有害变更的内容的频率。我们明确写下的优先级是:首先捕获真实缺陷,其次减少审查轮数。

当作者是智能体时,噪声的代价更高。人可以在几秒钟内忽略一个琐碎意见。智能体则会去修复它,这意味着又多一个提交和一轮审查。

审查必须收敛。智能体作者和智能体审查器可能会没完没了地互相折腾。有一个 CLI PR 在一夜之间经历了 50 多轮审查和修复,最后是作者叫停了它。

我们对审查器反复标记的内容运行 git blame 时,发现其中约 59% 是在审查器第一次检查时就已经存在的代码。审查器很少是在发现新的缺陷,而是每轮再多发现一些旧缺陷。

我们自己把情况弄得更糟了。我们已经习惯默认进行多轮审查,因为每一轮都会发现一些新问题。对于高风险变更,这可能值得,但不适用于每个 PR。团队现在会在召回率之外,也跟踪通过所需的轮数,并调整了重新审查流程:

  • 设置轮数上限。 三轮之后,审查器会要求作者退一步,重新考虑方案。
  • 前几轮之后,只对差异重新审查。
  • 标记缺陷类型,让作者修复所有实例,而不只是某一行。
  • 不重复已经发布过的发现。

审查智能体还会在夜间检查现有代码,帮助我们在旧缺陷出现在其他地方之前发现它们。

让审查收敛

原文图 D

收敛改动前后,内部拉取请求的情况

指标 改动前 改动后
经过一轮审查和修复后通过 65% 78%
需要五轮或更多 8.9% 1.5%
平均通过所需审查轮数 2.08 1.32

收敛工作之前  收敛工作之后

图 D 收敛改动后,每个内部拉取请求所需的审查轮数减少了。

人仍参与的环节

让一位资深工程师从深度工作中抽身出来抓一个常见错误,成本远高于自动化审查。在 Anthropic,我们的工作已经从阅读每一份差异,转向做机器不擅长的决策:

  • 我们究竟应该构建这个东西吗? 方向、品味和范围。一个团队曾宣称其审查瓶颈已经解决,但仍然保留对团队外部变更的人工审查,因此会有人问:“我们真的应该做这个吗?”
  • 高风险代码,例如账单、自动更新器和 CI 工作流。
  • 会设定模式、供其他人照着做的架构。
  • 阅读证据。 测试输出、运行过的命令及其返回结果、截图、审查器的发现。如果你说不出这些检查会漏掉什么,就应该要求一次真正的审查,而不是快速审批。
  • 承担结果。 无论是谁输入的代码,每一项发布的变更都由一个人负责。

哪些地方由人做决定

原文图 E

五项决策仍由人负责;其他地方都运行检查

  • 我们应该构建它吗?
  • 承担结果
  • 高风险代码
  • 自动化检查全程运行
  • 阅读证据
  • 架构
  • 自动化检查
  • 人来决定

图 E 人们的工作从阅读每一份差异,转向做机器不擅长的决策。

在团队中共享上下文

代码审查的第二项工作一直是传播对代码库的理解。阅读队友的差异,是了解变更内容以及各部分如何协作的方式。如果大部分阅读工作都由机器完成,人们要如何了解代码?

我们没有正式流程。团队里没有人能把 Claude Code 的完整心智模型装在脑子里,我们也不认为任何人需要做到这一点。如果有人想了解代码库的某一部分,他们就会让 Claude 针对那一部分撰写一份说明。只需几分钟,而且反映的是代码今天的实际状态。

代码库知识共享示意图

我们中的一些人会更进一步,让 Claude 构建一个小型的可视化产物,展示代码的那一部分,并按照那个人喜欢的学习方式讲解它。

如果目标是妥善利用人的注意力,这比逐行阅读琐碎差异更好。一行文案变更几乎教不会你什么。针对你即将修改的模块写一份说明,则能让你学到很多。我们默认在公开 Slack 频道中工作的文化也有帮助,因为你可以看到其他人在构建什么,以及他们如何构建。

“你合并,你负责”

如果你合并了一项小型或中型变更,之后仍然出了问题,团队规范通常要求你来修复。有几件事可以避免事情变糟:

  • 变更很小,因此容易审查、调试和回滚。
  • 一切都可以撤销。功能开关、回滚和分阶段发布可以在几分钟内撤销大多数错误。
  • 影响范围决定门槛。代价高昂的代码会有更多人参与和更多检查。
  • 遥测和内部使用会快速暴露回归问题。
  • 这不是追责。有上下文最多的人负责修复;事故复盘关注的是系统。

责任也是共享的。团队中许多人在公开频道工作,任何人都可以看到其他人在构建什么、接续某个讨论串,或让 Claude 补上某个缺口;反馈也来自不负责相关代码的人。这种开放性是质量能够保持较高、又不必对每一行代码都设置关卡的重要原因。

改变方向时

智能体让启动项目的成本变得很低,因此有些工作不应该合并。通常,频道里会有人询问原因、指出之前的决策,或建议一条更简单的路线,然后作者就会关闭或调整 PR。

既然代码写得很快,关闭 PR 就不会让人觉得是损失。诀窍是在讨论串中尽早提出不同方向,而不是等到 PR 完成后才用阻塞性评论提出。

如何采用这个流程

如今,你和团队实现这一流程所需的大部分组成部分都已经具备。

拉取请求之前

  • 在简短的 CLAUDE.md 中列出智能体可以运行的检查,并添加运行格式化工具和代码检查器的钩子。
  • 在本地运行 /code-review 和 /security-review,或让子智能体在全新的上下文中审查。
  • 添加 REVIEW.md,并把重复出现的审查评论整理到其中。

每个拉取请求都要做

  • 要求 CI 通过,并在 PR 模板中加入“测试”“风险”和“如何回滚”。
  • 在一个代码库中添加 AI 审查器(Claude Code 代码审查,或 Claude Code GitHub Action),用几周时间调整 REVIEW.md,然后再扩大范围。
  • 添加自动化安全审查,并要求合并前解决每个审查讨论串。
  • 让审查力度匹配风险:常规变更做快速检查,漏掉缺陷代价高的变更做深入检查(在代码审查中选择 Quick、Standard 或 Deep)。
  • 限制审查轮数;前几轮之后,只重新审查新的差异。

审批

  • 写下风险等级,由变更而不是作者决定;先从严格开始,再根据证据放宽。
  • 仅让你信任的作者走较轻量的审批路径。
  • 使用 CODEOWNERS 和分支保护,确保身份验证、账单、CI 和发布工作流,以及安装器始终需要人工审查。
  • 绝不要让机器人的审批取代必需的人类审批;新提交进入时,撤销已有审批。

合并及之后

  • 使用合并队列、功能开关、先在内部使用、分阶段发布和一步回滚。
  • 把事故和回滚加入评测集,并在提示、工具或模型发生变化时重新评估审查器。
  • 衡量人的时间,并以回滚率和事故率作为护栏。

接下来会怎样

“代码审查”功能的公告称,批准拉取请求仍然是人的决定;产品只发布发现结果,不提供审批。我们自己的代码库走得更远一些,让负责人决定哪些低风险变更只要自动化检查通过就可以合并,而这条界线仍在不断变化。

当审查漏掉了什么时,我们会询问模型当时没有看到什么信息,然后把修复写入 CLAUDE.md、技能或新的检查中。目标没有改变:减少每项变更所耗费的人工时间,同时不让回滚数量高于从前。

如果你的团队让智能体打开拉取请求,我们想知道你们自动化了哪些检查、哪些仍然需要人工,以及你认为我们哪些做法有问题。

感谢 Emma Webb、Michael Segner 和 Amie Rotherham 审阅本文。