跳至内容
用上这4个原则,为AI编程提效
所有文章 所有文章

用上这4个原则,为AI编程提效

托克
托克
云厂程序员,分享AI以及软件领域实践

Andrej Karpathy 最近写了一份 CLAUDE.md 示例,只有 4 条规则。

有人拿去测了:编码准确率从 65% 涨到 94%。

不是模型变强了,是约束条件做对了。

Karpathy 是谁不用多说。Tesla AI 前总监,OpenAI 创始成员。他识别的不是"怎么让 AI 写更好代码",而是 AI 编码助手最常见的 4 种失败模式,然后给每条配了一条行为契约。

这 4 条后来被扩展成 12 条,在 GitHub 上拿了 82,000 星。但核心没变:不是让 AI “更聪明”,而是让它别在同样的地方摔倒

你的 AI 为什么总在重复犯错

打开你的 CLAUDE.md,大概率能看到这种话:

  • 写高质量代码。
  • 仔细思考。
  • 保持简洁。

然后呢?

AI 点头说"好的",然后继续犯同样的错。

需求没对清楚就开始改。修一个小 bug 顺手把旁边一片代码也动了。假设项目里有某种约定,然后写出一套"看起来合理"、但和当前代码库完全不搭的实现。

最麻烦的不是它犯错,而是它犯错的过程很有迷惑性。先偏一点,再修一点,再偏一点。你看着它忙来忙去,甚至会觉得它快好了。最后才发现,它不是在靠近答案,是在被污染的上下文里继续打补丁。

从一个真实案例说起

我手头有个老 Go 项目,依赖 GOPATH 管理,但本地装的是默认用 go module 管理依赖的高版本 Go。

每次让 agent 跑测试,它都直接执行 go test ./...,报错后开始自我修正:先试 go mod init。不对。再试 GO111MODULE=off。还是不对。再试手动设置 GOPATH 指向某个它猜的目录。

来回自纠了四五轮才搞定。

实际上,直接把"本项目使用 GOPATH 模式管理依赖"写进 CLAUDE.md,一行就能解决。

但 agent 不知道这条信息存在。所以它每次都要重复试错。

我当时想解决的不是"怎么让 AI 更聪明"。

是更朴素的问题:能不能有一个地方,把这些重复出现的问题写下来,让 agent 每次进项目之前先看到?

记忆系统无法解决团队协作问题

我一开始用过 IDE 自带的记忆系统,把项目规约、常见坑和个人偏好塞进去。有用,但不够稳。

一个问题是记忆太个人化。个人项目里还好,多人项目里就会变成隐形分叉:同一个 repo,不同开发者的 agent 带着不同记忆工作。有人知道这个项目不能引入某个库,有人不知道;有人知道某个老模块不能随便重构,有人不知道。代码库没有分叉,上下文先分叉了。

另一个问题是加载不确定。你以为它记住了,但你不知道它在当前任务里到底有没有看到。简单任务可能没事,复杂任务一长,关键规则就可能被挤出上下文或者选择性遗忘。

后来我才觉得,项目里真正关键的规则不应该只放在某个人的私人记忆里。它应该进仓库,被版本管理,跟代码一起被所有人看到。CLAUDE.md 对我来说就是这个定义:不是更长的系统提示词,而是项目仓库级别的协作约定。

不再滥用 /init

刚开始用 Claude Code 时,我也用过 /init。它扫一遍项目,生成一份 CLAUDE.md,看着是很省事。但我很快发现一个问题:它太喜欢把代码细节写成长期上下文。

目录结构、模块说明、当前命令、实现细节,这些东西短期看有帮助,长期很容易变成旧地图。代码一改,CLAUDE.md 里的描述就开始腐化。更糟的是,agent 可能会相信这份旧描述,而不是重新读代码。

我现在更倾向于让代码细节留在代码里。AI 编码智能体本来就擅长现场搜索:读调用方、查导出、看测试、顺着工具函数摸上下文。根 CLAUDE.md 不该抢这个工作,它只需要告诉 agent 哪些事每次都要知道,哪些边界不能踩。

后来我试过把 CLAUDE.md 清空,从头手写。只保留两类内容:给 AI 的通用编码规则,以及这个项目专属的规则。效果比预期好了很多。agent 还是会犯错,但更少乱发散,也更少擅自改无关代码,同时生成的代码风格品味和质量也变高了。它像是终于知道这个项目不是一个随便发挥的空白练习场。

Karpathy 的 4 条铁律

Karpathy 的 4 条编码铁律非常短。短到你会怀疑"就这些?"

1. Think before coding. State your assumptions. Surface tradeoffs.
   Ask before guessing. Push back when a simpler approach exists.

2. Simplicity first. Minimum code that solves the problem. No
   speculative features. No abstractions for single-use code.

3. Surgical changes. Touch only what is asked. Do not "improve"
   adjacent code, comments, or formatting. Match existing style.

4. Goal-driven execution. Define success criteria. Loop until
   verified. Do not narrate steps; tell me what success looks like.

翻译成中文,就是四个问题:

Rule 1 - 编码前先思考,别直接开写

AI 最常见的失误:面对有歧义的需求默不作声,直接动手写。结果发现理解有误,只能推倒重来。

对应的契约:在处理非琐碎任务前,先阐明你的前提假设。遇到不确定的细节要主动发问。如果察觉到存在更简单的方案,要敢于提出异议。

Rule 2 - 简单优先,别过度工程

AI 为了"专业"会加抽象、加配置、加工具函数。看起来厉害,但后面的 agent 会继续沿着这个复杂结构扩建。

对应的契约:写解决当前问题所需的最少代码。不要实现用户没要求的功能。单次使用的逻辑不要提前抽象。

Rule 3 - 手术刀式修改,别顺手重构

老代码库里很多难看的代码不是没人看见,而是不敢轻易动。它可能背着历史兼容、客户定制、线上事故后的补丁。

AI 没有这种历史负担。看到重复就想消除,看到不一致就想统一。在修 bug 的任务里,这是风险。

对应的契约:只改被要求修改的部分。不要"顺手改进"相邻代码、注释或格式。匹配现有风格。

Rule 4 - 目标驱动,别自说自话

AI 最怕的不是"我不知道",而是"我觉得我知道"。自信满满地给出一个错误方案,比承认不确定要危险得多。

对应的契约:定义成功标准。循环验证直到达成。不要 narrate 步骤,告诉我成功长什么样。

这 4 条不是"我希望你怎样"。而是"在这个场景下,你必须怎样做"。

差别就在这里。

为什么这 4 条比 20 条更有效

Karpathy 的 4 条后来被扩展成 12 条。但有个反直觉的发现:规则超过 14 条后,AI 的合规率反而从 76% 掉到 52%。

为什么?

规则一多,每条规则的权重就变轻了。模型会"平均"掉所有规则,最后谁都不记得。

一个贴合项目的 6 条规则,通常比复制来的 20 条更有用。

所以我现在的做法:先放 Karpathy 的 4 条作为基线。然后根据项目真实失败模式,一条一条加。每加一条都要能对应一个具体场景:“上周 AI 在这个地方摔过跤”。

加的时候问自己:这条规则如果不存在,AI 会在哪个具体场景下犯错?

答不上来,就别加。

从 4 条到 12 条:什么时候扩展

Karpathy 的 4 条处理的是"写代码这一刻"。但在实际 agentic workflow 中,失败模式远不止这 4 种。

后来扩展的 8 条,补的是这些缺口:

  • Token 预算不是建议:长调试会话里,AI 会重复尝试、上下文污染,最后把问题越修越偏。
  • 每个重要步骤后 checkpoint:多步骤任务中,错误会在后续步骤上继续叠加。
  • 测试验证意图,不只验证行为:AI 会写"会通过但不验证业务意图"的浅测试,制造虚假信心。
  • 暴露冲突,不要折中平均:遇到两套冲突代码风格时,AI 可能"取平均"写出第三种怪物。
  • 匹配代码库约定,即使你不同意:AI 可能引入自认为更好的新范式,导致同一代码库双模式并存。
  • 只把模型用于判断题:让 LLM 处理重试、路由、状态码等确定性逻辑,是浪费且危险的。

这些不是否定 Karpathy 的 4 条,而是说:先守住基线,再按需扩展

我的建议是:新项目先用 4 条跑两周。每次 AI 犯错,判断是不是这 4 条没覆盖到。如果是,再加一条。不是,就修现有规则的表述。

项目规则不要写成百科

通用规则只是底座。而真正让 agent 在一个项目里跑顺的,还是项目自己的规则。

我现在会优先写这些东西:

  • 项目用什么技术栈和依赖管理工具
  • 常用的命令清单
  • 应该怎么本地验证和测试
  • 有哪些外部依赖和中间件

验证闭环尤其值得写清楚。比如:

修改后优先运行 pnpm typecheck。
涉及 API 行为时运行 pnpm test:api。
涉及 UI 时启动本地 dev server,并用浏览器确认关键页面可打开。
如果无法运行验证命令,必须立即退出并说明原因。

还有一类项目规则,我不会一开始就靠想象补全,而是边用边加。每次 agent 跑得不顺,任务结束前可以让它复盘一句:

仔细回顾一下刚刚犯过的一些错,并将经验教训用简明的语言总结成不超过 2 句话的项目开发原则。

这句话你可以直接专门写个 skill,每次任务跑完之后用下这个技能,然后由人再判断这句话值不值得写进 CLAUDE.md。注意只有从真实失败里长出来的项目规则,才更可能在下一次派上用场。真实工程里面从来没有银弹。

根 CLAUDE.md 更像入职说明

日常工作中,我会把 AI 编码智能体当成一个刚接手项目的实习生。它很聪明,读得快,也愿意干活,但它不知道项目为什么长成这样,不知道哪里不能碰,也不知道团队过去在哪些地方踩过坑。

给新同事做 onboarding 的时候,你不会把公司历史和每个模块的实现细节全塞给他。你会先说清楚几件事:项目在做什么,用什么技术栈,怎么测试验证改动,哪些目录高风险,遇到不确定该去哪里查。

CLAUDE.md 也差不多。根文件放每次都要知道的最小知识集,不放会频繁过时的细节。代码细节让 agent 现场搜;可选上下文放在 docs/ 或 Skills 里,让模型认为有相关性时再渐进式加载。

最终一个足够直接拿来用的结构可以很短:

# CLAUDE.md

## 项目
本仓库是一个 [项目类型]。
核心目标:[系统用来做什么]。
主要用户:[内部运维 / 客户 / 开发者]。

## 行为规则
- 编码前先思考:非琐碎任务开始前,先复述需求、成功标准和关键假设。
- 简单优先:写解决当前问题所需的最少代码;避免猜测性抽象。
- 手术刀式修改:只修改任务必需的文件;未经确认不要重构相邻代码。
- 先读后写:添加新代码前,先检查已有导出、调用方、测试和本地约定。
- 大声失败:如果跳过了检查或存在不确定性,要明确说明。

## 项目规则
- 使用 [包管理器] 管理依赖和脚本命令。
- 未经确认不要引入 [库 / 模式 / 服务]。
- 遵循 [关键目录] 中的已有模式。
- 修改 [XX模块] 前,先阅读 [docs/路径.md]。

## 验证
- TypeScript 改动后运行 [类型检查命令]。
- 逻辑改动后运行 [测试命令]。
- 如果任何命令无法运行,说明跳过了什么以及原因。

## 其他
- 架构细节放在 docs/architecture.md。
- API 契约放在 docs/api.md。
- 历史决策放在 docs/decisions.md。
- 只在相关时按需加载,不要把它们的内容抄进本文件。

这份模板不是让你照抄,而是给一个边界感:根文件只负责稳定事实、行为边界、项目红线、验证闭环和上下文路由。它越像百科全书,越容易变成噪音。

什么时候更新

CLAUDE.md 不是那种一次写完就不修改的文件。我更愿意把它当成测试一样维护:agent 犯了一个你不想再看到的错,就问它是不是可复发的失败模式;如果是,再看一条短规则能不能提前拦住。

如果某条信息每次任务都需要知道,放进根 CLAUDE.md。如果只在某类任务里需要,放进对应文档或 skill。如果必须强制执行,别只靠文字,交给 hooks、测试或 CI。

这也是我不喜欢把 CLAUDE.md 写得太长的原因。规则太多之后,每条规则都变轻了。一个贴合项目的 6 条规则,通常比复制来的 20 条规则更有用。

立刻开始

打开你的项目根目录。

创建一个 CLAUDE.md

把 Karpathy 的 4 条贴进去,然后补充最基本的项目说明和测试验证规则:

# CLAUDE.md

## 通用编码规则

1. Think before coding. State your assumptions. Surface tradeoffs.
   Ask before guessing. Push back when a simpler approach exists.

2. Simplicity first. Minimum code that solves the problem. No
   speculative features. No abstractions for single-use code.

3. Surgical changes. Touch only what is asked. Do not "improve"
   adjacent code, comments, or formatting. Match existing style.

4. Goal-driven execution. Define success criteria. Loop until
   verified. Do not narrate steps; tell me what success looks like.

## 项目专有规则

技术栈:
依赖管理:
测试:
lint:

补充规则:
- XXX
- XXX

通过 ln -s CLAUDE.md AGENTS.md 链接兼容类似 Qoder 这样的 IDE。

然后跑两周。

每次 AI 犯错,记下来。判断是这 4 条没覆盖到,还是它根本没遵守。

如果是没覆盖到,加一条。如果是没遵守,修表述。

两周后,你会有一份真正属于你的 CLAUDE.md:不是从别人那里复制来的,是从你的真实失败模式里长出来的。

CLAUDE.md 不是为了让 AI “记住我说过什么”。

它不会让 agent 不犯错。但会让错误少一点、偏航短一点、返工可控一点。

Karpathy 的 4 条原则不是终点,是起点。

真正改变的其实不是 AI 的行为,而是你把那些本来只存在于人脑里的隐形上下文,变成了项目的一部分。

阅读