78.9k星!Karpathy力荐的AI助手编码规范
2025年初,AI研究员Andrej Karpathy在X上发了一条贴子,吐槽他使用LLM编程时反复遇到的几个问题:模型总是擅自做错误假设、从不主动澄清困惑、把简单需求搞成复杂架构、还会顺手改动本不该碰的代码。这条帖子引发了广泛共鸣——这不是某个模型的缺陷,而是当前LLM在编码任务中的通病。半年后,一个名为“Karpathy-Inspired Claude Code Guidelines”的开源项目出现在了GitHub上,它没有发明新的方法论,只是把Karpathy的观察转化成了一页纸的行为准则。如今这个项目已经收获了78.9k星,成为开发者配置AI编程助手的标配之一。
如果你平时用Claude Code、Cursor或者其他AI编程工具写代码,大概会遇到这样的场景:
-
你让AI“加一个导出用户数据的功能”,它二话不说开始写——默认导出所有用户、默认用JSON格式、默认存到项目根目录。它没问你任何问题,等代码跑起来才发现,用户表有几十万行,导出直接打爆内存。
-
你让AI“修复空邮箱导致验证崩溃的bug”,它不但修复了,还把整个验证逻辑重构成一个带策略模式的验证器,顺手加了类型注解和docstring。你看着diff里几十行改动,真正相关的只有两行。
-
你让AI“让搜索变快一点”,它开始写缓存、加async、连数据库索引都帮你规划好了。但你其实只是想优化一下前端搜索框的防抖。
这些问题的本质不是AI“笨”,而是AI的工作方式与人类的期望之间存在错位。Karpathy的贴子精准概括了这种错位,而本文介绍的这个项目则提供了一套可操作的矫正方案。
01
—
这个项目是什么
这是一个单文件的规范集,核心内容来自CLAUDE.md。它会告诉AI:不要猜、不要堆、不要乱动、要闭环。具体来说就是四个原则:
-
编码前思考(Think Before Coding)—— 先暴露假设和歧义,再动手
-
简洁优先(Simplicity First)—— 只写解决问题的必要代码
-
精准修改(Surgical Changes)—— 只改该改的,别顺手“优化”别的
-
目标驱动执行(Goal-Driven Execution)—— 把任务翻译成可验证的测试
原则一:编码前思考
AI最让人头疼的行为之一就是“擅自替你做决定”。你只说了半句话,它补全了剩下大半句,而且从不告诉你它补了什么。
这个原则要求AI在写代码之前先做这几件事:
-
明确说出自己的假设。比如你要导出用户数据,AI应该先问:导出全部还是分页?哪些字段?文件放哪?而不是直接开写。
-
遇到歧义时列出多种理解。比如“加一个日志”可以指打印到控制台、写入文件、还是上报到远程服务?AI需要把这些选项摆出来,而不是自己选一个。
-
如果存在更简单的方案,直接说出来并反问。AI不是被动执行者,它可以提建议。
-
搞不清楚就停下来,问清楚再继续。
在EXAMPLES.md中有一个很典型的对比:
❌ AI通常的做法:
def export_users(format='json'):users = User.query.all() # 导出全部用户,不问数量with open('users.json', 'w') as f: # 硬编码路径json.dump([u.to_dict() for u in users], f)
✅ 符合规范的做法(AI先输出问询):
在实现之前,我需要澄清几点:1. 导出范围:全部用户还是需要筛选?(考虑性能和隐私)2. 导出方式:浏览器下载 / 后台任务发邮件 / API端点返回数据?3. 包含哪些字段?是否有敏感字段需要排除?4. 数据量有多大?如果是百万级,需要分页或流式处理。最简单的实现:先做一个API端点,返回分页JSON。其他方式需要更多信息,你怎么看?
这一步的核心在于:把沉默的假设变成公开的提问。
原则二:简洁优先
AI有一种天然的“炫技”倾向——你让它算一个折扣,它给你整一套策略模式+工厂类+配置文件。200行代码解决的问题,明明20行就够了。
这个原则给出了几条硬性约束:
-
不添加任何没要求的功能。不要因为“以后可能会用到”就提前加。
-
不为一次性使用场景做抽象。如果只有一个地方用到,直接写死,别搞那么多层。
-
不添加未要求的“灵活性”或“可配置性”。参数能写死就别做成配置项。
-
不为不可能发生的场景写错误处理。比如一个函数接收整数参数,不需要判断参数是不是None。
-
如果200行能写成50行,那必须重写。
判断标准很简单:让一个资深工程师来看这段代码,他会说“过度设计”吗? 如果是,就简化。
同时项目也给出了一个容易被忽视的洞察:“过度设计”的问题不在于代码本身“错”,而在于时机不对。 在需求还不明确的时候就堆砌设计模式,会让代码更难理解、更容易引入bug、更难测试。而一个简单直接的版本,等你真的需要那些复杂性的时候,再重构也不迟。
原则三:精准修改
这是让很多团队头大的问题:你让AI修一个bug,它顺便把整个文件格式化了一遍,改了注释,加了类型标注,还重构了旁边一个函数。review的时候你根本分不清哪些改动是修bug,哪些是“顺便”。
这个原则的要求是:
-
不要“改进”相邻的代码、注释或格式。 哪怕你看到旁边有个丑陋的变量名,也别碰它——除非这次的任务就是要改它。
-
不要重构没坏的东西。
-
匹配现有风格,即使你个人更喜欢另一种写法。
-
如果你发现了无关的死代码,可以提一句,但不要顺手删掉。
-
当你自己的改动导致某个导入或变量不再被使用时,只清理你自己造成的垃圾,不要顺手清理原本就存在的死代码。
判断标准:diff中的每一行改动,都应该能直接追溯到用户的任务要求。
一个具体的例子(来自EXAMPLES.md):
用户要求:“修复空邮箱导致验证崩溃的问题”。
❌ AI的过度操作:改了邮件验证的逻辑,同时顺手加了用户名长度校验、加了docstring、换了引号风格、加了类型注解……
✅ 精准修改:只改动那两行导致空邮箱崩溃的代码,其他所有内容维持原样。
原则四:目标驱动执行
LLM有一个很强的能力:在明确的反馈循环中反复尝试直到达到目标。但很多用户给AI的指令是模糊的——“让系统更稳定”、“优化性能”、“重构一下”——这些不是目标,是方向。
这个原则要求把每一个任务翻译成可验证的成功标准:

对于多步骤的任务,AI应该输出一个简短的执行计划,每一步都要有明确的验证方式:
1. 添加基础的限流(单个接口) → 验证:压力测试,前10个请求成功,第11个返回4292. 提取成中间件(应用到所有接口) → 验证:/users和/posts两个接口都受到限流保护3. 接入Redis(支持多实例部署) → 验证:重启应用后限流记录不丢失
一旦有了这样的目标和验证步骤,AI就可以独立地执行、测试、修正、再测试,直到达成目标,而不需要你每步都要人工确认。
—
这些规则有效吗?
GitHub上78.9k的star本身就说明了一些问题。而项目的维护者给出了更具体的判断标准——如果你在使用这些规则后注意到以下几点,就说明它们在起作用:
-
diff中的不必要改动变少了——提交历史里不再有那些“顺手格式化”的噪音提交
-
返工/重写变少了——代码第一次写出来就比较简洁,而不是过度设计后再改回来
-
AI的澄清问题出现在编码之前——它先问清楚再写,而不是写完再暴露理解偏差
-
PR干净、聚焦——每个PR只做一件事,没有夹杂其他“小改进”
03
—
一点提醒
这个规范集有一个明确的倾向:谨慎优先于速度。对于修一个拼写错误、改一行配置这种琐碎任务,不需要严格执行所有步骤。但当你面对的是一个非琐碎的功能开发或bug修复时,这套规则能帮你省下大量因为AI“自作主张”而产生的时间。
最终,这个项目传达的核心信息并不复杂:不要告诉AI“怎么做”,给它清晰的成功标准,然后让它自己去验证。 而作为人类开发者,你需要的不是更聪明的AI,而是一套能和AI有效协作的约定。
项目地址:https://github.com/forrestchang/andrej-karpathy-skills
夜雨聆风