Karpathy 的四条规矩:129K Star 的 CLAUDE.md
2026 年 1 月底,Andrej Karpathy 在 X 上发了[一条推文]1,总结了大模型写代码时的几个通病。这条推文很快就被一个开发者做成了一个 GitHub 仓库——一个单独的 CLAUDE.md 文件,里面只有四条原则,但每一条都精准命中了 AI 编程的痛点。
四个月过去,这个仓库拿了 129,378 个 Star,13,129 个 Fork。
说实话,我第一反应是:一个 CLAUDE.md 文件凭什么拿 129K Star?但当我仔细看完内容之后,我觉得这个 Star 数一点都不夸张。因为它解决的不是某个技术问题,而是所有用 AI 写代码的人都会遇到的那个最根本的问题:AI 太听话了,听话到你让它往东它绝不往西,但它会在往东的路上把整条街重新装修一遍。
下面我来拆解这四条原则,聊聊它为什么有效。
Karpathy 指出的三个毛病
先看看 Karpathy 在推文里怎么说的。他的原文有三个核心观察,我逐条拆解。
问题一:AI 会替你做错误假设,然后一路狂奔
“The models make wrong assumptions on your behalf and just run along with them without checking. They don’t manage their confusion, don’t seek clarifications, don’t surface inconsistencies, don’t present tradeoffs, don’t push back when they should.”
翻译过来就是:模型会替你做假设,然后不验证、不提问、不展示矛盾、不做权衡、该反驳的时候不反驳。
这个痛点太真实了。你跟 AI 说“加个用户导出功能”,它默认导出所有用户、导出为 JSON 文件、存到项目根目录——这三件事里没有一件是你说的,但它全做了,而且做完之前一个字都不会问你。
更可怕的是,它做错了你还不一定能发现。因为它给的代码看起来很完整、很专业、甚至还有注释和类型标注。但方向是错的,代码写得再漂亮也是白费。
问题二:AI 特别喜欢把简单的事情搞复杂
“They really like to overcomplicate code and APIs, bloat abstractions, don’t clean up dead code… implement a bloated construction over 1000 lines when 100 would do.”
100 行能搞定的事,AI 非要写成 1000 行。抽象工厂、策略模式、配置系统,该上的不该上的全上了。
这个问题的根源在于大模型的训练数据。训练数据里有大量的“教科书级”代码——设计模式完整、架构分层清晰、可扩展性极强。AI 学会了这些“好的实践”,但没学会什么时候该用、什么时候不该用。你让它算个折扣,它能给你整出 DiscountStrategy 抽象基类、PercentageDiscount 和 FixedDiscount 两个实现类、一个 DiscountConfig 数据类、再加一个 DiscountCalculator 管理类。30 行代码能搞定的事情,硬是写了 60 行,还得先理解五个类之间的关系。
问题三:AI 会改它不该改的东西
“They still sometimes change/remove comments and code they don’t sufficiently understand as side effects, even if orthogonal to the task.”
你让 AI 修一个空邮箱崩溃的 bug,它顺手把旁边的邮箱验证逻辑“改进”了,把用户名校验也加强了,还加了 docstring、改了引号风格、把单引号换成了双引号。等你 review 的时候发现 diff 里有 30 行改动,但真正修 bug 的只有 3 行。
这不是个别现象,这是大模型的通病。它太热情了,改一个地方的时候总忍不住“顺便”把周围的代码也收拾一下。问题是,那些“顺便”的改动,你没法确认它们是不是正确的,因为你没要求改那些地方。
四条原则:精准的治疗方案
这个仓库的核心就是四条原则,每一条精准对应上面三个问题中的一个。
原则一:编码前思考(Think Before Coding)
不要假设。不要隐藏困惑。呈现权衡。
这条原则针对的是问题一。它要求 AI 在动手写代码之前,先把假设说出来、把困惑摆出来、把多种理解列出来。
具体来说就是四件事:明确说明假设——不确定就问,别猜。呈现多种理解——有歧义的时候,别默默选一个。该反驳就反驳——如果有更简单的方法,说出来。困惑时停下来——指出不清楚的地方,要求澄清。
这条原则的本质是把 AI 从“执行者”变成“协作者”。不是你给一个指令它就埋头苦干,而是它先跟你确认方向,然后再动手。方向对了,后面的事才不白费。
原则二:简洁优先(Simplicity First)
用最少的代码解决问题。不要过度推测。
这条针对问题二。五条规则很直接:不要添加要求之外的功能。不要为一次性代码创建抽象。不要添加未要求的“灵活性”或“可配置性”。不要为不可能发生的场景做错误处理。如果你写了 200 行代码,50 行就能搞定,重写它。
仓库里有个特别好的例子。同样是“计算折扣”这个需求,过度工程版本搞了抽象基类、策略模式、配置系统,写了 60 多行。而简洁版本就一个函数,6 行代码:
def calculate_discount(amount: float, percent: float) -> float:
"""Calculate discount amount. percent should be 0-100."""
return amount * (percent / 100)
检验标准很简单:资深工程师会觉得这过于复杂吗?如果是,简化。
什么时候加复杂度?当需求真正出现的时候。如果以后确实需要多种折扣类型,到时候再重构。提前设计是好事,但提前过度设计就是灾难。
原则三:精准修改(Surgical Changes)
只碰必须碰的。只清理自己造成的混乱。
这条针对问题三。两个维度的约束:编辑现有代码时,不要“改进”相邻的代码、注释或格式。不要重构没坏的东西。匹配现有风格,即使你更倾向于不同的写法。如果注意到无关的死代码,提一下就好——不要删它。
而当你的改动产生了孤儿代码(比如你删了一个函数,但有些 import 变得没用了),你只删因你的改动而变得无用的代码,不要删之前就存在的死代码。
检验标准:每一行修改都应该能直接追溯到用户的请求。
这个原则的背后是一个很朴素的道理:你在 review PR 的时候,希望每一行改动都是你能理解的、有明确意图的。如果 diff 里混着大量“顺手牵羊”式的改动,review 的难度和风险都会指数级上升。
原则四:目标驱动执行(Goal-Driven Execution)
定义成功标准。循环验证直到达成。
这条是 Karpathy 的一个核心洞察:
“LLMs are exceptionally good at looping until they meet specific goals… Don’t tell it what to do, give it success criteria and watch it go.”
翻译一下:LLM 特别擅长循环执行直到达成特定目标。别告诉它该做什么,给它成功标准,然后看着它完成。
这个洞察太准了。你跟 AI 说“修复认证系统”,它会给你一个模糊的执行计划——审查代码、发现问题、做出改进、测试变更。每一步都说了,但每一步都不可验证。
但如果你换一种方式:
- 编写测试:修改密码后验证旧 session 失效 → 验证:测试失败(重现 bug)
- 实现:密码修改时使 session 失效 → 验证:测试通过
- 检查边缘情况:多个活跃 session、并发修改 → 验证:额外测试通过
- 验证无回归:现有认证测试仍通过 → 验证:完整测试套件通过
每一步都有明确的验证条件。AI 知道什么时候算“做完了”,什么时候需要继续迭代。
对于多步骤任务,这个仓库建议用这样的格式:
1. [步骤] → 验证: [检查]
2. [步骤] → 验证: [检查]
3. [步骤] → 验证: [检查]
强有力的成功标准让 AI 能独立循环执行。弱标准(“让它工作”)需要不断人工干预。
CLAUDE.md 原文
下面是这个仓库的 CLAUDE.md 完整原文。总共不到 60 行,但每一行都有分量。你可以直接复制到你的项目中使用。
以下内容来自 [multica-ai/andrej-karpathy-skills]2 仓库的 CLAUDE.md 文件:
# CLAUDE.md
Behavioral guidelines to reduce common LLM coding mistakes. Merge with
project-specific instructions as needed.
**Tradeoff:** These guidelines bias toward caution over speed. For trivial
tasks, use judgment.
## 1. Think Before Coding
**Don't assume. Don't hide confusion. Surface tradeoffs.**
Before implementing:
- State your assumptions explicitly. If uncertain, ask.
- If multiple interpretations exist, present them - don't pick silently.
- If a simpler approach exists, say so. Push back when warranted.
- If something is unclear, stop. Name what's confusing. Ask.
## 2. Simplicity First
**Minimum code that solves the problem. Nothing speculative.**
- No features beyond what was asked.
- No abstractions for single-use code.
- No "flexibility" or "configurability" that wasn't requested.
- No error handling for impossible scenarios.
- If you write 200 lines and it could be 50, rewrite it.
Ask yourself: "Would a senior engineer say this is overcomplicated?"
If yes, simplify.
## 3. Surgical Changes
**Touch only what you must. Clean up only your own mess.**
When editing existing code:
- Don't "improve" adjacent code, comments, or formatting.
- Don't refactor things that aren't broken.
- Match existing style, even if you'd do it differently.
- If you notice unrelated dead code, mention it - don't delete it.
When your changes create orphans:
- Remove imports/variables/functions that YOUR changes made unused.
- Don't remove pre-existing dead code unless asked.
The test: Every changed line should trace directly to the user's request.
## 4. Goal-Driven Execution
**Define success criteria. Loop until verified.**
Transform tasks into verifiable goals:
- "Add validation" → "Write tests for invalid inputs, then make them pass"
- "Fix the bug" → "Write a test that reproduces it, then make it pass"
- "Refactor X" → "Ensure tests pass before and after"
For multi-step tasks, state a brief plan:
1. [Step] → verify: [check]
2. [Step] → verify: [check]
3. [Step] → verify: [check]
Strong success criteria let you loop independently. Weak criteria
("make it work") require constant clarification.
---
**These guidelines are working if:** fewer unnecessary changes in diffs,
fewer rewrites due to overcomplication, and clarifying questions come
before implementation rather than after mistakes.
中文翻译版:
# CLAUDE.md
行为指南,用于减少常见的 LLM 编程错误。根据需要与项目特定指令合并使用。
**权衡:** 这些指南倾向于谨慎而非速度。对于琐碎的任务,请自行判断。
## 1. 编码前思考
**不要假设。不要隐藏困惑。呈现权衡。**
在实现之前:
- 明确说明你的假设。如果不确定,就问。
- 如果存在多种理解,把它们都呈现出来——不要默默选择。
- 如果存在更简单的方法,说出来。必要时提出异议。
- 如果有不清楚的地方,停下来。指出困惑之处。问清楚。
## 2. 简洁优先
**用最少的代码解决问题。不要过度推测。**
- 不要添加要求之外的功能。
- 不要为一次性代码创建抽象。
- 不要添加未要求的"灵活性"或"可配置性"。
- 不要为不可能发生的场景做错误处理。
- 如果你写了 200 行代码,而 50 行就能搞定,重写它。
问问自己:"资深工程师会觉得这过于复杂吗?"如果是,简化。
## 3. 精准修改
**只碰必须碰的。只清理自己造成的混乱。**
编辑现有代码时:
- 不要"改进"相邻的代码、注释或格式。
- 不要重构没坏的东西。
- 匹配现有风格,即使你更倾向于不同的写法。
- 如果注意到无关的死代码,提一下——不要删除它。
当你的改动产生孤儿代码时:
- 删除因你的改动而变得无用的 import/变量/函数。
- 不要删除之前就存在的死代码,除非被要求。
检验标准:每一行修改都应该能直接追溯到用户的请求。
## 4. 目标驱动执行
**定义成功标准。循环验证直到达成。**
将任务转化为可验证的目标:
- "添加验证" → "为无效输入编写测试,然后让它们通过"
- "修复 bug" → "编写一个能重现 bug 的测试,然后让它通过"
- "重构 X" → "确保重构前后测试都能通过"
对于多步骤任务,说明一个简短的计划:
1. [步骤] → 验证: [检查]
2. [步骤] → 验证: [检查]
3. [步骤] → 验证: [检查]
强有力的成功标准让你能独立循环执行。弱标准("让它工作")需要不断澄清。
---
**这些指南正在起效的标志:** diff 中不必要的改动更少,因过度复杂导致的重写更少,澄清问题在实现之前提出而非在犯错之后。
怎么用
这个仓库提供了几种使用方式,覆盖了主流的 AI 编程工具。
Claude Code 插件安装(推荐)
在 Claude Code 里执行两条命令就行:
# 添加插件市场
/plugin marketplace add forrestchang/andrej-karpathy-skills
# 安装插件
/plugin install andrej-karpathy-skills@karpathy-skills
安装后,这些指南会在你所有项目中生效。
直接放入项目
如果你只想在单个项目里用,或者用的不是 Claude Code:
# 新项目,直接下载
curl -o CLAUDE.md https://raw.githubusercontent.com/forrestchang/andrej-karpathy-skills/main/CLAUDE.md
# 已有项目,追加到现有 CLAUDE.md
echo "" >> CLAUDE.md
curl https://raw.githubusercontent.com/forrestchang/andrej-karpathy-skills/main/CLAUDE.md >> CLAUDE.md
Cursor 用户
仓库里也提供了 Cursor 的规则文件 .cursor/rules/karpathy-guidelines.mdc,设置 alwaysApply: true,打开项目就自动生效。内容跟 CLAUDE.md 完全一致,只是格式适配了 Cursor 的规则系统。
与项目自定义规则合并
这些指南设计为可以和项目特定的规则共存。比如你可以在 CLAUDE.md 里加上自己的规则:
## Project-Specific Guidelines
- 使用 TypeScript 严格模式
- 所有 API 端点必须有测试
- 遵循 src/utils/errors.ts 中现有的错误处理模式
我的看法
用了一段时间之后,我觉得这四条原则里,最有用的是“目标驱动执行”和“精准修改”这两条。
“目标驱动执行”改变了我跟 AI 协作的方式。以前我都是告诉 AI “做什么”,现在我更倾向于定义“什么算做完了”。这个转变看似很小,但效果差异巨大。举一个我自己的真实例子:之前让 AI 修复一个博客构建报错,我说“修复这个 bug”,它改了三个文件、重构了错误处理逻辑、还顺手加了类型标注——结果 bug 没修好,反而引入了两个新问题。后来我换了个方式:“写一个能重现这个报错的测试,然后只改让测试通过的那行代码”,结果它改了两行就搞定了。
“精准修改”则直接减少了 review 的负担。之前每次 AI 改完代码,我都要仔细检查 diff 里哪些是它“顺手牵羊”改的,哪些是我要求的。有次我让它修一个空指针异常,它把整个模块的错误处理都“优化”了一遍,diff 里 40 多行改动,我花了 20 分钟才确认哪些是安全的。现在 diff 干净多了,改了什么一目了然。
不过也有人会问:这些原则会不会让 AI 变得太保守?明明两分钟能搞定的事,非得先问一堆问题,效率反而更低了。 这个担心有道理,但只对了一半。对于改个变量名、修个拼写错误这类事,确实不需要 AI 先做三轮假设分析。但问题是,大多数人低估了“看起来简单”的改动带来的风险。我自己的经验是:改动涉及超过一个文件、或者涉及业务逻辑的时候,多花 30 秒让 AI 确认方向,能省下后面 30 分钟的返工。这四条原则的价值体现在非琐碎的任务上——你越是在重要的功能开发、复杂的 bug 修复中用,越能感受到它们的威力。
还有一点值得说的是,这个仓库之所以能拿到 129K Star,不只是因为内容好,更因为它抓住了 AI 编程时代的一个共识性问题:AI 编程的瓶颈已经不是 AI 会不会写代码,而是你能不能管好它写代码的方式。
写在最后
这四条原则,说穿了都是资深工程师在做 code review 时会提的要求。只不过以前这些要求是人对人提的,现在写成了对 AI 的行为规范。CLAUDE.md 本质上就是一种“AI 行为管理”——通过规则约束让 AI 的输出更可控、更可预测。形式变了,但核心没变:好的代码是简洁的、精准的、可验证的。
如果你在用 AI 编程工具,不管是 Claude Code、Cursor 还是其他的,我都建议你试试这套指南。不需要全盘照搬,挑最让你头疼的那条先用上,你会立刻感受到差异。
评论互动