Karpathy 吐槽 LLM 写代码的 4 个毛病,有人做成了一份 73k Star 的 CLAUDE.md

如果你在用 Claude Code、Cursor、Copilot 写代码,大概率被 AI "自作聪明"坑过。

Andrej Karpathy 在 X 上吐槽了这件事,然后有人把他的吐槽做成了解决方案。

这篇文章讲清楚:他吐了什么槽、解决方案长什么样、你今天就能抄走用


先认识下吐槽的人

如果你是 AI 圈外的开发者,Karpathy 这个名字可能听着耳熟但说不准是谁。先花 30 秒介绍一下:

  • 前 OpenAI 创始团队成员
  • 前特斯拉 AI 高级总监,Autopilot 的掌舵人
  • 斯坦福 CS231n(深度学习视觉课)讲师,很多人入门 AI 就是看他的课
  • AI 教育圈公认最会"讲人话"的大神,B 站也有他的课程搬运

他最近在 X 上发了一条观察,吐槽大语言模型写代码时的几个典型毛病。这条推文本身没什么特别------谁都吐过类似的槽。但有意思的是:

一位叫 forrestchang 的开发者把这条吐槽,做成了一份 CLAUDE.md 文件,放到 GitHub 上。

结果这份文件,收获了 73k Star。

一份 markdown 文件,没有代码,没有脚本,比很多精心打磨的开源项目还火。

为什么?因为它解决的真的是所有 AI 编程用户的共同痛点。下面我把 Karpathy 的原话、这份 CLAUDE.md 的 4 条规则、以及你怎么用,一次讲清楚。


Karpathy 的原话:LLM 写代码的三宗罪

先看 Karpathy 原帖的三段核心吐槽(我翻译成大白话):

罪状一:瞎假设 + 不求证

"模型会替你做错误的假设,然后一路狂奔也不检查。它们不管理自己的困惑、不寻求澄清、不暴露不一致、不呈现权衡、该反驳的时候也不反驳。"

翻译过来就是:

你告诉它"做个用户登录",它不会问"用 JWT 还是 Session?用户密码怎么存?要不要记住登录?"------它会默默替你选一个,然后写 500 行代码,最后你发现选错了,全部推翻重来。

你说"这里有点问题,好像不太对",一个好的工程师会说"你是指 X 还是 Y?我倾向 X,因为......",而 LLM 经常就直接改,结果越改越离谱。

罪状二:过度工程上瘾

"它们特别喜欢把代码和 API 搞复杂,堆叠臃肿的抽象......不清理死代码......100 行能解决的事,它实现成了 1000 行的庞然大物。"

翻译过来就是:

你说"写个读取配置的函数",它给你整出来:

  • 一个 ConfigLoader 抽象类
  • 三个具体实现 JSONConfigLoaderYAMLConfigLoaderTOMLConfigLoader
  • 一个 ConfigLoaderFactory
  • 一个 ConfigLoaderRegistry
  • 再加上完整的错误处理、日志、缓存......

你:"我只是想读一个 .env 文件啊?"

罪状三:顺手改不该改的东西

"它们有时候会修改或删除自己并没有充分理解的注释和代码,哪怕这些跟当前任务完全无关。"

翻译过来就是:

你让它在某个函数里加一行日志。提交 PR 时你一看 diff:

  • ✅ 加了日志(你要的)
  • ❓ 顺手把附近一个函数的参数顺序改了
  • ❓ 删掉了一段"看起来没用"的注释(其实是团队的重要约定)
  • ❓ 把一个 const 改成了 let(毫无理由)
  • ❓ 甚至格式化了整个文件

这种"顺便优化"是 code review 里最让人头疼的事,因为你得一行行过,生怕它漏看哪里偷偷改了东西。


痛吗?痛就对了

上面这三条,只要你真用 AI 写过几周代码,一定全部中过枪

我自己最痛的一次:让 Claude 改一个 API 的返回格式,它改完顺手把请求参数校验逻辑"优化"了------实际上是把原来的校验函数删了,换成了一个更"优雅"但漏了一个边界情况的新函数。等到上线后用户反馈才发现。

这不是 Claude 蠢,这是它被训练得"太勤快" ------训练数据里那些"好代码"都是在重构里抽象出来的,所以它本能地想把你的代码也"优化"到那个样子。但问题是:

你只让它做 A,它顺手做了 A、B、C、D。多出来的 B、C、D 就是定时炸弹。

Karpathy 的洞察就在于:他把这种"AI 勤快病"总结清楚了,而 forrestchang 把它做成了可以直接贴给 AI 的规则。


解决方案:四条规则,一份文件

forrestchang 做的这份 CLAUDE.md,本质是把 Karpathy 的观察翻译成 AI 能理解、能执行的指令。它一共四条规则,每条都精准对应 Karpathy 吐槽的一个毛病:

规则 解决的毛病
Think Before Coding(先想再写) 瞎假设、藏着困惑、不讲权衡
Simplicity First(简洁优先) 过度工程、臃肿抽象
Surgical Changes(外科手术式修改) 顺手动不该动的代码
Goal-Driven Execution(目标驱动执行) 靠验证标准而不是指令细节

下面逐条讲。


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

核心要求

不要假设。不要藏着困惑。把权衡摆出来。

具体做法(这些会直接写进 CLAUDE.md 让 AI 遵守):

  • 明确说出假设 ------ 如果不确定,先问,别猜
  • 呈现多种解读 ------ 需求有歧义时不要默默选一个
  • 该反驳就反驳 ------ 有更简单的方案就直说
  • 困惑了就停 ------ 说清楚哪里不懂,要求澄清

实际效果对比

规则生效前(AI 常见行为):

vbnet 复制代码
用户: "给这个用户模块加个权限校验"

AI: "好的,我会实现一个完整的 RBAC 权限系统..."
    [开始写 800 行代码,包含角色表、权限表、中间件、装饰器]

规则生效后:

vbnet 复制代码
用户: "给这个用户模块加个权限校验"

AI: "开始实现前我想确认几点:
     1. 你是想要简单的"登录即有权限"的检查,还是需要细粒度的角色/权限控制?
     2. 看到你的代码里已经有 requireAuth 中间件,是基于这个扩展,
        还是要重新设计?
     3. 如果只是单个接口,我建议最小化改动,只在这个接口上加一行检查。
     
     倾向哪种?"

区别一目了然:第一种你会得到一堆没人要的代码;第二种你用 30 秒澄清,省下 2 小时返工。


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

核心要求

能解决问题的最少代码。不搞投机性设计。

具体禁令:

  • ❌ 不做没被要求的功能
  • ❌ 不为一次性代码做抽象
  • ❌ 不搞没要求的"灵活性"和"可配置性"
  • ❌ 不处理不可能发生的错误
  • ✅ 200 行能压成 50 行,就压

判断标准

资深工程师看到会不会说"这太复杂了"?会 → 简化。

这个标准非常关键,因为它不是死规则,而是一个可以让 AI 自我校验的启发式问题。

一个真实例子

我让 Claude 写一个"把字符串转成 slug"的函数(比如把 "Hello World!" 转成 "hello-world")。

没有这条规则时,它的输出:

python 复制代码
from typing import Optional, List
import re
import unicodedata

class SlugConfig:
    def __init__(
        self,
        separator: str = "-",
        lowercase: bool = True,
        max_length: Optional[int] = None,
        allowed_chars: Optional[str] = None,
        replacement_map: Optional[dict] = None,
    ):
        # ... 30 行初始化
        pass

class SlugGenerator:
    def __init__(self, config: SlugConfig):
        # ... 
    def generate(self, text: str) -> str:
        # ... 50 行
    def batch_generate(self, texts: List[str]) -> List[str]:
        # ... 你没要这个
    
# 外加单元测试类、异常类......

加了简洁优先规则后:

python 复制代码
import re

def slugify(text: str) -> str:
    return re.sub(r'[^a-z0-9]+', '-', text.lower()).strip('-')

两行代码,功能完全一样 。这就是"简洁优先"的力量------它不是让 AI 偷懒,而是让 AI 停止为想象中的需求做准备


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

核心要求

只碰必须碰的。只清理你自己弄出的烂摊子。

具体做法:

修改现有代码时:

  • ❌ 不"顺手改善"相邻的代码、注释、格式
  • ❌ 不重构没坏的东西
  • ✅ 匹配现有风格,哪怕你不喜欢
  • ✅ 发现无关的死代码 → 只提一下,不要删

你的改动产生孤儿代码时:

  • ✅ 删除因你的修改而变得无用的 import、变量、函数
  • ❌ 不要删除预先存在的死代码,除非被要求

判断标准

每一行改动,都必须能直接追溯到用户的某个请求。

这条规则听起来简单,但对 AI 是最难遵守的一条------因为它的训练数据让它天然觉得"看到能改进的就应该改进"。

为什么这条这么重要

因为顺手改的代码是 code review 的噩梦:

  • 你以为在 review 一个改动,结果发现要 review 5 个改动
  • 每个"顺手改"都可能引入 bug,而且最难排查
  • 团队代码风格被不断"微调",一致性崩坏
  • 任务复杂度会指数级增长:一次改 5 个地方 → 5 个地方都可能出问题 → 排查时间 x 5

加上这条规则后,AI 提交的 diff 会变得非常"干净"------你能一眼看完、一眼 review、一眼合并


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

这条是全篇最有价值的洞察,也是 Karpathy 原帖的灵魂。

Karpathy 的原话

"LLM 特别擅长围绕明确目标不断迭代。不要告诉它做什么,给它成功标准,看着它自己跑。"

翻译成实操

把命令式指令 → 转化为可验证的目标。

❌ 别这样说 ✅ 改成这样
"加个校验" "为非法输入写测试,让测试通过"
"修这个 bug" "写一个能复现 bug 的测试,然后让它通过"
"重构这个模块" "确保重构前后所有测试都通过"
"优化性能" "把这个函数的耗时从 X ms 降到 Y ms 以内"

为什么这个转变这么关键

命令式的问题:"加个校验"------ 加什么?加多严?加到哪一层?AI 得猜,你也得不停澄清。

目标式的好处 :"为非法输入写测试让它通过"------AI 可以自己循环:

  1. 写测试(定义什么叫"对")
  2. 写实现
  3. 跑测试
  4. 没过 → 改
  5. 过了 → 完成

整个过程不需要你干预。AI 自己就能判断成功与否。

多步任务的模板

对于复杂任务,用这个模板:

ini 复制代码
1. [步骤] → 验证:[检查项]
2. [步骤] → 验证:[检查项]
3. [步骤] → 验证:[检查项]

比如"实现用户注册":

markdown 复制代码
1. 写 API 接口 → 验证:curl 能拿到 200
2. 加入参数校验 → 验证:非法邮箱返回 400
3. 密码加密存储 → 验证:数据库里看不到明文
4. 发送确认邮件 → 验证:测试邮箱能收到

每一步都有验证,AI 就能独立推进。没有验证的任务("让它工作")需要你不断澄清。

这条规则的哲学意义

这其实不只是一条 coding 规则------它是和 AI 协作的根本范式转变:

旧范式:我是老板,AI 是员工,我给指令,它执行。

新范式:我是产品经理,AI 是整个工程团队。我定义成功标准(验收条件),它自己组织、执行、迭代。

这个转变一旦理解,你和 AI 的协作效率会整体跃升一个台阶------不只是写代码,写文章、做分析、跑数据都适用。


怎么用?两种方式

方式一:Claude Code 插件(推荐)

在 Claude Code 里执行:

bash 复制代码
/plugin marketplace add forrestchang/andrej-karpathy-skills
bash 复制代码
/plugin install andrej-karpathy-skills@karpathy-skills

装完后,这份规则对你所有的项目生效。

方式二:直接下载 CLAUDE.md(逐项目)

新项目:

objectivec 复制代码
curl -o CLAUDE.md https://raw.githubusercontent.com/forrestchang/andrej-karpathy-skills/main/CLAUDE.md

已有 CLAUDE.md 的项目,追加到现有文件末尾:

bash 复制代码
echo "" >> CLAUDE.md
curl https://raw.githubusercontent.com/forrestchang/andrej-karpathy-skills/main/CLAUDE.md >> CLAUDE.md

如何验证起作用了?

作者给了四个观察指标:

  1. diff 里的废话变少 ------ 只出现你请求涉及的改动
  2. 少因过度复杂而重写 ------ 第一次就写得简洁
  3. 澄清问题提在实现之前 ------ 不是等你发现错了才问
  4. PR 干净整洁 ------ 没有顺手的"改进"

装上一周后回头看看你的 commit history,如果这四个指标都改善了,说明规则在起效。


一个重要的 Tradeoff 提醒

作者在 README 末尾特别提到:

这份规则偏谨慎,牺牲速度换可靠性。对于简单任务(改错字、显而易见的一行改动),用你的判断力,不是每次改动都需要完整流程。

目标是减少复杂工作上的昂贵错误,而不是拖慢简单任务。

我的实际使用体验也是如此------装上之后,AI 会稍微"慢"一点,会问更多问题。

对于 prototype、一次性脚本、学习项目 :可能会觉得有点烦 对于生产代码、团队协作、长期维护的项目:价值巨大

建议:在你的主力工作项目里装,在玩具项目里别装


我自己的几条延伸思考

读完这个项目,我有三个更深的感悟,分享一下:

1. "AI 勤快病"的根源是训练数据的偏见

AI 之所以爱过度工程,是因为它训练数据里的"优秀代码"大多是经过多次迭代、抽象、重构的成熟代码------GitHub 上那些高 Star 项目、设计模式教科书的例子。

它看多了这些,就以为"代码就应该长这样"。

真实工作中,大部分代码的寿命只有几周、几个月,不需要任何抽象 。这份 CLAUDE.md 本质上是在纠正 AI 的训练偏见

2. Prompt Engineering 的范式正在变

三年前我们研究 prompt,重点是"怎么说才能让 AI 听懂"------咒语、few-shot、thought chain。

但 andrej-karpathy-skills 代表的是新范式:"怎么给 AI 定边界"。

从"教它怎么做"→ "告诉它不该做什么 "和"什么样算做完了"。

这个转变背后,是 AI 能力已经足够强,短板不在理解力,而在自律

3. 73k Star 说明了什么

一份没有代码、只有 4 条规则的 markdown 文件,能收获 73k Star------这背后揭示了几件事:

  • AI 工具的痛点正在从"能用"转向"好用" ------能力已经不是问题,用得舒服才是
  • "认知工具"可能比"代码工具"更有价值 ------帮人想清楚问题比帮人写代码更稀缺
  • 内容即产品 ------在 AI 时代,一份好的文档、一套好的规则,本身就可以是产品

结语

Karpathy 的这条观察之所以引发这么大共鸣,是因为它说出了所有 AI 编程用户心里的一个声音:

"我不需要 AI 更聪明,我需要它更克制。"

andrej-karpathy-skills 这份 CLAUDE.md 就是这句话的具象化。四条规则,没有任何黑科技,全是经验之谈。但经验之谈才是最稀缺的------因为经验是用踩坑换来的。

如果你在用 Claude Code,花 30 秒装一下这份规则。一周后你会回来给这篇文章点赞的。


参考资料

相关推荐
Garfield20059 小时前
VSCode SSH 连接远程服务器后,Codex 插件登录失败
服务器·vscode·ssh·claude·codex
bug制造者阿杜10 小时前
拯救 AI 生成的烂代码:Vibe Coding 后的重构指南
ai编程·claude
bug制造者阿杜10 小时前
如何创建高效的 Claude Code Skill 并实现团队共享
ai编程·claude
码路飞10 小时前
这周 AI 圈连炸两次:我把 Kimi K2.6 和 Claude Opus 4.7 都接进 OpenClaw 试了一遍
ai编程·claude
程序新视界12 小时前
使用Claude Code最需要做的一件事:与AI签订一份契约(CLAUDE.md)
claude
火锅国大侠1 天前
一张图 → 完整应用:我用 ClaudeCode 复刻了这个开发流程
ai编程·claude
streaker3031 天前
Agent 规则文件不想入库?用 symlink 单仓托管多项目规则
ai编程·claude
夏天的峰没有风1 天前
claude code 无法连接到 Anthropic 服务
claude
jerrywus1 天前
把 Obsidian 知识库接进 Claude Code:400 行代码实现 AI 长期记忆
前端·agent·claude