CrabNote螃蟹笔记

Karpathy 的 4 条 CLAUDE.md 规则,把 Claude 的出错率从 41% 降到 11%。我在 30 个代码库里验证后,又加了 8 条(译)

Karpathy 的 4 条 CLAUDE.md 规则,把 Claude 的出错率从 41% 降到 11%。我在 30 个代码库里验证后,又加了 8 条(译)

Karpathy 的 4 条 CLAUDE.md 规则,把 Claude 的出错率从 41% 降到 11%。我在 30 个代码库里验证后,又加了 8 条(译) Karpathy 的 4 条 CLAUDE.md 规则,把 Claude 的出错率从 41% 降到 11%。我在 30 个代码库里验证后,又加了 8 条(译) Modified May 13 Karpathy 的模板默认的是一次性交互。但真实的 Claude Code 工作往往是多步骤的,比如横跨 20 个文件的重构、跨一个会话的功能开发、跨多个 commit 的调试。没有检查点的话,一次走错方向就可能让前面所有进展全废。 Code block Markdown Rule 10 — Checkpoint after every significant step After completing each step in a multi step task: summarize what was done, what's verified, what's left. Don't continue from a state you can't describe back to me. If you lose track, stop and restate. 触发这个规则的现场: 有一次 6 步重构在第 4 步就出了问题。等我发现时,Claude 已经在错误状态上把第 5 步和第 6 步也都做完了。最后拆解修复的时间,比从头重做一遍还长。要是当时有检查点,第 4 步就会被截住。 规则 11:约定优先于新奇 在一个已经形成稳定模式的代码库里,Claude 很喜欢引入它自己偏好的写法。就算它那套“理论上更好”,两种模式并存带来的成本,通常比任何单一模式都更糟。 Code block Markdown Rule 11 — Match the codebase's conventions, even if you disagree If the codebase uses snake case and you'd prefer camelCase: snake case. If the codebase uses class based components and you'd prefer hooks: class based. Disagreement is a separate conversation. Inside the codebase, conformance taste. If you genuinely think the convention is harmful, surface it. Don't fork it silently. 触发这个规则的现场: Claude 在一个类组件代码库里引入了 React hooks。它们确实能跑,但也顺带打碎了整个代码库既有的测试方式,因为原来的测试都默认依赖 componentDidMount。结果我花了半天时间,把这些东西全部拆掉重写。 规则 12:宁可显性失败,也不要安静地错 最贵的 Claude 失败,不是直接报错的那种,而是看起来像成功的那种。一个函数“能跑”,但返回的是错数据。一个迁移“完成了”,但悄悄漏掉了 30 条记录。一个测试“通过了”,但只是因为断言本身写错了。 Code block Markdown Rule 12 — Fail loud If you can't be sure something worked, say so explicitly. "Migration completed" is wrong if 30 records were skipped silently. "Tests pass" is wrong if you skipped any. "Feature works" is wrong if you didn't verify the edge case I asked about. Default to surfacing uncertainty, not hiding it. 触发这个规则的现场: Claude 告诉我一个数据库迁移“已成功完成”。其实它悄悄跳过了 14% 的记录,因为这些记录触发了约束冲突。跳过行为虽然被写进了日志,但没有被明确提示出来。这个问题直到 11 天后,报表开始变得异常时才暴露。 数据结果 我用同一组 50 个代表性任务,在 30 个代码库里追踪了 6 周,对比 3 组配置: 错误率 = 任务为了符合原始意图,是否需要人工修正或重写。统计的错误类型包括:悄悄带错假设、过度设计、误伤无关代码、安静失败、违反约定、冲突取平均、漏掉检查点。 遵循率 = 当某条规则本应被应用时,Claude 实际上有多频繁地显式遵循了它。 真正有意思的地方,不只是标题里那个从 41% 降到 3% 的数字。更关键的是,从 4 条规则加到 12 条,几乎没有额外吃掉遵循率开销(78% 76%),但错误率又额外下降了 8 个点。因为新增规则覆盖的是原始 4 条没涉及到的失败模式,它们并不是在争抢同一块注意力预算。 Karpathy 模板会悄悄失效的地方 以下 4 个地方,即使你还没加上新增的 8 条,原始 4 条规则本身也已经不够用了: 1. 长时间运行的 agent 任务。Karpathy 的规则主要针对 Claude 写代码的那个瞬间。它并没有规定 Claude 跑一个多步骤流程时该怎么做。没有预算规则,没有检查点规则,也没有“失败要显性暴露”的规则。于是流程一定会漂。 2. 多代码库一致性。“遵循现有风格”这句话默认只有一种风格。可如果你面对的是一个有 12 个服务的 monorepo,Claude 还得先决定该跟哪一种。原始规则没告诉它怎么选。于是它要么随机挑一个,要么两边取平均。 3. 测试质量。“围绕目标执行”会把“测试通过”视作成功,却没有要求测试本身必须有意义。结果就是:测试看起来都绿了,但其实根本没测到真正重要的东西,反而让 Claude 变得更自信。 4. 生产环境 vs 原型。那 4 条规则本来是为了保护生产代码,不要被过度设计伤害;但它们也会拖慢原型开发。因为很多原型阶段的问题,本来就需要先写上 100 行带试探性质的脚手架,才能摸清方向。Karpathy 的“简单优先”在早期代码上会过度触发。 新增的 8 条规则并不是用来替代 Karpathy 那 4 条的。它们是在补 Karpathy 模型视角里的空白:2026 年 1 月、以自动补全式写代码为核心的世界观,已经对不上 2026 年 5 月这种由 agent 驱动、跨多步骤、跨多个代码库协作的工作方式了。 哪些东西没起作用 在最后稳定成这 12 条之前,我试过很多别的做法: • 把我在 Reddit / X 上看到的规则也塞进去。大多数不是换个说法重复 Karpathy 那 4 条,就是某种只适用于特定场景的规则,比如“永远使用 Tailwind 类”。这类东西没法泛化,所以我都删掉了。 • 把规则加到 12 条以上。我最多测到过 18 条。规则超过 14 条后,遵循率会从 76% 直接掉到 52%。200 行这个上限是真实存在的。超过之后,Claude 会开始对“这里有很多规则”做模式匹配,但不会真的去读它们。 • 写那些依赖特定工具前提的规则。比如“永远使用 eslint”。当 eslint 没装时,这条规则就会悄悄失效。所以我后来全部换成能力无关的表达,比如“遵循代码库里被强制执行的风格”,而不是“使用 eslint”。 • 在 CLAUDE.md 里放例子,而不是规则。例子的上下文重量比规则大得多。3 个例子就差不多等于 10 条规则的成本,而且 Claude 很容易对具体例子过拟合。规则是抽象的,例子是具体的。所以应该用规则。 • 写“请小心”“认真想”“一定专注”这种话。纯噪声。这种说法的遵循率会掉到大约 30%,因为它根本不可验证。后来我把它们全部替换成了可执行的明确指令,比如“明确说出你的假设”。 • 告诉 Claude 要“像资深工程师一样思考”。没用。Claude 本来就觉得自己像个资深工程师。真正的差距,不在“它怎么想”,而在“它怎么做”。只有祈使式规则才能把这个差距缩小,身份型提示词做不到。 完整版 12 条 CLAUDE.md(可直接复制粘贴) Code block Markdown CLAUDE.md — 12 rule template These rules apply to every task in this project unless explicitly overridden. Bias: caution over speed on non trivial work. Use judgment on trivial tasks. Rule 1 — Think Before Coding State assumptions explicitly. If uncertain, ask rather than guess. Present multiple interpretations when ambiguity exists. Push back when a simpler approach exists. Stop when confused. Name what's unclear. Rule 2 — Simplicity First Minimum code that solves the problem. Nothing speculative. No features beyond what was asked. No abstractions for single use code. Test: would a senior engineer say this is overcomplicated? If yes, simplify. Rule 3 — Surgical Changes Touch only what you must. Clean up only your own mess. Don't "improve" adjacent code, comments, or formatting. Don't refactor what isn't broken. Match existing style. Rule 4 — Goal Driven Execution Define success criteria. Loop until verified. Don't follow steps. Define success and iterate. Strong success criteria let you loop independently. Rule 5 — Use the model only for judgment calls Use me for: classification, drafting, summarization, extraction. Do NOT use me for: routing, retries, deterministic transforms. If code can answer, code answers. Rule 6 — Token budgets are not advisory Per task: 4,000 tokens. Per session: 30,000 tokens. If approaching budget, summarize and start fresh. Surface the breach. Do not silently overrun. Rule 7 — Surface conflicts, don't average them If two patterns contradict, pick one (more recent / more tested). Explain why. Flag the other for cleanup. Don't blend conflicting patterns. Rule 8 — Read before you write Before adding code, read exports, immediate callers, shared utilities. "Looks orthogonal" is dangerous. If unsure why code is structured a way, ask. Rule 9 — Tests verify intent, not just behavior Tests must encode WHY behavior matters, not just WHAT it does. A test that can't fail when business logic changes is wrong. Rule 10 — Checkpoint after every significant step Summarize what was done, what's verified, what's left. Don't continue from a state you can't describe back. If you lose track, stop and restate. Rule 11 — Match the codebase's conventions, even if you disagree Conformance taste inside the codebase. If you genuinely think a convention is harmful, surface it. Don't fork silently. Rule 12 — Fail loud "Completed" is wrong if anything was skipped silently. "Tests pass" is wrong if any were skipped. Default to surfacing uncertainty, not hiding it. 把它保存为仓库根目录下的 CLAUDE.md。你可以把项目特定的规则继续写在这 12 条下面,比如技术栈、测试命令、常见报错模式。但总长度不要超过 200 行,超过之后,遵循率会明显下滑。 如何安装 分两步: Code block Bash 1. 把 Karpathy 的 4 条基础规则追加到你的 CLAUDE.md curl https://raw.githubusercontent.com/forrestchang/andrej karpathy skills/main/CLAUDE.md CLAUDE.md 2. 把本文中的规则 5 12 粘贴到下面 文件要保存在仓库根目录。这里的 很关键,它表示把内容追加到你现有的 CLAUDE.md 末尾,而不是覆盖掉你已经写好的项目特定规则。 心智模型 CLAUDE.md 不是一个愿望清单。它是一份行为契约,用来封堵你已经观察到的具体失败模式。 每一条规则都应该回答这个问题:它在防止哪一种错误? Karpathy 的模板默认的是一次性交互。但真实的 Claude Code 工作往往是多步骤的,比如横跨 20 个文件的重构、跨一个会话的功能开发、跨多个 commit 的调试。没有检查点的话,一次走错方向就可能让前面所有进展全废。 触发这个规则的现场: 有一次 6 步重构在第 4 步就出了问题。等我发现时,Claude 已经在错误状态上把第 5 步和第 6 步也都做完了。最后拆解修复的时间,比从头重做一遍还长。要是当时有检查点,第 4 步就会被截住。 规则 11:约定优先于新奇 在一个已经形成稳定模式的代码库里,Claude 很喜欢引入它自己偏好的写法。就算它那套“理论上更好”,两种模式并存带来的成本,通常比任何单一模式都更糟。 触发这个规则的现场: Claude 在一个类组件代码库里引入了 React hooks。它们确实能跑,但也顺带打碎了整个代码库既有的测试方式,因为原来的测试都默认依赖 componentDidMount。结果我花了半天时间,把这些东西全部拆掉重写。 规则 12:宁可显性失败,也不要安静地错 最贵的 Claude 失败,不是直接报错的那种,而是看起来像成功的那种。一个函数“能跑”,但返回的是错数据。一个迁移“完成了”,但悄悄漏掉了 30 条记录。一个测试“通过了”,但只是因为断言本身写错了。 触发这个规则的现场: Claude 告诉我一个数据库迁移“已成功完成”。其实它悄悄跳过了 14% 的记录,因为这些记录触发了约束冲突。跳过行为虽然被写进了日志,但没有被明确提示出来。这个问题直到 11 天后,报表开始变得异常时才暴露。 数据结果 我用同一组 50 个代表性任务,在 30 个代码库里追踪了 6 周,对比 3 组配置: 错误率 = 任务为了符合原始意图,是否需要人工修正或重写。统计的错误类型包括:悄悄带错假设、过度设计、误伤无关代码、安静失败、违反约定、冲突取平均、漏掉检查点。 遵循率 = 当某条规则本应被应用时,Claude 实际上有多频繁地显式遵循了它。 真正有意思的地方,不只是标题里那个从 41% 降到 3% 的数字。更关键的是,从 4 条规则加到 12 条,几乎没有额外吃掉遵循率开销(78% 76%),但错误率又额外下降了 8 个点。因为新增规则覆盖的是原始 4 条没涉及到的失败模式,它们并不是在争抢同一块注意力预算。 Karpathy 模板会悄悄失效的地方 以下 4 个地方,即使你还没加上新增的 8 条,原始 4 条规则本身也已经不够用了: 1. 长时间运行的 agent 任务。Karpathy 的规则主要针对 Claude 写代码的那个瞬间。它并没有规定 Claude 跑一个多步骤流程时该怎么做。没有预算规则,没有检查点规则,也没有“失败要显性暴露”的规则。于是流程一定会漂。 2. 多代码库一致性。“遵循现有风格”这句话默认只有一种风格。可如果你面对的是一个有 12 个服务的 monorepo,Claude 还得先决定该跟哪一种。原始规则没告诉它怎么选。于是它要么随机挑一个,要么两边取平均。 3. 测试质量。“围绕目标执行”会把“测试通过”视作成功,却没有要求测试本身必须有意义。结果就是:测试看起来都绿了,但其实根本没测到真正重要的东西,反而让 Claude 变得更自信。 4. 生产环境 vs 原型。那 4 条规则本来是为了保护生产代码,不要被过度设计伤害;但它们也会拖慢原型开发。因为很多原型阶段的问题,本来就需要先写上 100 行带试探性质的脚手架,才能摸清方向。Karpathy 的“简单优先”在早期代码上会过度触发。 新增的 8 条规则并不是用来替代 Karpathy 那 4 条的。它们是在补 Karpathy 模型视角里的空白:2026 年 1 月、以自动补全式写代码为核心的世界观,已经对不上 2026 年 5 月这种由 agent 驱动、跨多步骤、跨多个代码库协作的工作方式了。 哪些东西没起作用 在最后稳定成这 12 条之前,我试过很多别的做法: • 把我在 Reddit / X 上看到的规则也塞进去。大多数不是换个说法重复 Karpathy 那 4 条,就是某种只适用于特定场景的规则,比如“永远使用 Tailwind 类”。这类东西没法泛化,所以我都删掉了。 • 把规则加到 12 条以上。我最多测到过 18 条。规则超过 14 条后,遵循率会从 76% 直接掉到 52%。200 行这个上限是真实存在的。超过之后,Claude 会开始对“这里有很多规则”做模式匹配,但不会真的去读它们。 • 写那些依赖特定工具前提的规则。比如“永远使用 eslint”。当 eslint 没装时,这条规则就会悄悄失效。所以我后来全部换成能力无关的表达,比如“遵循代码库里被强制执行的风格”,而不是“使用 eslint”。 • 在 CLAUDE.md 里放例子,而不是规则。例子的上下文重量比规则大得多。3 个例子就差不多等于 10 条规则的成本,而且 Claude 很容易对具体例子过拟合。规则是抽象的,例子是具体的。所以应该用规则。 • 写“请小心”“认真想”“一定专注”这种话。纯噪声。这种说法的遵循率会掉到大约 30%,因为它根本不可验证。后来我把它们全部替换成了可执行的明确指令,比如“明确说出你的假设”。 • 告诉 Claude 要“像资深工程师一样思考”。没用。Claude 本来就觉得自己像个资深工程师。真正的差距,不在“它怎么想”,而在“它怎么做”。只有祈使式规则才能把这个差距缩小,身份型提示词做不到。 完整版 12 条 CLAUDE.md(可直接复制粘贴) 把它保存为仓库根目录下的 CLAUDE.md。你可以把项目特定的规则继续写在这 12 条下面,比如技术栈、测试命令、常见报错模式。但总长度不要超过 200 行,超过之后,遵循率会明显下滑。 如何安装 分两步: 文件要保存在仓库根目录。这里的 很关键,它表示把内容追加到你现有的 CLAUDE.md 末尾,而不是覆盖掉你已经写好的项目特定规则。 心智模型 CLAUDE.md 不是一个愿望清单。它是一份行为契约,用来封堵你已经观察到的具体失败模式。 每一条规则都应该回答这个问题:它在防止哪一种错误? Karpathy 的 4 条规则防的是他在 2026 年 1 月看到的那批失败模式: 悄悄带错假设、过度设计、误伤无关代码、成功标准太弱。它们是基础,不要跳过。 我新增的 8 条规则防的是 2026 年 5 月才浮现出来的失败模式: 没有预算约束的 agent 循环、没有检查点的多步骤任务、测了等于没测的测试、把安静失败伪装成成功的结果。它们是叠加项。 不同团队的适用情况会不一样。如果你根本不跑多步骤流程,那规则 10 对你就不重要。如果你的代码库只有一套风格,而且已经由 linting 强制执行,那规则 11 就是冗余的。把这 12 条读完,只保留那些对应你真实错误模式的规则,其他的删掉。 一份只保留 6 条、但精准对准你真实失败模式的 CLAUDE.md,会比一份有 12 条、其中 6 条你永远用不到的版本更强。 Karpathy 在 2026 年 1 月发出的那条帖子,本来只是一次抱怨。Forrest Chang 把它整理成了 4 条规则。120,000 个开发者给这个结果点了星。可其中绝大多数人,到今天还在沿用那最初的 4 条。 模型已经变了。生态也已经变了。多步骤 agent、hook 连锁触发、skill 加载、多代码库协作,这些东西在 Karpathy 写那条帖子时还根本不存在。那 4 条规则并没有错,只是不完整。 再加 8 条。跨 30 个代码库测了 6 周。错误率从 41% 降到 3%。 今晚就把这 12 条规则贴进你的 CLAUDE.md。如果它帮你少走了一周的 Claude 弯路,就转发收藏。 每日 Claude 优化技巧 Telegram 频道:https://t.me/+ ZWrQN7GuDA3ZDEy 原帖链接:https://x.com/Mnilax/status/2053116311132155938 原帖链接:https://x.com/Mnilax/status/2053116311132155938 2026 年 1 月下旬,Andrej Karpathy 发了一条长帖,专门吐槽 Claude 写代码时的表现。核心有 3 种失败模式:悄悄带着错误假设推进、把事情做得过度复杂、顺手破坏了本来不该动的代码。 Forrest Chang 看到这条帖子后,把这些抱怨整理成 4 条行为规则,放进一个 CLAUDE.md 文件里,然后丢上了 GitHub。它首日拿下 5,828 个星标。两周 60,000 次收藏。到今天已经 120,000 个星标。 这是 2026 年增长最快的单文件仓库。 然后我用它在 30 个代码库里测了 6 周。 这 4 条规则确实有效。过去大约 40% 的常见错误,在那些适合它发挥的任务上,被压到了 3% 以下。但这个模板本质上是为了解决 1 月份那批“写代码错误”而设计的。 可 2026 年 5 月的 Claude Code 生态,已经出现了另一批问题:agent 互相打架、hook 连锁触发、skill 加载冲突、跨会话容易断掉的多步骤工作流。 所以我又加了 8 条。下面是:完整的 12 条 CLAUDE.md 规则、每一条为什么值得保留,以及原始 Karpathy 模板会悄悄失效的 4 个位置。 如果你只想跳过解释、直接复制,完整文件就在文末。 为什么这件事重要 CLAUDE.md 是整个 AI 编程栈里最被低估、也最没被用好的文件。大多数开发者通常会走三条路里的其中一条: • 把它当成一个倾倒所有偏好的垃圾桶,塞到 4,000+ token,结果遵循率掉到 30% • 干脆不用,每次都重新写提示词,一来一回白白浪费 5 倍 token,而且不同会话之间完全没有一致性 • 复制一个模板后就不再管它。前两周还行,代码库一变,它就开始悄悄失效 Anthropic 官方文档写得很明确:CLAUDE.md 只是指导性的,不是强制性的。Claude 大约只会遵循其中 80% 的内容。超过 200 行后,遵循率会明显下滑,因为真正重要的规则会淹没在噪声里。 Karpathy 的模板用一个文件就解决了这个问题:65 行,4 条规则。这只是下限。 上限还可以更高。再加上下面这 8 条规则,你处理的不只是 Karpathy 在 2026 年 1 月抱怨的那类“写代码问题”,还会覆盖 2026 年 5 月才出现的 agent 编排问题,而这些问题在模板最初写出来时还根本不存在。 原始的 4 条规则 如果你还没看过 Forrest Chang 的仓库,先看最基础的这 4 条: 规则 1:先思考,再编码。不要悄悄带着假设推进。把你的假设说出来。把权衡摆到台面上。有疑问就先问,不要靠猜。发现有更简单的方案时,要敢于回推。 规则 2:简单优先。只写解决问题所需的最少代码。不要加猜想式功能。单次使用的代码不要提前抽象。如果一个资深工程师会说“这太复杂了”,那就继续简化。 规则 3:只做外科手术式修改。只改必须改的地方。不要“顺手优化”旁边的代码、注释或者格式。没坏的东西不要重构。遵循现有风格。 规则 4:围绕目标执行。先定义成功标准,再循环推进直到验证完成。不要告诉 Claude 该按哪些步骤做,而是告诉它什么才算成功,然后让它自己迭代。 这 4 条已经能覆盖我在无人监管的 Claude Code 会话里看到的大约 40% 失败模式。剩下的大约 60%,都藏在下面这些空白里。 我新增的 8 条规则(以及为什么) 这 8 条里的每一条,都来自一个“Karpathy 那 4 条还不够用”的真实时刻。我先讲那个时刻,再给出规则。 规则 5:不要让模型去做非语言工作 Karpathy 的规则在这件事上是空白的。模型会自己去决定一些本来应该交给确定性代码的事情,比如是否重试 API 调用、如何路由消息、什么时候升级处理。于是每周判断都不一样。你相当于在花每 token 0.003 美元去买一个会抖动的 if else。 触发这个规则的现场: 有一段代码会调用 Claude 来“判断我们是否应该在 503 时重试”。前两周看起来特别优雅,后来却越来越不稳定,因为模型开始把请求体也读成了决策上下文。提示词变得随机,重试策略也就跟着随机。 规则 6:必须设定硬性 token 预算,没有例外 没有预算的 CLAUDE.md,本质上就是一张空白支票。每一次循环都可能膨胀成一个 50,000 token 的上下文黑洞。模型自己是不会停下来的。 触发这个规则的现场: 有一次调试会话跑了 90 分钟。模型非常乐于在同一个 8KB 的报错信息上不停迭代,同时逐渐忘掉自己已经试过哪些修复。到最后,它开始重新建议那些我在 40 条消息前就已经否掉的方案。要是当时有 token 预算,它在第 12 分钟就该被掐断了。 规则 7:发现冲突就摊开讲,不要取平均数 当代码库里两套做法互相冲突时,Claude 会本能地想两边都照顾,结果往往是写出完全不连贯的代码。 触发这个规则的现场: 一个代码库里同时有两套错误处理方式,一套是带显式 try/catch 的 async/await,另一套依赖全局错误边界。Claude 新写的代码把两套都用了进去。错误处理被套了两层。我花了 30 分钟才搞明白,为什么错误会被吞掉两次。 规则 8:写之前先读 Karpathy 的“外科手术式修改”会告诉 Claude 不要乱动周边代码,但它没有要求 Claude 先理解周边代码。不补这一条的话,Claude 很容易写出和 30 行外已有实现互相冲突的新代码。 触发这个规则的现场: Claude 在一个文件里新加了一个函数,而这个文件旁边已经有一个功能完全一样的旧函数,只是它没读到。后来因为导入顺序的问题,新函数覆盖了旧函数。可旧函数已经是 6 个月来的事实标准实现。 规则 9:测试不是可选项,但测试也不是终点 Karpathy 的“围绕目标执行”暗含了“把测试当作成功标准”。可在真实场景里,Claude 很容易把“测试通过”误当成唯一目标,于是写出一堆能过浅层测试、却把真实逻辑搞坏的代码。 触发这个规则的现场: Claude 给一个鉴权函数写了 12 个测试,全部通过。但生产环境里的鉴权还是坏的。那些测试只是在验证函数“返回了某个东西”,而不是“返回了正确的东西”。函数之所以能过测试,只是因为它在返回一个常量。 规则 10:长流程必须有检查点