首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >别再让Claude Code瞎写了——Karpathy的4条行为规则

别再让Claude Code瞎写了——Karpathy的4条行为规则

作者头像
java金融
发布2026-07-07 18:19:05
发布2026-07-07 18:19:05
80
举报
文章被收录于专栏:java金融java金融

事情是这样的。

你把一个需求喂给 Claude Code:用户登录接口加个邮箱验证。逻辑很简单,你心里已经有谱了——不改现有表结构,加个 verified 字段,发一封验证邮件,半小时的事。

Claude 开始干活。

两分钟后,它新建了一个 EmailVerificationService 类,引入了一个 TokenGenerator 工具类,定义了一个 VerificationStatus 枚举(pending / sent / verified / expired / revoked),还顺手写了个 VerificationConfig 配置类,方便未来扩展。

你盯着屏幕看了一会,然后开始手动删代码。

这不是 Claude 傻。

不管你用的是 Claude Code 还是 Codex,这个问题都一样。Karpathy 在 X 上说过一段很准的话:

"模型会代你做错误假设,然后不假思索地执行。它们不管理自身的困惑,不寻求澄清,不呈现矛盾,不展示权衡,在应该提出异议时也不反驳。"

他接着说:LLM 特别爱把代码搞复杂,堆砌抽象,100 行能搞定的事非要写成 1000 行。还会顺手改动或删掉自己并不理解的代码和注释,哪怕这些改动跟当前任务完全无关。

你看到的现象,他都描述过了。

但问题不在这。问题是,怎么治

有个开源小哥(forrestchang)把 Karpathy 这些观察转化成了 4 条可执行的规则,打包到一个文件里。在 Claude Code 里叫 CLAUDE.md,在 Codex 里叫 AGENTS.md——本质上是同一套规矩。他还顺手做了一个 Claude Code 插件,上线当周就冲上了 GitHub Trending。

行,一条一条看。

第一层:它替你做了错误假设——而且不告诉你

回到开头那个登录验证的例子。

你把需求敲成一句话:"用户注册后需要验证邮箱。" Claude 接收到的信息就这么多。然后它开始自己填补空白:

  • 验证链接有效期 24 小时(你没说过)
  • 验证失败 3 次锁定账号(你没说过)
  • 需要支持重新发送验证邮件(你没说过)
  • 需要一个后台管理页面查看验证状态(你没说过)

每一个假设在特定场景下都可能合理,但没有一条是你说的。

更致命的是,它不会告诉你它做了这些假设。它直接写代码,就好像这些都是你提出的需求一样。等你发现的时候,代码已经改了 5 个文件,你要花 10 分钟逐行审读才能找出哪些是你想要的,哪些是它自创的。

Karpathy 说的"不管理困惑"就是这个意思。LLM 在遇到歧义时不会停下来问,而是默默选一个解释然后跑下去。

第一条规则:Think Before Coding(先想再写)。

这条规则强制 AI 在动手前先说出来:

  • 我现在有哪些假设
  • 这里有没有歧义,如果有,我该怎么理解
  • 有没有更简单的做法
  • 如果某个地方我不确定,我现在就问,而不是猜

CLAUDE.md 里它被写成:

代码语言:javascript
复制
- 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.

在真实场景里,这 4 句话能堵住 30% 以上的无用代码。

你试试看:下次给 Claude 一个模糊的需求,不带这条规则;再给一次,带上。你会发现第一条产出像刚毕业的实习生,第二条产出像跟你磨合过的同事。区别就在于——它会在写之前问你一句:"验证链接是 24 小时有效,还是不管时效?"

第二层:100 行能写完的,它给你写成 1000 行

LLM 有个根深蒂固的倾向:过度设计。

这不是能力问题。LLM 的训练数据里有太多"最佳实践"、设计模式、SOLID 原则的代码样本,它们学到的范式是:一个像样的工程就应该分层、解耦、扩展。

问题出在场景失配。你在做原型验证,它在写生产级框架。你只需要一个 if-else,它给你造了一个策略模式加责任链。

Karpathy 原话:

"它们真的很喜欢把代码和 API 搞复杂,堆砌抽象概念,不清理死代码……明明 100 行能搞定的事情,非要实现成 1000 行的臃肿架构。"

第二条规则:Simplicity First(简洁优先)。

规则写得极其直白:

代码语言:javascript
复制
- 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.

注意最后一条:"如果你写了 200 行但 50 行就能搞定,重写。"这不止是一条格式规则,它逼 LLM 做一次自我审计。

检验标准也很简单:Would a senior engineer say this is overcomplicated? If yes, simplify.

在真实的开发场景里,这条规则最直接的效果是:你的代码 review 从"这是什么东西"变成了"这里少了个空值检查"。差别不在代码量,在可读性和维护成本。

第三层:你让它改 A,它顺手把 B、C、D 也"优化"了

这是 LLM 编程助手最隐蔽的一个坑。

你让它改登录接口的错误码。它改完之后,觉得旁边的几个 handler 风格不统一,顺手 refactor 了一下。然后它看到有个变量命名不太满意,改了。然后又发现 test 文件里有个过时的 comment,删了。

你 git diff 一下,200 行改动,其中 150 行跟你的需求没关系。

表面看它很勤快。实际上它在制造风险——那些"顺手优化"的代码,它并不真的理解。它只是觉得"看起来应该这样"。

Karpathy 的观察:

"它们有时仍会改动或删除自己理解不足的代码和注释,即使这些内容与任务本身无关。"

第三条规则:Surgical Changes(精准修改)。

这条规则的核心是一个测试:Every changed line should trace directly to the user's request.

具体的约束:

代码语言:javascript
复制
- 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.

做减法也有边界——只删因你自己改动而变成孤儿的代码

代码语言:javascript
复制
- Remove imports/variables/functions that YOUR changes made unused.
- Don't remove pre-existing dead code unless asked.

这条规则在多人协作的项目里价值特别大。你合入一个 PR,reviewer 不需要花时间分辨"哪些改动是需求的、哪些是 AI 的自我表达"。每行改动的动机都可追溯。

第四层:你说"把它做好",它不知道什么叫"好"

这是 LLM 编程里最常见的沟通问题。

你给 Claude 的任务是:"把这段代码写好一点。"它可能理解为加注释、加类型标注、加异常处理、加日志、加单元测试。你在想的是"把那个 O(n²) 循环改成 O(n)"。

你和 LLM 之间没有共享的"好"的定义。

但 LLM 有一个被低估的能力:它在给定明确成功标准后,能自己循环验证直到达成。Karpathy 的原话:LLMs are exceptionally good at looping until they meet specific goals.

你不需要告诉它每一步怎么做。你需要告诉它"做完之后应该长什么样"。

第四条规则:Goal-Driven Execution(目标驱动执行)。

把指令式任务,转成可验证的目标:

原来的说法

改成

"加个验证"

"给 POST /register 写一个测试,传入未验证邮箱,断言返回 403;然后实现让它通过"

"修一下这个 bug"

"先写一个能复现这个错误的测试,确认它失败,再修代码让它通过"

"重构这段"

"重构前后所有现有测试通过;代码行数减少 30% 以上"

对多步骤任务,显式写计划:

代码语言:javascript
复制
1. 写一个复现 email 重复注册 500 错误的测试 → verify: 测试 fail
2. 在 register handler 里加唯一性检查 → verify: 测试 pass + 返回 409
3. 跑全量回归 → verify: 0 failures

很多 AI 编程辅助的翻车现场,复盘下来都是一个原因:成功标准太模糊。"把它做好"对 LLM 来说是空指令,"让这 12 个 test case 全部 pass"才是。

四条规则一起用,化学反应才出来

单独看每一条,都是常识。但四条放在一起,解决的是同一个根问题:LLM 缺少人类工程师的行为边界感。

一个人类工程师拿到需求,会自然地问:范围是什么?有没有简单的做法?这事儿以前做过吗?改完怎么验证?——这是经验带来的元认知。

LLM 没有这个。但你可以在 CLAUDE.md 里给它一套规则模拟这个边界感:

代码语言:javascript
复制
Think Before Coding    → 管理歧义和假设
Simplicity First       → 管理复杂度和抽象层级
Surgical Changes       → 管理改动范围和副作用
Goal-Driven Execution  → 管理成功标准和验证闭环

四条规则覆盖了 LLM 编码最脆弱的四个环节。任何一条单独用都有效果,但四条一起用才会改变你的工作流——从"分配任务然后审代码",变成"定义目标然后看它自己循环到达"。

README 里给了四个直观的验证信号,符合规则生效时你会看到:

  • diff 里无用的改动明显减少,只有你要求的修改出现在变更里
  • 因过度设计而重写的次数下降,第一版代码就基本可接受
  • 澄清性问题先于实现浮现,AI 会在写之前问你,而不是写错之后你才看出来
  • PR 干净、最小,没有顺手重构和"优化"——每一行改动都能追溯到你的某句话

工程上怎么落地

如果你用 Claude Code,最简单的落地方式是装插件:

代码语言:javascript
复制
/plugin marketplace add forrestchang/andrej-karpathy-skills
/plugin install andrej-karpathy-skills@karpathy-skills

装完后,这 4 条规则成为 Claude Code 的全局行为约束,所有项目都生效。

如果你用 Codex,更简单——打开桌面端,设置 → 个性化 → 自定义指令,把规则贴进去,全局生效。

其实你本地 ~/.codex/AGENTS.md 里可能已经有这套规则了。如果没有,两分钟就能贴好。核心就几句话:

代码语言:javascript
复制
## 编码前思考
- 明确假设,不确定时询问而非猜测。
- 存在歧义时,列出多种解释,不默默选一种。
- 如果任务有明显更简单的做法,直接指出。
- 发现矛盾或不一致时停下来,要求澄清。

## 简洁优先
- 用最少的代码解决问题。
- 不为一次性需求创建抽象层。
- 不为"万一以后需要"加灵活性和可配置性。
- 如果 200 行可以写成 50 行,重写它。

## 精准修改
- 只修改与当前任务直接相关的代码。
- 不顺手改进相邻代码、注释或格式。
- 匹配现有代码风格,即使你更偏好另一种写法。

## 目标驱动执行
- 定义清晰的成功标准再开始。
- "修复 bug" 转化为"写一个重现 bug 的测试,然后让它通过"。
- 多步骤任务先给简短计划,每一步带验证方式。

两分钟贴进去,以后少跟 AI 吵没用的架。

如果想按项目定制,直接把文件放到项目根目录:Claude Code 用 CLAUDE.md,Codex 用 AGENTS.md

落地时有几个关键点:

第一,先跑一周看看行为变化。

不要一上来就改规则。先用默认版本跑一周,对比改动前后的 diff 质量、review 时间、重写频率。收集完数据再决定是否需要调整。

第二,跟项目规则共存,不是替代。

这 4 条是行为规范,不是技术决策。你项目里已有的编码规范(lint、测试覆盖率、API 设计约定)继续用,把 CLAUDE.md 当成它们之上的行为层:

代码语言:javascript
复制
## Project-Specific Guidelines

- 所有 API 端点必须有集成测试
- 错误处理遵循 `src/utils/errors.ts` 的现有模式
- 数据库 migration 需要单独 review

第三,琐碎任务不要过度约束。

改一个拼写错误,不需要先写个测试再改。这 4 条规则的 tradeoff 是谨慎优先于速度。对于显然的一次性修改,跳过仪式。

第四,把"可验证目标"写成工程习惯。

这是第四条规则最难的部分——不是因为技术难,而是因为它要求你从"告诉 AI 做什么"变成"告诉 AI 成功长什么样"。这个思维转变需要练习。

一个小技巧:下次给 AI 分配任务时,在每句话后面加一句"验证方式是什么"。连续做两周,你会发现 bug 率明显下降。

面试怎么答

"你用过 AI 编程助手吗?效果怎么样?"——这个问题在工程面试里越来越常出现。

直接说"好用"没有区分度。能展开 4 层的人才算用过:

面试官要是问"怎么避免 AI 写多余代码",别回答"仔细 review"——这是废话。真正有效的做法是:在 CLAUDE.md.cursorrules 里加行为约束。3 条规则就够了:

  • 不添加需求之外的功能
  • 不为一次性代码建抽象
  • 不改风格不统一的相邻代码

这比事后 review 省 3 倍时间。

再问"AI 写的代码质量怎么保证"——不给模糊指令。"把这个函数优化一下"是模糊的。"给这个函数加 3 个边界 case 的单元测试,所有测试通过,代码不被改多"是可验证的。

面试官想听的是从指令驱动到目标驱动的转变。

最后如果问"AI 会不会把项目代码搞乱"——会的。Karpathy 自己都说了:LLM 会改动它不理解的代码。

解法不复杂:让 AI 在改动任何代码前先声明它的假设和范围,你不确认它不动手。这不是技术问题,是流程问题。四条规则本质上就是把这件事写成了自动化约束——Claude Code 里叫 CLAUDE.md,Codex 里叫 AGENTS.md

回到开头那个场景。

你给 Claude 一句话的需求,它给你 5 个文件的改动。你把 CLAUDE.md 丢到项目根目录之后再试一次。

这次它先停了下来,回了你一条消息:

"我只加一个 verified 字段和一个 send email 的 helper。验证有效期我不设,除非你指定。不改现有表结构,不改其他 handler。可以吗?"

可以。

你看,两分钟贴好的四条规则,把你以前说过的无数次"别瞎改"变成了它自己的一条消息。

参考资料

  • andrej-karpathy-skills - GitHub
  • Karpathy 原始推文
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2026-07-06,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 java金融 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 第一层:它替你做了错误假设——而且不告诉你
  • 第二层:100 行能写完的,它给你写成 1000 行
  • 第三层:你让它改 A,它顺手把 B、C、D 也"优化"了
  • 第四层:你说"把它做好",它不知道什么叫"好"
  • 四条规则一起用,化学反应才出来
  • 工程上怎么落地
  • 面试怎么答
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档