Karpathy 的 LLM 编码批评与 CLAUDE.md 最佳实践

基于 Andrej Karpathy 对 LLM 编程助手的观察,forrestchang 提炼出一个 CLAUDE.md 文件,4 条原则解决 AI 编码的典型失控问题:乱猜假设、过度设计、乱改代码、目标不清

$2.7k 字/约 8 min👁— views

Karpathy 的 LLM 编码批评与 CLAUDE.md 最佳实践

Andrej Karpathy 在 X(前 Twitter)上的一条帖子,催生了一个 107k stars 的 GitHub 仓库。

forrestchang/andrej-karpathy-skills 由 Jiayuan(forrestchang,同时是 Multica 项目作者)创建,将 Karpathy 对 AI 编程工具的犀利批评提炼成了四条 CLAUDE.md 规则。这个仓库的核心问题是:为什么现在的 AI 编程助手总是让人抓狂?怎么修?

Karpathy 为什么批评现在的 AI 编程工具

Karpathy 不是在无脑批评,他本人就是 AI 领域最顶尖的工程师之一,曾在 OpenAI 担任研究科学家,也是特斯拉 Autopilot 的前负责人。他的批评来自真实的使用体验,每一条都戳在痛点上。

他的原始帖子(@karpathy,推文 ID:2015883857489522876)中写道:

“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 没问你就开始写代码,写了一大堆,但方向错了。

四个典型问题

Karpathy 归纳了 AI 编程助手的几个核心问题:

问题一:乱猜假设,不求确认

“The models make wrong assumptions on your behalf and just run along with them without checking.”

LLM 非常擅长"看起来在执行任务"。当需求不清晰时,它不会停下来问,而是选择一个看起来合理的解释,然后全速运行。这种"自信执行"的风格在需求明确时是优点,在需求模糊时是灾难。

问题二:过度设计,代码膨胀

“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.”

AI 有一种奇怪的本能:把简单的事情做复杂。100 行能解决的问题,它可能给你写 1000 行,附带一堆你没要求的抽象层、工厂模式、策略模式。这不是能力的体现,是认知过载的副产品——LLM 见过太多"企业级代码",把复杂度当作质量的代理指标。

问题三:误伤无关代码

“They still sometimes change/remove comments and code they don’t sufficiently understand as side effects, even if orthogonal to the task.”

这是最让开发者头疼的问题之一。你叫 AI 修一个 bug,它顺手删了几行注释、改了几个变量名,理由是"优化了可读性"。在代码库中这是极其危险的行为——你不知道哪些看起来无关的改动会引发连锁反应。

问题四:目标不清,循环失控

Karpathy 也看到了 LLM 的潜力所在:

“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 特别擅长"为了达成目标反复迭代"。但如果你给的是模糊的操作指令而不是清晰的成功标准,这个循环能力反而会变成失控的来源。

CLAUDE.md 四条原则逐一解析

forrestchang 将 Karpathy 的观察提炼为四条可操作的规则,写进了一个 CLAUDE.md 文件。

原则一:Think Before Coding(先想后写)

对应问题:乱猜假设,不求确认

核心内容

  • 在写代码之前,显式声明你对任务的理解和假设
  • 如果存在歧义,主动问清楚,不要自己脑补
  • 列出多个可能的实现方案及其权衡,再决定用哪个

这条规则改变了 LLM 的默认行为模式——从"接到任务立刻执行"变成"先理解,再执行"。

实际上,这也是好的软件工程师的习惯:在键盘上敲第一行代码之前,先在脑子里(或者白板上)把问题想清楚。

效果:让 AI 暴露它的假设,你可以在它走错之前纠正。

原则二:Simplicity First(简单优先)

对应问题:过度设计,代码膨胀

核心内容

  • 写最简单的能解决问题的代码
  • 不要实现没有被明确要求的功能
  • 不要添加未被要求的抽象层
  • 不要"顺手"重构

这条规则直接对抗 LLM 的"复杂化冲动"。它的哲学来源是 YAGNI(You Aren’t Gonna Need It)和 UNIX 哲学:每个模块只做一件事,做好这一件事。

效果:得到更短、更直接的代码,更容易 review,更容易维护。

原则三:Surgical Changes(外科手术式修改)

对应问题:误伤无关代码

核心内容

  • 只修改任务直接要求修改的代码
  • 不要"顺便"修改看起来不相关的东西
  • 不要删除你没有完全理解的注释或代码
  • 如果发现了其他需要修改的地方,报告出来,不要自行修改

"外科手术式"这个比喻很精准:外科医生做手术,只处理目标部位,绝对不会因为"发现旁边有个不好看的地方"就顺手切掉。

效果:代码库的意外变动大幅减少,diff 更干净,review 更容易。

原则四:Goal-Driven Execution(目标驱动执行)

对应问题:目标不清,循环失控(以及正向利用 LLM 的循环能力)

核心内容

  • 把任务转化为可验证的成功标准
  • 给 LLM 目标,而不是步骤
  • 让它自主决定如何达成目标
  • 通过测试用例、断言、具体的输出格式来定义"完成"

这条规则是四条中最反直觉的,也是最有力量的。

Karpathy 说得很清楚:“Don’t tell it what to do, give it success criteria and watch it go.”(不要告诉它做什么,给它成功标准,然后看它运行。)

比较两种指令方式:

指令式(不推荐)

“先读取 users 表,然后过滤出 active=true 的用户,然后按 created_at 排序,然后取前 10 条,然后格式化成 JSON…”

目标式(推荐)

“返回最近注册的 10 个活跃用户,格式为 JSON 数组,每个元素包含 id、name、email 字段。用 pytest 测试:给定测试数据库有 20 个用户(15 活跃),函数应返回长度为 10 的数组,且所有元素的 active 字段为 true。”

第二种方式利用了 LLM 的循环能力:它会不断尝试,直到写出通过测试的代码。

效果:释放 LLM 的 agent 能力,同时用可验证的目标约束其行为。

如何安装和使用

方式一:Claude Code Plugin

/plugin marketplace add forrestchang/andrej-karpathy-skills

安装后,这些规则会自动注入到 Claude Code 的系统 prompt 中。

方式二:单项目 CLAUDE.md

在项目根目录添加 CLAUDE.md 文件:

curl -o CLAUDE.md https://raw.githubusercontent.com/forrestchang/andrej-karpathy-skills/main/CLAUDE.md

Claude Code 会自动读取项目根目录的 CLAUDE.md,将其内容作为额外的系统指令。

方式三:Cursor 规则文件

对于 Cursor 用户:

mkdir -p .cursor/rules
curl -o .cursor/rules/karpathy-guidelines.mdc https://raw.githubusercontent.com/forrestchang/andrej-karpathy-skills/main/CLAUDE.md

Cursor 的 .mdc 规则文件和 CLAUDE.md 在功能上是等价的——都是"给 AI 看的行为约束文件"。

和 anthropics/skills 的关系

理解这两个仓库的关系,有助于更清晰地认识"给 Claude 的指令文件"这个生态:

anthropics/skills forrestchang/andrej-karpathy-skills
目标 能力增强 行为约束
内容 教 Claude 怎么做特定任务 规范 Claude 的编码行为模式
类比 技能培训课程 职业道德准则
适用范围 特定任务场景 所有编码任务

两者都是"给 Claude 的指令文件",但层次不同:

  • anthropics/skills 是领域知识:我要做 Web 测试,加载 webapp-testing skill
  • karpathy-skills 是行为规范:我在做任何编码任务,都应该遵守这四条原则

两者可以叠加使用,互不冲突。

为什么"给成功标准"比"给指令"更有效

Goal-Driven Execution 是这套规则中最值得深入思考的部分。

指令式指导的问题在于:它要求人类提前想好所有细节,然后把思维过程翻译成 AI 能理解的步骤序列。这既耗时,又容易出错——你的步骤描述一旦有歧义,AI 会按照它自己的理解执行,而不是你的意图。

目标式指导的优势在于:

  1. 降低认知负担:你只需要想清楚"什么算完成",不需要想清楚"怎么完成"
  2. 利用 LLM 的规划能力:LLM 其实很擅长把目标分解成步骤,这是它的强项
  3. 可验证性:成功标准是客观的,测试要么通过要么不通过,没有"差不多完成"

这和 OKR 的思路很像:定义关键结果(Key Results),而不是指定行动步骤(Action Items)。

踩坑提醒

这套规则非常有用,但有几个需要注意的地方:

1. 偏保守,简单任务不必全套用

"Think Before Coding"要求 AI 先列出假设和方案,对于简单任务会显得冗余。如果你只是要它写一个格式化日期的工具函数,直接要结果更高效。

2. "Surgical Changes"可能让 AI 错过明显问题

有时候你叫 AI 修 bug,顺路发现了一个明显的代码质量问题,但"Surgical Changes"原则会让它保持沉默。解决办法是:在任务描述中加一句"如果你发现其他潜在问题,请报告但不要自行修改"。

3. 目标式指导需要你能描述"成功"

Goal-Driven Execution 的前提是你知道什么是成功。如果你自己也不确定想要什么结果(探索性任务),这条原则就不太适用。

4. 不同工具的支持程度不同

这套规则最适合 Claude Code,因为 Claude Code 原生支持 CLAUDE.md。在 ChatGPT、Gemini 等工具中使用,需要手动复制粘贴规则内容到 system prompt。


Karpathy 的批评和 forrestchang 的 CLAUDE.md 提醒我们:工具的能力和工具的行为是两回事。LLM 已经具备了强大的编码能力,但如果没有正确的行为约束,这个能力就像一辆没有方向盘的赛车——跑得很快,但不知道会撞到哪里。

四条原则的本质是:把 AI 从"急于完成任务的执行者"变成"谨慎推理的协作者"。这不是限制 AI 的能力,而是让能力发挥在正确的方向上。