
先说痛点:恃强而懈
Claude Code(下文都叫 cc)非常强大,绝对算是一个神队友。
但它有个要命的毛病:会偶尔失智。关键是失智是随机出现的,且不低频。国内用第三方 API 调用,这种情况尤其明显,神队友秒变猪队友,坑死你没商量那种。
日常维护一个项目,当 CLAUDE.md 和 hooks 比较完善之后,在不失智时,cc 是非常稳的。简单的提示词,就能生成正确的代码。
之前跟 cc 配合其实很顺。简单需求一句提示词,它就懂我的意思,该查的查,该改的改,基本不用我多说。我就这么一路被它伺候着——但时不时它就降一轮智,挑不出规律。正好好的干着活,下一秒给你一个眼神迷离的答案,每次还都是不同的锅,这才是最头疼的地方。
CLAUDE.md 里有硬规:前后端改完必须通过编译。 cc 每次都能做到。所以时间长了,我也就不会上线前自己编译一下试试了。结果就大意了。需求一说,cc 直接写完提交上线,打开一看线上脚本报错,回头看后端编译就没通过。当时有点懵:多久没出过这种事了。
把报错粘给 cc,cc 态度那叫一个诚恳,说自己疏忽了,已经改好了,以后保证不再犯。再次提交,编译又报错。再粘给 cc,cc 再修改并道歉。再提交再报错,如此几轮彻底麻了。
心态崩了,破口大骂。这两年我对 AI 代码工具说的脏话,比这辈子加起来都多。
之前那次:为什么 cc 总是「差那么一点」
失智这事,大伙儿应该都见过。我把最常见的几种拉个清单:
| 失智模式 | 具体表现 |
|---|---|
| 「应该没问题」型 | 「我已经加完测试了」「应该编译过」,结果跑起来红一片 |
| 「一次梭哈」型 | 一次甩出几千行代码,出问题就是大爆炸 |
| 「文档过期」型 | 写完代码不更新文档,3 个月后自己都看不懂 |
| 「口头承诺型」 | 「我同步改了」,实际上根本没改 |
| 「为了绿而绿」型 | 测试不过? 改期望值。 把 assert 写成跟 bug 一样 |
这一长串失智的根本原因只有一个:cc 没有「下一步会死」的紧迫感,它只是给你一个「看起来差不多」的答案。
我只压实了一道护栏:文档,文档能摁住
跌了几次坑之后,我反思「到底什么最重要」。
答案越缩越小,最后只剩一句话:在中型功能开发里,把文档当主战场,其他都是配套。
文档不是写到 IDE 边上就行。文档是被我要反复锤的——锤到「任何 AI 工具拿到都能独立干活,不需要反过来问我」。
下面这几段,就是我怎么锤的。注意:这几段我都没让 cc 在场。 找 cc 来做「是不是真懂」的元话语陪练,讨论本身会把 cc 搞糊涂,所以我都是请另一 AI 工具当陪练,后面单独说。
一:把「理解」逼出来
文档我口述,第一稿让 cc 在一个 session 里整理成 markdown。这是体力活,不在这段讨论范畴。
cc 写完会跟你说「明白了」。这俩字最坑。它只是没报错,不等于它懂了。
我的做法是换另一个 AI 工具来当陪练,做法:
- 我把原始需求抄出来,扔给另一 AI(我现在用 workbuddy 的免费额度):「用你自己的话,把这条需求复述一遍,有任何不确定的也列出来」。
- 另一 AI 列出来 → 我逐条校对,跟我的原意有出入就当场标记。
- 不一致的条目我重新喂回另一 AI,让它自己说哪里理解了、哪里模糊了。
- 再让另一 AI 复述第二版。
反复到它的复述跟我的原意几乎逐字一致,「需求理解」这步才算过。
有个真实场景特别扎心:某次我描述一个边界条件,cc 复述的时候把它简化了。我没注意,直接进下一步。到了实施阶段它按简化版去做,上线后边界条件没覆盖,线上告警。回去看文档,我俩谁都没错——错在 cc 没复述、我没校对。 之后我把这一段改成另一 AI 来复述,cc 在原 session 里只管写,审稿交给陪练。
cc 说「我懂了」不算数。要让它把理解倒出来,我校对了,才算数。
二:把「步骤」嚼烂
需求这头对齐了,接着看实施步骤。这一步我必须搞懂。
我不再让 cc 在元话语里跟我来回。我的做法是:
- 新开一个 session,让 cc 看上面定好的需求文档,出实施步骤。
- 我逐条读,看不懂的就反问 cc 「为什么要这么做」。
- cc 解释 → 我再反问**「如果换成 X 方案,你为什么没选」**,逼它说出取舍。
- 这里的关键:不光是 cc 解释清楚,还得我自己能讲出来——我得在脑子里 / 在纸上复盘一次,直到能口述给另一个人听。
这一段的精髓是双向流动:不是我把需求丢给 cc 就不管了,也不是 cc 把步骤丢给我就不管了。反复「为什么这么做」、「为什么没选 X」,几轮下来**「我懂了 cc 的步骤」这一头才算过**。
但有个坑我也踩过:我懂了步骤不代表我没漏问。所以下一步还得让陪练再扫一遍——见下面「跨 AI 工具对账」。
这里有个小技巧,问cc的时候可以常用
/btw,防止污染上下文。
三:对得上,才算初步定稿
需求、步骤反复锤完之后,有那个瞬间,两件事都成了:
- 「另一 AI 把我需求复述得跟我原意几乎逐字一致」(理解这头)。
- 「我把 cc 的实施步骤嚼到能口述给另一个人听清楚」(方案这头)。
「cc 理解了我的需求,我理解了 cc 的方案」。
两边都对得上,文档才算初步定稿。这是文档合格的最低线——不是「我自己看了觉得还行」,是**「我审过、cc 知道怎么动、cc 动的时候不需要再回头问我」**。
如果任何一边是糊的,继续锤。不要因为赶进度跳过这一步。跳过的代价,通常在生产环境兑现。
兜底:hook 是把护栏写进工具链
文档护栏是主战场,但有些规则写在文档里,cc 还是会忘。我见过最典型的是:
- 它改某个契约文件,忘了同步重新生成下游代码。
- 它甩出一个几千行的 commit,把分阶段铁律踩得稀碎。
光靠文档拦不住。得靠 hook 在它动手那一秒强行拦截。
我跑了几条 hook,挑三种最有叙事价值的、按拦截强度分梯度来列:
- 真阻断 · 关键配置写保护: 任何写运维配置(关键 KV/secret 段)的动作,如果近 10 分钟内没有对应备份,exit 2 直接拒收。我有一次写新配置时手滑覆盖掉了同事刚加的 KV 段,补救花了一整个下午。这条上线后,这类失误就被彻底死锁了。
- 强提示 · 迁移改动广播: 任何方式动到迁移文件(
Edit/Write/Bash/手工INSERT schema_migrations/db.AutoMigrate),都被 hook 截到,往 cc 的stderr里塞一段「上次同类事故怎么炸的 + 防御步骤」——故意不阻断,只强提示。我让 cc 看到提示就自己停顿想一下,这条比强制 reject 灵活得多。 - 上下文注入 · 关键协议硬塞:
SessionStart启动会话,或者用户消息里命中「数据库 / 部署 / 重启 / 上线」关键词时,把对应约束协议(「开发=生产=同库,改库必备份」 / 「部署走build.sh,不要 mv bin/snow」)摘要直接塞进 cc 的stderr,不阻断,只逼 cc 在第一个 turn 前就看见协议。这条是吃了亏才加的——cc 失智时根本不会主动读CLAUDE.md,必须硬塞。
这三条上线后,拦下了若干次 cc 想要「图省事」的违规操作。 拦下来那一下心里特别爽,有种「这才是真的护栏」的感觉。
铁律必须落 hook,否则就是写在沙滩上。
但 hook 是兜底,不是主角。文档才是。反过来,hook 写错比没 hook 更危险——匹配错了该拦的没拦住、不该拦的反而拦截,我吃过一次亏。所有 hook 上线前必须人工跑几个场景验证(那次我为了一条钩子测了 8 个场景才安心)。
一个「不常见的需求」:写到 CLAUDE.md 里都不管用,只能靠 hook
我有个业务系统,开发库和生产库共用同一个 MySQL。这事我写得清清楚楚在 CLAUDE.md 里,每次实施还反复叮嘱——「开发时改表 = 改了生产,任何 schema 变更必须走 migration 文件,不要直接 ALTER」。
结果 cc 还是经常搞错——CLAUDE.md 写了不读,提示词发了不听。
经典翻车剧本:
- cc 写代码过程中需要加个列,直接
mysql -e "ALTER TABLE"改了表,顺手往schema_migrations里INSERT占了坑。 - 接着 cc 觉得「为了部署同步」,正经地新写一个
000025_add_xxx.up.sql文件。 - 上线 →
migrate.Up()看到000025这条 → 执行ADD COLUMN xxx→ 1060 Duplicate column name → migrate fail-fast → 服务起不来。
过去几个月实打实踩过几次,每次 dev/prod 上抓狂几分钟才定位。
规则写进 CLAUDE.md 不管用,prompt 里反复叮嘱也不管用。最后还是只能靠 hook 兜底。我的 hook(脱敏伪代码):
- 数据库结构变更日志 hook:cc 跑任何
ALTER / CREATE / DROP / TRUNCATE之前,自动落一份日志,说明「这是 dev 还是 prod、是 migration 还是手工」——并强制 cc 在 PR description 里引用这条日志,让人审。 - migration 文件生成 hook:cc 写
0NNNNX_*.up.sql之前,先跑scripts/migration_check取 max version +1,禁止手写编号,绕开「我以为下一个是 11,其实同事已经占了 11」这类连环撞号(我出过两次)。
CLAUDE.md写规则、prompt 里反复强调都不保险的时候,只剩 hook 能帮 cc 守住边界——不常见的需求尤其如此,因为没人会主动防御。
跨 AI 工具对账 — 找茬的工艺
回到文档主战场。一、二、三只是把「理解」和「步骤」对齐了,文档里仍可能藏着歧义、漏边界条件、术语不一致——这本质上是多模型互补的一个具体玩法: 用一个独立 AI 来挑刺,比 cc 自己复审彻底得多。这些不是 cc 能发现的,因为 cc 既当运动员又当裁判,会自然地把文档讲通顺,不会暴露矛盾。
需要一个独立的 AI 工具,专职挑刺。这就是「对账」。
我的工艺:
- 喂文档给另一 AI(不是 cc,不是 cc 的同一型号兄弟,是另一个独立陪练):
- 「请你扮演一个新接手这个项目的工程师 + 另一个 AI 工具,只看这份文档,你要把它实现出来。找出所有让你走不动的地方,一条一条列出来」。
- 陪练会列出几类问题:
- 歧义:「这个字段到底允许 NULL 吗」「失败是软失败还是硬失败」。
- 漏边界:「迁移 10000 条数据并发多少」「客户端掉线重试几次」。
- 术语打架:「你说的『快照』和你步骤 3 里的『快照』不是一回事」。
- 隐式假设:「你假设客户端在线,如果整个客户端群组都掉线,这流程怎么退化」。
- 我逐条修文档,改完再喂回去,让陪练再扫一遍。
反复几轮,直到陪练再也挑不出刺(或者只剩「这条属于实现细节,放到下一步细化了)。2-3 轮是我的经验上限,再多就是陪练在凑数,边际收益快速递减。
而且我审我自己永远审不干净——这才是跨 AI 工具挑刺存在的意义。cc 偏偏既当运动员又当裁判,会自然地把文档讲通顺,暴露不出矛盾,这一步不得不做。
这一段本质上是:复盘前我」假装」是别人看自己的文档,逼自己写得不依赖任何上下文。
对账不是请 cc 写第二遍,是请另一个 AI 工具证明这一遍够干净。两种 AI 视角各自带盲区,擦一次比 cc 自己擦十次更彻底。
这套工艺我之前专门拆过一遍——多个 AI 互喷到一方服的 具体 prompt 模板,有兴趣可以翻翻那一篇。
对账结束后,文档真的到了「任何 AI 拿到都能独立干活」的水位。这时再开新 session 把文档丢给 cc,cc 看一眼,直接写代码,不需要反复回头问我。
这一步有时候让我感觉——文档终于不是 cc 的陪练了,是 cc 的施工图。
完成一个需求的流程
一句话先说清楚:我有需求 → 跟 cc 反复对齐 → 多 AI 找茬 → 实施 + 每功能 e2e。完整流程图如下:

走完这一整套,中型功能来回 2-3 天是常事。不是每次小修小补都要走,改动 > 几百行 或 涉及 schema 变化才走完整锤法;小改动反而 cc 一把梭更高效。
写在最后
回头看,cc「失智」这事,我现在的态度跟半年前不一样了。
半年前我会拍桌子:「AI 怎么这点事都做不好!」
现在我反而觉得:cc 失智是 feature,不是 bug。 它逼着我把模糊的「需求」逼成清晰的「文档」,把单视角的「答案」逼成跨 AI 工具对账的「共识」。
AI 不会替你做决定,它会逼你把决定想清楚。
这套「文档护栏 + 跨工具对账 + hook 兜底」我建了一年多,中间被无数次 cc 失智打过脸,但每一道护栏都是被真实事故逼出来的。
工程这件事,从来不是「我一个人 hold 得住」——是「我 + cc + 一份跨工具对账过的文档 + 一组 hook」一起 hold 住。
不过几句丑话得说在前头,免得大家觉得捡到宝:
CLAUDE.md是活的护栏 —— 它既是你跟 cc 之间的「项目说明」,也是「约束清单」:项目情况写到位、不允许 cc 自由发挥的边界写清楚。写完别扔,每隔几周回来重读一遍,跟代码一起演进。 cc 失智的很多次其实是文件里某条约定已经过时、没人更新,等于没写。/clear别心疼 —— 主动/compact压缩上下文、常用/clear,跨主题就开新 session,同主题段落结束就清一次上下文。一个 session 聊久了上下文会互相干扰,cc 会跟着胡说八道。- 闭环不是装上 hook 就完了 —— 事故 → 文档 → 铁律 → hook 这条链每一步都得有人主动触发。忙起来一周不复盘,事故就在脑子里飘着,下次同类问题还会再发生。
