基于 Karpathy 观察的 LLM 编程陷阱,单文件 CLAUDE.md 规则集,包含「编程前先思考」「保持简洁」「主动暴露不确定性」等四条原则。
看看我的新项目 Multica——一个用于运行和管理可复用技能的编程 Agent 的开源平台。
关注我的 X:https://x.com/jiayuan_jy
一份用来改善 Claude Code 行为的 CLAUDE.md 文件,源自 Andrej Karpathy 对 LLM 编程陷阱的观察。
"模型会替你做出错误假设,然后顺着这些假设跑下去而不去验证。它们不管理自己的困惑,不寻求澄清,不暴露不一致性,不呈现权衡取舍,不在应该反驳的时候反驳。"
"它们真的很喜欢把代码和 API 搞得太复杂,堆砌抽象层级,不清理死代码……实现一个超过 1000 行的臃肿结构,明明 100 行就够了。"
"它们有时仍然会改动或删除自己没有充分理解的代码和注释作为副作用,即便这些代码和任务正交。"
四个原则汇聚在一个文件里,直接解决这些问题:
四项原则详解
不假想。不隐藏困惑。呈现权衡。
LLM 经常默默地选择一个解释然后直接开干。这条原则强制显式推理:
明确陈述假设——不确定时,问清楚而不是猜
呈现多种解释——存在歧义时不要默默地选一个
有理由时反驳——如果存在更简单的方案,说出来
困惑时停下来——说出不清楚的地方并请求澄清
对抗过度工程的倾向:
不做超出需求的特性
不为单次使用的代码创建抽象
不加没被要求"灵活性"或"可配置性"
不为不可能的场景写错误处理
如果 200 行能写成 50 行,就重写
检验标准:一位资深工程师会说这太复杂了吗?如果是,就简化。
编辑现有代码时:
不"改进"相邻的代码、注释或格式
不重构没坏的东西
匹配现有风格,即便你会有不同做法
如果注意到无关的死代码,提出来——不要删掉
当你的改动产生孤立代码时:
删除因你的改动而变得无用的 import/变量/函数
不要删除事先存在的死代码,除非被要求
检验标准:每行改动的代码都应该能直接追溯到用户的请求。
定义成功标准。循环直到验证通过。
将命令式任务转化为可验证的目标:
对于多步骤任务,陈述简要计划:
1. [步骤] → 验证:[检查项]
2. [步骤] → 验证:[检查项]
3. [步骤] → 验证:[检查项]
强有力的成功标准让 LLM 能独立循环。弱标准("让它能跑")需要不断澄清。
在 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
现有项目(追加):
echo "" >> CLAUDE.md
curl https://raw.githubusercontent.com/forrestchang/andrej-karpathy-skills/main/CLAUDE.md >> CLAUDE.md
该仓库包含一个提交的 Cursor 项目规则(.cursor/rules/karpathy-guidelines.mdc),所以当你用 Cursor 打开项目时同样的指南也会生效。详见 CURSOR.md,了解在其他项目中设置规则、与 Claude Code 的关系等内容。
"LLM 非常擅长循环直到达到特定目标……不要告诉它要做什么,给它成功标准然后看它跑。"
"目标驱动执行"原则捕捉到了这一点:将命令式指令转化为带有验证循环的声明式目标。
如果你看到以下迹象,说明这些指南正在生效:
diff 中不必要的改动更少——只出现被请求的改动
因过度复杂而重写的情况更少——代码第一次就很简单
澄清问题出现在实现之前——而不是出错之后
干净、最小化的 PR——没有顺便重构或"改进"
这些指南设计为与项目特定指令合并使用。将它们加入你现有的 CLAUDE.md 或创建一个新的。
对于项目特定规则,添加如下部分:
## 项目特定指南
- 使用 TypeScript 严格模式
- 所有 API 端点必须有测试
- 遵循 `src/utils/errors.ts` 中现有的错误处理模式
这些指南偏向谨慎而非速度。对于琐碎任务(简单的笔误修复、明显的一行代码改动),运用判断力——不是每个改动都需要全套流程。
目标是减少非平凡工作中的高代价错误,而不是拖慢简单任务。