让我先交代下背景。上个月我维护的一个内部数据导出工具积压了一批改动,功能做了不少,但代码越写越“能跑就行”。提交前我心里发虚,又不想麻烦同事做正式 review,就想着让 Claude Code 充当一回独立审查官,把我这堆代码从头到尾骂一遍。结果它不客气,真的骂了,而且有几条刺耳到让我当场想改行。
这篇博文就是那场“审查现场”的完整记录,包括 Claude Code 的安装配置、审查指令怎么写、审查报告长什么样、哪些批评骂对了、哪些纯属 AI 误伤,以及我踩过的安装配置坑。如果你想让命令行 AI 帮你做代码审查,又不知道怎么把它用好,这篇应该能让你少走不少弯路。
1. 为什么想起让 AI 来审查代码
1.1 人工代码审查,为什么总是草草收场
我在的团队规模不大,代码审查靠的是 GitHub PR 里的评论。理论上每个人都应该认真看,实际上能吐槽一句“LGTM”就算给面子了。不是说同事不负责,而是大家手里都压着需求,谁也没精力在别人代码里逐行较真。真正尖锐的意见大家不好意思说出口,毕竟抬头不见低头见。
还有一个现实问题:review 的人往往没有跑过你的代码,也没看过完整上下文。他只能看到 diff,看不到你当时的受限条件,更不会替你把“这个分支为什么这么绕”这种问题刨根问底。结果就是:人工审查经常变成格式检查,真正藏得深的逻辑问题反而没人发现。
我这次想换个思路。让 AI 当那个“说话难听的外聘审查员”,没有面子顾虑,也不会因为关系好就放过我。
1.2 为什么选 Claude Code,而不是把代码复制给网页版聊天框
之前我也试过把一段函数直接丢给网页版 Claude 问“有什么问题”,能拿回一些建议,但效果非常碎片化。问题在于它看不见我工程里其他文件,不知道这个函数被谁调用,不知道数据库连接在哪初始化,也不知道我日志体系是什么风格,给出的意见总有一种悬空感。
Claude Code 的差异在于是直接跑在项目目录里的命令行工具。它能读取仓库结构,能打开任意文件,能调用命令甚至跑测试,然后基于整个项目的上下文给出审查意见。这就好比你是把整份代码卷宗递给律师看,而不是在电话里口述一段案情。
另外它支持长对话,审查完一个问题,你可以追问“这条依据是哪个文件里的哪一行”,它会沿着上下文继续回答,而不是每次重新开始。
1.3 我的真实动机:能跑但不敢提交
被审查的项目是一个 Python 写的 SQLite 数据导出脚本,后来越扩越大,变成了一堆互相调用的模块。功能上没问题,我在本机跑了十几次都正常,但我很清楚中间有不少“临时”写法:异常被吞掉、函数写得老长、命名随心所欲。这种代码最怕的是上线后遇到边界情况,没有任何日志可查,也没人敢动。
我当时的想法是:上线前至少来一轮无情的独立视角,把我自己看不见的问题挖出来。
2. 环境准备:Claude Code 安装与基础配置
2.1 安装前的环境要求
Claude Code 本质上是 npm 包,所以最基础的要求是 Node.js 环境。我本机的 Node 版本是 20,跑得很稳。官方一般要求 18 以上,这个不算高门槛。如果你在 Windows 上开发,建议直接用 WSL 里的 Linux 环境来装,避免一些路径和权限上的别扭;我在 Windows + WSL 下同时试过,WSL 内使用体验明显更顺。
终端方面,iTerm2、Windows Terminal、VS Code 内置终端都可以。因为 Claude Code 有交互式界面,需要终端支持一些控制字符,建议用主流现代终端,别用老古董。
另外确认 npm 的全局安装目录有写权限。这一点很多人栽过跟头,后面我会讲到具体报错。
2.2 安装步骤和一条高频报错
安装命令很简单,一行:
npm install -g @anthropic-ai/claude-code装完验证:
claude --version如果输出版本号,说明装上了。我第一次装完卡在升级环节,启动 Claude Code 时提示类似 “auto-update failed: no write permission to npm prefix”。这个问题的根因很直白:npm 全局目录被安装到了系统级路径,当前用户没有写权限,工具想自动升级时没权限覆盖自己的文件。
解决办法有两种。一是改 npm 全局前缀到用户目录,这也是我推荐的方式:
npm config set prefix ~/.npm-global然后把新路径加进 PATH,重新登录终端。另一种就是直接修改 npm 全局目录的文件权限,但动系统目录总归有点风险,后期换电脑还要重来。改到用户目录之后,自动升级就不再碰权限墙了。
2.3 登录与模型接入配置
安装完成后,在项目目录执行:
claude首次会进入登录流程。如果用的是 Anthropic 账号,直接按提示走浏览器授权即可。如果走 API Key 方式,提前把 key 配到环境变量里,名称是ANTHROPIC_API_KEY。我建议把这类变量写进~/.bashrc或~/.zshrc,别每次启动现填。
如果你用的是兼容 Anthropic 接口的其他模型服务,通常还需要配置接口地址和模型名称两个环境变量,大体是ANTHROPIC_BASE_URL和ANTHROPIC_MODEL这种格式。不同服务商给的字段名可能略有差异,以官方文档为准。
不管走哪种方式,最后验证方法都一样:在 Claude Code 里随便问一句“当前模型是什么”,能答上来就说明配置通了。
2.4 审查指令模板:别让它漫无目的地读代码
AI 审查效果的上限,很大程度取决于你怎么开局。我第一轮只是说“帮我看看代码”,结果它给了一堆“代码整体结构清晰、功能完整”的正确废话,气得我重来。
后来我把指令改成严格的审查场景,效果好得多。下面是我现在用的模板:
你现在是一位有 10 年工作经验的资深工程师,擅长做代码审查。 请审查当前项目 src/ 目录下的所有 Python 文件,重点关注: 1. 错误处理和异常吞掉的情况 2. 函数过长、嵌套过深、职责不分 3. 命名不达意、变量含义模糊 4. 潜在并发或资源泄漏问题 5. 魔法数字、重复逻辑、边界条件遗漏 输出要求: - 先给出整体结论,说明严重程度分布 - 再按严重程度从高到低列出具体问题 - 每个问题必须给出:位置、代码片段、为什么是问题、建议改法 - 如果没有依据请不要臆测,标注为“需要确认”这套模板核心是三个约束:身份、范围、输出格式。身份让 AI 进入资深 reviewer 的角色,范围避免它满仓库乱翻,输出格式保证结果可以直接当作 review 文档来用。
3. 实操过程:让 Claude Code 审查我的代码
3.1 被审查的项目画像
被审的是一个内部用的订单数据导出工具。一开始只是单文件脚本export.py,后来加了过滤、多格式输出和定时任务,膨胀到约 1800 行,连带几个辅助模块。
项目基本信息大致这样的:
| 项目属性 | 情况 |
|---|---|
| 语言 | Python 3.10 |
| 存储 | SQLite / 本地数据库 |
| 核心文件 | export.py(约 1200 行)、formatter.py、db.py |
| 运行方式 | 命令行调用,偶尔由计划任务触发 |
| 最大的问题 | 我一直能跑通,但不敢保证边界情况 |
审查前我先跑了claude进入项目目录,等它加载完项目结构之后,把我刚才那段模板指令原样发了过去。
3.2 审查过程发生了什么
Claude Code 拿到指令后不是马上给结论,而是一步步操作。它会先扫描目录,然后逐个打开相关文件,界面里能看到它在“阅读”哪些文件。这个过程大概持续了两三分钟,期间我不需要做任何干预。
之后它给出了一份按严重程度分级的 review 报告,长度很惊人。除了“高/中/低”分级,每条都带了文件路径和行号,甚至截取了一段代码片段出来,这比我预想的要认真得多。我看完整个人都不好了。
中间我试过打断它,问其中一个批评的依据是什么,它确实会回到对应文件展开解释,说明它确实是“读过”代码才给出的结论,而不是套模板。
3.3 扎眼的几条批评原文
我摘几条当时最扎眼的,你们感受一下:
| 位置 | Claude Code 的批评大意 | 我的第一反应 |
|---|---|---|
| export.py write_rows() | “这个函数有 120 行,6 层嵌套,我无法一眼看出它在干嘛。” | 冷汗,因为确实没人敢改这个函数 |
| db.py 的异常处理 | “except Exception: pass 连日志都没有。一旦数据库被锁,你会收获一个静默失败。” | 破防,因为我真的是为了测试省事才这么写 |
| export.py 顶部 | “CONN 是全局连接,脚本进程一旦跑起来就不会释放,SQLite 迟早给你报 database is locked。” | 没想到它连运行时的资源状态都考虑到了 |
| formatter.py | “字段叫 data,作用域里还有 data_list,这两个名字需要你看三遍才能分清楚。” | 这条倒不猛,但正好戳中我偷懒命名的毛病 |
| export.py 的解析逻辑 | “CSV 读进来的数字没有类型校验,None 会直接炸穿后面的 f-string。” | 真的很丢人,测试数据碰巧都是干净的所以从来没炸过 |
| export.py 主函数 | “这 600 行的主函数有一半能拆出来。拆完之后你就不需要那个 8 个参数的调用。” | 我甚至没意识到自己有 8 参数的函数 |
它最狠的地方不是骂得难听,而是每条批评都能给出对应的触发场景。这意味着它确实站在运行时的角度推演过我的代码,而不只是做静态扫描。
3.4 让我难堪的对话片段
审查流程走完之后,我又追问了几个问题。其中一个对话让我印象很深。
我问:“这个异常处理真的有问题吗?我测试时没出过错。”
它反问:“你现在 catch 这个异常只是为了不让程序退出,所以你直接吞掉了。如果哪天数据库文件损坏,你希望这个模块继续往下跑,然后生成一份只有一半数据的导出文件吗?”
我沉默了。这个场景确实没想过。
还有一次它说:“你确定这个文件找不到的异常要在这里捕获吗?如果这是用户传参问题,应该在上游调用处就报出来,而不是在这个深度静默处理。”
语气很平静,但句句都是灵魂拷问。属于那种同事看了都不会当面说你的话,AI 毫无心理负担地全说出来了。
4. 逐条复盘:哪些批评骂对了,哪些是 AI 误伤
4.1 骂得对的:修复之后实测有效
冷静下来之后,我开始一条条处理它指出的问题。最直观的是 write_rows 函数拆分。我把 120 行的函数拆成fetch_batch、transform_row、flush_to_file三个职责清晰的函数。拆完之后意外发现原来的一个 bug:数据量超过某个阈值时,缓冲列表不会清空。这个 bug 藏得很深,但拆开之后逻辑一眼就能看出来。
异常处理方面,我给它所有吞异常的地方加上了 logging,并且明确什么场景该往上抛、什么场景该记录后跳过。之后我特意模拟了一次数据库被锁的情况,发现日志里能清楚看到重试失败的时间点和原因。这种可观测性在之前是完全不存在的。
SQLite 全局连接的批评也命中要害。我改成了每次任务进入时通过上下文管理器获取连接,任务结束自动关闭。改完没有再遇到过连接无法释放的问题。
4.2 存疑与误伤:AI 审查也不是金口玉言
当然,Claude Code 也不是每次都骂得对。它有一条建议是“SQLite 不支持并发写入,建议改用 PostgreSQL”。问题是我这里就是个单用户命令行导出工具,并发写入根本不是我的场景,改数据库属于杀鸡用牛刀。这种建议一旦照单全收,成本会非常不可控。
还有一条让我很无语:它建议用asyncio.to_thread来包装一些 IO 操作。但我的脚本是同步逻辑,也没有异步加载的必要。加一层异步封装只会让代码更绕,收益为零。
最让我警惕的是它的一些“脑补”。比如它根据一个变量名猜测这个模块“可能被多个线程调用”,但实际没有。AI 审查能力强,但它不知道业务上下文,经常会把可能性当成必然性来写。
所以我的结论是:AI 的意见需要人工判断,尤其涉及架构变更、换依赖、大范围重构的建议,千万不能无脑采纳。它是指出问题的放大镜,不是决定改造方向的决策者。
4.3 从“被骂”到学会怎么看代码
之前我一直把 code review 理解成“找错”,觉得没 bug 就不用改。这次之后我的理解变了:审查更多是在找“脆弱的地方”——那些目前能跑、但一旦换个输入就会炸的地方。
现在我看一段不熟悉的代码,会下意识问几个问题:这里如果返回 None 会怎样?这条 except 会不会把真实错误掩盖掉?这个函数能不能拆分?这个命名是不是要靠上下文才能懂?这些思维习惯,就是那次被 AI 骂出来的。
5. 用 Claude Code 做代码审查的经验沉淀
5.1 review prompt 的持续打磨
第一版模板能用了,但用过几轮之后我会定期调整。现在我的模板里多了一条:“如果有无法确定的点,明确标出需要人工确认”。这个非常重要,能有效降低 AI 脑补的情况。
不同的项目我会换不同的审查重点。比如数据库相关代码强调连接管理和事务边界,爬虫脚本强调重试和超时,CLI 工具强调参数校验和错误信息可读性。你不给方向,AI 就只能按通用标准来,效果会打折扣。
5.2 让 AI 改代码的正确姿势
审查效果最好的一轮是在它给出问题清单之后,紧接着让它针对每条问题直接生成修复建议。我通常要求它给出 diff 级别的改动,然后一条条人工过。
这里我要特别提醒:不要直接让它“顺手把这些问题全改了”。AI 对你整个系统的理解还没到那个程度,一次性大改很容易引入新问题。正确做法是让它一次只改一个严重问题,然后我跑测试验证,再继续下一个。这样每一步都能控制回归风险。
这个流程基本符合正常 review 的节奏:发现问题、分析问题、小步修复、验证。
5.3 实测有效的几个技巧
用了两三周之后,我总结出几个对审查质量影响很大的实践:
- 先格式化代码再审查。代码不格式化时会把大量格式噪声混进审查,给它一份 vscode format 后的代码,审查会集中关注逻辑问题,而不是一直挑缩进。
- 指定文件范围。大仓库直接让人 AI 全会读,它容易“走马观花”。我会指定核心文件,忽略测试目录和静态资源,保证注意力集中。
- 用 git diff 作为审查对象。审查未提交的改动时,让 AI 只看 diff,基本就相当于让人工 reviewer 看 PR。
- 要求引用精确位置。如果它说不出来自哪一行,这条意见通常可信度不高。
- 用“严重程度”字段过滤。输出中只有高和中的意见是必须处理的,低的我看心情。
5.4 常见报错与避坑速查表
实际使用中,除了开头的 npm 权限问题,还有几个非常常见,我干脆给个速查表:
| 现象 | 原因 | 处理方式 |
|---|---|---|
| claude: command not found | npm 全局 bin 目录不在 PATH | 执行 npm prefix -g 找到路径并加入 PATH |
| auto-update failed: no write permission | npm 全局目录无写权限 | npm config set prefix ~/.npm-global 后重开终端 |
| 登录之后一直提醒 API key 无效 | 环境变量名拼错或未生效 | 确认变量名是 ANTHROPIC_API_KEY,重开终端 |
| 在 WSL 里 claude 找不到 | 包安装到了 Windows 全局目录 | 在 WSL 的 npm 环境里单独安装一次 |
| 审查一半提示上下文过长 | 仓库文件太多 | 用 /compact 压缩上下文,或拆分成模块审查 |
| 报告格式时好时坏 | prompt 约束不够 | 明确要求 markdown 表格或固定字段顺序 |
| 回答开始偏离主题 | 对话轮次太长 | 用 /clear 开新一轮会话,把审查范围重新说明 |
5.5 团队落地的个人建议
如果你想把 Claude Code 引入团队 review 流程,我会建议先从“辅助角色”开始,不要让 AI 直接卡 PR。第一步是让 AI report 和人工 review 并行;第二步再约定哪些问题必须人工复核,比如架构变更和 UI 行为相关的问题;第三步才是把 AI 评论作为 PR 的必选第一步。
这个渐进方式的好处是:既能享受 AI 审查的覆盖面,又不会被它偶尔的误报绑架。
结尾
那次被 Claude Code 骂得很难堪,回头看反而是好事。它把那些“我知道但一直没改”的问题一件件摆到了台面上,逼着我做了久拖不决的重构。现在我的工作流是:提交前先在项目里跑一轮 AI 审查,把严重问题处理掉再发 PR。
我个人的体会是,工具能替你找到问题,但决定改不改、怎么改的永远是你自己。从那之后,每次写完“临时”代码,我都会默认这个仓库会被 AI 审查,写完先自查一轮。这个习惯帮我避开了大量的运行时深坑。希望这篇记录也能给你一点启发。