andrej-karpathy-skills:把 AI 编程的坏习惯写成约束
这篇文章解决什么问题
andrej-karpathy-skills 看起来像一个很小的仓库:核心只是一个 CLAUDE.md,再加上 Claude Code plugin、Cursor rules 和示例文件。
但它真正值得看的地方,不是文件多复杂,而是它抓住了 AI coding agent 最容易翻车的几个点:
- 自己脑补需求,然后一路做下去
- 明明有歧义,却不问
- 喜欢加抽象、加配置、加“以后可能会用”的功能
- 顺手改不相关代码、注释、格式
- 没有完成标准,只是在“看起来差不多”时停下
这个仓库的目标很直接:把这些坏习惯压进一份可复用的行为规则里,让 coding agent 在写代码前、写代码中、交付前都有约束。
仓库地址:
采集时间:2026-04-29
先说结论
- 这个仓库不是一个框架,也不是一个复杂工具链。
- 它更像一份“给 AI 程序员的工作纪律”。
- 核心内容是四条原则:编码前思考、简洁优先、精准修改、目标驱动执行。
- 它适合放进
CLAUDE.md、Cursor rules 或 coding agent plugin 中,长期约束 AI 的代码修改行为。 - 它的价值不在于让 AI 更“聪明”,而在于让 AI 更少自作主张。
如果你经常用 Claude Code、Cursor、Codex 这类工具改代码,这类规则比单次 prompt 更有用。因为单次 prompt 解决的是这一次怎么做,项目规则解决的是每一次都不要乱做。
它从什么问题出发
仓库 README 里引用了 Andrej Karpathy 对 LLM 编码问题的观察,大意是:
- 模型会替你做错误假设,而且不检查
- 模型不会管理自己的困惑
- 模型不会主动暴露矛盾和权衡
- 模型该反驳时不反驳
- 模型喜欢把代码和 API 做复杂
- 模型会改到自己没理解的代码,即使那些代码和任务无关
这些问题在真实项目里很常见。
比如你说:
帮我加一个导出用户数据功能。
一个不受约束的 agent 可能直接写:
- 导出所有用户
- 默认导出 JSON 和 CSV
- 默认字段包含 email、name、id
- 默认写到服务器本地文件
- 顺手加一个抽象的
ExportService
但真实需求可能是:
- 只能导出当前筛选条件下的数据
- 不能导出敏感字段
- 应该走后台任务
- 文件应该上传到对象存储
- 前端只拿下载链接
所以问题不只是“代码写错了”,而是 agent 在需求还不清楚时已经替你做了很多产品、权限、架构决策。
andrej-karpathy-skills 试图解决的正是这个入口问题:AI 不应该在关键不确定性上偷偷做决定。
仓库里有什么
截至我查看时,这个仓库主要包含这些内容:
| 文件或目录 | 作用 |
|---|---|
CLAUDE.md | Claude Code 行为规则,核心文件 |
.claude-plugin | Claude Code plugin 相关配置 |
.cursor/rules | Cursor 项目规则 |
skills/karpathy-guidelines | 可复用 skill 形式的规则 |
EXAMPLES.md | 展示常见错误写法和更好的写法 |
README.md / README.zh.md | 英文和中文说明 |
这说明它不是只服务某一个工具,而是在做一件更通用的事:
把“AI 写代码应该遵守什么纪律”整理成可迁移的文本规则。
四条原则怎么理解
1. 编码前思考
这条原则解决的是“AI 偷偷假设”。
很多 coding agent 最大的问题不是不会写代码,而是太快开始写代码。它会在下面这些问题上自动选一个答案:
- 这个功能是前端做,还是后端做
- 是新增页面,还是改已有页面
- 是覆盖旧逻辑,还是兼容旧逻辑
- 是一次性脚本,还是长期能力
- 是修一个 bug,还是顺便重构整个模块
人类工程师如果不知道,会停下来问。AI 往往不会。
所以这条规则要求 agent 在动手前做几件事:
- 明确说出假设
- 有多个解释时列出来
- 发现更简单方案时要说出来
- 看不懂时停下,而不是继续猜
这不是让 AI 变慢,而是避免它把错误方向做得很完整。
一个好的 agent 响应不应该是:
我已经实现了导出功能。
更应该是:
“导出用户数据”有几个歧义:导出范围、字段、格式、权限、数据量。最小方案是新增一个分页 JSON 导出接口。如果你要文件下载,需要确认格式和存储位置。
这一步看似多问了一次,实际是在避免后面十倍返工。
2. 简洁优先
这条原则解决的是“AI 过度工程”。
LLM 很容易写出看起来很专业、实际很臃肿的代码。比如一个折扣计算,本来只需要:
javascript
function calculateDiscount(amount, percent) {
return amount * (percent / 100)
}它可能会写出:
DiscountStrategyPercentageDiscountFixedDiscountDiscountConfigDiscountCalculatorValidationService
这些东西不是永远不该有,而是现在还不该有。
这也是仓库里很重要的判断标准:好代码不是提前解决明天所有问题,而是简单解决今天的问题,并且未来真有需求时还能改。
简洁优先不是反对架构,而是反对没有需求支撑的架构。单次使用的逻辑,不要急着抽象。没有被要求的配置,不要先做。不存在的错误场景,不要为了“严谨”加一堆分支。
在 AI 编程里,这条尤其重要,因为 agent 写代码成本低,导致它更容易“多写一点”。但真实项目里,多出来的代码不是免费资产,它会变成阅读成本、测试成本和维护成本。
3. 精准修改
这条原则解决的是“顺手改”。
AI 很喜欢在修一个小 bug 时,顺便做这些事:
- 统一格式
- 改注释
- 加类型标注
- 调整函数命名
- 重排 import
- 重构相邻逻辑
这些变化单独看可能都不坏,但它们会制造三个问题。
第一,diff 变大,review 成本变高。
第二,不相关修改混在一起,出了问题很难回滚。
第三,agent 很可能改到自己没完全理解的代码。
所以 andrej-karpathy-skills 要求:
- 只碰必须碰的代码
- 匹配现有风格
- 不重构没坏的东西
- 发现无关死代码可以提,但不要删
- 只清理自己这次改动造成的无用代码
这条对老项目尤其关键。老项目里很多代码看起来“不优雅”,但背后可能有历史兼容、线上数据、第三方接口、灰度逻辑。AI 不知道这些上下文时,最安全的做法不是“顺手优化”,而是保持修改边界清晰。
4. 目标驱动执行
这条原则解决的是“没有完成标准”。
很多指令太模糊,比如:
- 修一下登录问题
- 优化搜索
- 加一个校验
- 重构这个模块
如果没有完成标准,agent 只能凭感觉结束。它可能跑了部分测试,也可能只看了代码,也可能只是没有报错就认为完成。
目标驱动执行要求把任务改写成可验证目标:
| 模糊指令 | 更好的目标 |
|---|---|
| 加校验 | 为非法输入补测试,然后让测试通过 |
| 修 bug | 先写复现用例,再修到用例通过 |
| 重构模块 | 重构前后同一组测试都通过 |
| 优化搜索 | 明确是降低响应时间、提高吞吐,还是改善感知速度 |
这条原则的关键不是“必须测试先行”,而是必须知道怎么证明完成。
对 coding agent 来说,成功标准越具体,越能自动循环。如果标准只是“弄好”,它就会自己决定什么叫好;如果标准是“这个测试失败后通过、这个页面仍可打开、这个接口返回结构不变”,它就有明确的停点。
它和普通项目规则有什么区别
普通项目规则经常写这些内容:
- 使用什么语言
- 目录怎么放
- 命名怎么做
- 不要新增依赖
- 提交前跑什么命令
这些规则管的是“项目风格”。
andrej-karpathy-skills 管的是“agent 行为”。
两类规则应该合在一起用。比如:
markdown
## 项目规则
- 不新增依赖
- 修改 Vue 文件时参考同目录风格
- 多语言文案写在当前页面
## Agent 行为规则
- 不清楚就先问
- 不做需求外功能
- 不顺手重构
- 交付前说明验证方式项目规则告诉 agent 这个仓库怎么写;行为规则告诉 agent 不要用错误方式写。
一个实际例子:修复搜索变慢
假设你对 agent 说:
搜索有点慢,帮我优化一下。
没有规则时,agent 可能会直接上缓存、异步、索引、分页、预加载,甚至引入新依赖。
按这四条原则,它应该先拆问题。
编码前思考
它应该指出“慢”至少有三种含义:
| 解释 | 可能方案 |
|---|---|
| 单次响应慢 | 查 SQL、索引、接口耗时 |
| 并发能力差 | 连接池、队列、限流 |
| 用户感觉慢 | loading、骨架屏、增量渲染 |
如果没有指标,它不应该静默选择其中一个。
简洁优先
如果当前问题只是某个查询缺索引,就不要先做全局搜索架构。先加最小修改。
精准修改
只改搜索相关查询或索引,不顺手重构整个 service,不改无关命名。
目标驱动执行
完成标准可以是:
- 复现慢查询
- 记录优化前耗时
- 修改后同样条件下耗时下降
- 原搜索结果顺序和字段不变
这就是这份规则真正想带来的变化:不是让 agent 说得更像专家,而是让它工作方式更像靠谱工程师。
它适合怎么用
适合直接放进项目规则
如果一个项目长期使用 AI agent 改代码,可以把核心四条合并进项目级 CLAUDE.md、AGENTS.md 或类似文件。
适合的项目:
- 代码量较大
- 历史逻辑较多
- review 成本高
- 多人协作
- 经常让 AI 做小步修改
这类项目最怕 agent 自作主张。规则越早固定,后续 diff 越干净。
适合作为个人全局规则
如果你在多个项目里使用同一个 coding agent,也可以把它装成 Claude Code plugin 或 Cursor rule。这样不用每个项目都复制一份。
但要注意:全局规则只适合放通用行为,不适合放项目细节。比如“不要顺手重构”适合全局,“这个项目不使用 TypeScript”应该放项目内。
适合和本地项目规则叠加
最佳方式不是二选一,而是叠加:
- 全局层:约束 agent 行为
- 项目层:约束技术栈、目录、风格
- 当前任务层:定义这次任务的完成标准
这样 AI 才不会只知道“怎么写代码”,还知道“这次为什么写、写到哪里算完”。
最小落地清单
如果只是想把这套方法用起来,不需要一开始就把所有文件都搬进项目。更稳的做法是先落三层规则。
第一层,放通用行为约束:
- 不确定就先说出不确定
- 有歧义就列方案和权衡
- 不做需求外功能
- 不顺手重构无关代码
- 交付时说明验证方式
第二层,叠项目专属约束:
- 当前项目使用什么技术栈
- 哪些目录不能随意改
- 是否允许新增依赖
- 是否允许主动跑 lint、format、build、test
- 回复语言、提交格式、注释要求是什么
第三层,在每次任务里补完成标准:
- 哪个现象算修好
- 哪些文件或页面是修改范围
- 哪些命令或人工检查能验证结果
- 哪些事情明确不做
这三层合在一起,才比较接近真实工程里的“边界”。只放四条原则,容易太泛;只放项目规则,又管不住 agent 的工作方式。
它不适合什么场景
这份规则也有代价。
它偏谨慎,所以在非常简单的任务里可能显得重。比如:
- 改一个错别字
- 改一个固定链接
- 删除一行明显无用的日志
这些任务不需要完整计划和多轮确认。仓库 README 也明确提到,它的目标是减少非琐碎任务里的高成本错误,不是拖慢简单任务。
另一个边界是:规则不能替代上下文。
如果项目里没有测试、没有运行说明、没有清晰模块边界,agent 仍然可能做不好。规则只能减少乱猜,不能凭空补齐项目知识。
对当前项目有什么启发
这个仓库最值得借鉴的不是具体文案,而是它的规则形态。
对一个文档项目、前端项目或业务系统来说,可以直接吸收这些做法:
- 每次任务开始前写清完成标准
- 有多个方案时列优缺点,并明确推荐项
- 修改前先看相关模块,不凭空假设
- 不主动扩大范围
- 不把页面专属内容抽到全局
- 不顺手跑格式化造成大 diff
- 交付时说明改了哪些文件、哪些没有验证
这些规则看起来像沟通习惯,实际会影响代码质量。
因为 AI agent 最大的问题通常不是能力不够,而是边界感不够。andrej-karpathy-skills 的价值,就是把边界感写成固定约束。
最后总结
andrej-karpathy-skills 是一个很小但方向很准的仓库。
它没有试图发明新的 coding agent,也没有包装复杂流程,而是把 AI 写代码时最常见的失败模式压缩成四条可执行规则:
- 先想清楚,不要偷做假设
- 先写简单,不要提前架构
- 只改必要范围,不要顺手优化
- 先定义完成标准,再循环验证
如果你已经在认真使用 AI 改项目,这类规则应该尽早进入项目文档。它不会让 AI 每次都写出完美代码,但能明显减少最烦人的那类问题:改太多、想太多、猜太多、验证太少。