编程 当 Karpathy 用 65 行 Markdown 收编 149K 程序员:AI 编程纪律的 4→12 条进化史——从「先思考再写代码」到「Token 预算不是建议」的生产级完全指南

2026-06-20 13:26:04 +0800 CST views 15

当 Karpathy 用 65 行 Markdown 收编 149K 程序员:AI 编程纪律的 4→12 条进化史——从「先思考再写代码」到「Token 预算不是建议」的生产级完全指南

引子:一个只有 65 行的文件,凭什么拿到 GitHub 历史上增长最快的 Star 数?

2026 年 1 月下旬,Andrej Karpathy——前 Tesla AI 总监、前 OpenAI 创始成员——发了一串帖子,不是分享什么新模型架构,也不是宣布什么融资消息。他只是抱怨 Claude 写代码的几个毛病:

  • 默默做假设,不问你到底想要什么
  • 把 100 行能搞定的事膨胀成 1000 行
  • 顺手把旁边没坏的代码也「优化」了
  • 改完就走,不管 bug 复现了没、测试通过了没

这串抱怨,程序员读完会有两种反应。第一种:「我也是!」第二种:「但这不就是所有新手程序员的毛病吗?」

Forrest Chang 属于第一种,但他做了第三种反应——他把这些抱怨提炼成 4 条行为规则,写进一个叫 CLAUDE.md 的文件,放到 GitHub。

第一天:5,828 Star。两周内:60,000 Bookmark。今天:149K+ Star。

这是 2026 年 GitHub 上增长最快的单文件 repo。没有代码,没有框架,没有 API。只有 65 行 Markdown。

为什么?因为这 65 行解决了一个真实存在的问题:AI 编程工具越来越强大,但越来越不可控。 程序员不是缺 AI 写代码的能力,而是缺一种让 AI 写代码时「守规矩」的方法。

这篇文章不是又一篇「Karpathy 四原则介绍」。那类文章已经够多了。我要做的是:从这 4 条规则出发,追踪它们在真实项目中的失效模式,展示从 4 条到 12 条的进化过程,最终给你一份可以直接放进项目根目录的生产级 CLAUDE.md。


第一部分:AI 编程的纪律危机——为什么你的 AI 助手像一个没有 code review 的实习生

1.1 问题不是「AI 写不好代码」,而是「AI 不守规矩」

让我们先说清楚一件事:2026 年的 Claude Code、Codex、Cursor,在「写代码」这件事上已经很强了。它们能读懂你的需求,能生成合理的代码,能在多文件之间跳转修改。单次任务的成功率,在人类监督下已经超过 80%。

但「无人监督」的成功率呢?大约 60%。剩下 40% 的失败,不是因为 AI 不够聪明,而是因为 AI 不够自律。

打个比方:你招了一个能力很强的实习生,但他有以下习惯:

  • 你说「优化一下」,他没问你要优化什么,就自己选了个方向开始改
  • 你要他改一个小 bug,他把整个模块重构了
  • 你要他修一个函数,他顺手把旁边三个函数的命名也改了
  • 他改完代码就提交,从来不跑测试

你会怎么说?「这人能力不错,但不能没有 code review。」

对 AI 编程助手来说,CLAUDE.md 就是那个 code review。不是事后审查,而是事前约束——在 AI 开始写代码之前,先告诉它什么不能做。

1.2 四种典型翻车现场

Karpathy 的观察不是理论推导,是实战总结。下面是每种翻车模式的真实案例。

翻车一:默默做假设

你跟 AI 说:「给用户数据加个导出功能。」你心里想的是 CSV 导出。AI 默认你想要 JSON + CSV + Excel 三种格式,还带分页、带过滤、带进度条。等你看到结果,300 行代码已经写完了。

这不是 AI「理解错了」,是 AI「没确认就动手了」。人类程序员面对模糊需求,会先问一句:「导出什么格式?」AI 不会主动问,除非你告诉它要问。

翻车二:过度复杂化

一个最经典的场景:你让 AI 加一个简单的重试逻辑。它给你写了一个带指数退避、带 jitter、带 circuit breaker、带 metrics 收集、带配置文件、带环境变量的「生产级重试框架」。

150 行。而你只需要 5 行:

for i := 0; i < 3; i++ {
    resp, err := client.Do(req)
    if err == nil {
        return resp, nil
    }
    time.Sleep(time.Second * time.Duration(i+1))
}
return nil, fmt.Errorf("max retries exceeded: %w", err)

AI 不知道你只需要 5 行,除非你告诉它「简单优先」。

翻车三:乱改无关代码

这个最让程序员恼火。你让 AI 修一个 API handler 的返回值格式,它顺手把:

  • 旁边三个 handler 的注释风格统一了
  • import 语句按字母排序了
  • 一个 TODO 注释删了(它觉得「这看起来不需要」)
  • 两个变量名从 user_id 改成了 userId

diff 从 3 行变成了 47 行。代码审查的时候你根本看不出它到底改了什么。

翻车四:不验证结果

你报告一个 bug:「登录页面偶尔会 500。」AI 改了一段代码,告诉你「已修复」。你问它:

  • 你复现了这个 bug 吗?→ 没有
  • 你跑测试了吗?→ 没有
  • 你确认 500 不会再出现了吗?→ 「根据我的分析应该不会了」

这不是修复,这是猜测。人类程序员修复 bug 的标准流程:先复现,再定位,再修复,再验证。AI 跳过了前两步和最后一步,除非你告诉它要走完整流程。


第二部分:Karpathy 的 4 条规则——从观察提炼到结构化约束

2.1 规则一:Think Before Coding(先思考再写代码)

## Rule 1 — Think Before Coding

Before making changes:
- List your assumptions about the code and the task.
- If anything is ambiguous, ask instead of assume.
- If there are multiple ways to interpret the request, present them and ask which to pursue.
- When you propose a change, also propose the trade-off you're making.

这条规则的精髓不是「让 AI 思考」——AI 本来就在思考。精髓是让 AI 把思考过程暴露出来

正常模式下,AI 的思考链(chain of thought)是内部的,你看不到。你只看到最终输出的代码。这条规则要求 AI 在写代码之前,先输出一段文本,说明:

  • 我假设你要的是 X
  • 如果你要的是 Y,那我需要改方案
  • 我选择方案 A 而不是方案 B,因为……

这就像让实习生在动手前先写一个简短的设计文档。不是完整的设计评审,只是一个 30 秒的「我在做什么以及为什么」。

实战效果:加了这条规则后,AI 主动问问题的频率从大约 5% 提升到 40%。不是每个任务都需要确认,但那些模糊需求现在会被识别出来。

2.2 规则二:Simplicity First(简单优先)

## Rule 2 — Simplicity First

- Use the simplest solution that solves the problem correctly.
- Do not add speculative features, abstractions, or complexity.
- Do not create one-time abstractions for single-use code.
- If a senior engineer would say "this is over-engineered," simplify.

这条规则的价值在于,它给了 AI 一个判断标准:「如果资深工程师会说这过度设计了,就简化。」

AI 模型在训练数据里见过大量「生产级」「高可用」「可扩展」的代码范例。它们倾向于向这些范例靠拢——即使你的场景只需要一个简单脚本。这条规则告诉 AI:不要用生产级标准来衡量一个只需要跑一次的脚本。

一个实际的代码对比:

# 过度复杂版本(AI 默认倾向)
class DataExporter:
    def __init__(self, config: ExportConfig):
        self.config = config
        self.formatters = {
            'csv': CSVFormatter(),
            'json': JSONFormatter(),
            'excel': ExcelFormatter(),
        }
    
    def export(self, data: List[Record], format: str) -> Path:
        formatter = self.formatters.get(format)
        if formatter is None:
            raise UnsupportedFormatError(format)
        return formatter.format(data, self.config.output_path)

# 简单优先版本(规则约束后)
def export_csv(data, path):
    with open(path, 'w', newline='') as f:
        writer = csv.DictWriter(f, fieldnames=data[0].keys())
        writer.writeheader()
        writer.writerows(data)

如果你的需求就是「导出 CSV」,第二个版本更好。不是第一个版本写错了——它在更复杂的场景下是正确的设计。但当前场景不需要它

2.3 规则三:Surgical Changes(精准修改)

## Rule 3 — Surgical Changes

- Make the smallest change that fixes the problem.
- Do not reformat unrelated code, update comments, change variable names, or "improve" adjacent code.
- Do not refactor code that isn't directly related to the change.
- Match existing code style, even if you personally think it's "better."

这条规则的底层逻辑是:代码变更的副作用应该尽可能小。

在人类团队里,这是一个基本共识:PR 的 diff 应该只包含必要的修改,方便审查和回滚。AI 没有 PR review 流程,它改什么就直接提交了。所以你需要事前告诉它:只碰必须碰的地方。

实际效果非常明显。在一个内部测试中,加了这条规则后,平均每次修改的 diff 行数从 47 行降到了 8 行。不是 AI 写得更少了,而是 AI 不再「顺手」改东西了。

// 修改前:AI 顺手「优化」了注释风格和 import 顺序
// diff: 47 行,包含 3 个不相关文件的改动

// 修改后:只改了目标函数
// diff: 3 行
func GetUser(id int) (*User, error) {
-   return db.Find(&User{}, id)
+   return db.Where("id = ? AND deleted_at IS NULL", id).Find(&User{}, id)
}

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

## Rule 4 — Goal-Driven Execution

- Define success criteria before starting.
- Loop until the criteria are met:
  - Verify the fix worked (run tests, check behavior).
  - If not, adjust and try again.
- Do not tell the model the specific steps; tell it the goal and let it iterate.

这条规则的颠覆性在于:它改变了你给 AI 下指令的方式。

传统方式:你给 AI 一系列步骤——「1. 复现 bug,2. 定位原因,3. 修复,4. 跑测试」。问题是,如果步骤 2 的结果和预期不同,AI 不知道怎么调整。它只是机械执行步骤 3。

目标驱动方式:你告诉 AI 目标——「修复这个 bug,确保测试通过且 bug 不复现」。AI 自己规划步骤,遇到问题自己调整,直到目标达成。

# 传统指令式
"Step 1: Write a test that reproduces the bug.
 Step 2: Find the root cause.
 Step 3: Fix the code.
 Step 4: Run the test to verify."

# 目标驱动式
"Fix this bug. Success criteria:
 1. The test `test_login_500` passes.
 2. A new test that reproduces the original 500 error now returns 200.
 Iterate until both criteria are met."

实测数据:目标驱动方式的首次成功率比步骤式高出 22%。因为 AI 在遇到问题时会调整策略,而不是继续执行可能已经无效的步骤。


第三部分:4 条不够了——2026 年 5 月的新问题与 8 条补充规则

3.1 为什么 4 条规则会失效

Karpathy 的 4 条规则解决的是 2026 年 1 月的问题。那时候 AI 编程的主流用法是:一个程序员坐在电脑前,开一个 Claude Code session,跟 AI 对话式地写代码。

但 5 个月后的 AI 编程生态已经完全不同了:

  • Agent 模式成为主流:AI 不再是对话式助手,而是自主执行任务的 Agent
  • 多 Agent 协作出现:一个项目里可能有多个 AI Agent 同时工作
  • Hook 和 Skill 系统成熟:Claude Code 可以加载插件、触发钩子、调用外部工具
  • 跨 session 工作流普及:AI 任务不再在单次对话内完成,可能跨多个 session

这四个变化带来了新的失败模式,Karpathy 的 4 条规则没有覆盖。

3.2 规则五:只用 AI 做判断,不用 AI 做路由

## Rule 5 — Use the model only for judgment calls

Use Claude for: classification, drafting, summarization, extraction from unstructured text.
Do NOT use Claude for: routing, retries, status-code handling, deterministic transforms.
If a status code already answers the question, plain code answers the question.

真实翻车场景:一段代码调用 Claude 来「决定 503 时是否应该重试」。前两周运行完美。第三周开始抖动——因为模型开始把请求 body 当成决策上下文来读,重试策略变成了随机的。

问题本质:你用每 token 0.003 美元的模型来做一个 if-else 的工作。 这个 if-else 每周结果不同,因为模型每次推理的上下文都不同。

正确做法:

# ❌ 用 AI 做确定性决策
async def should_retry(response):
    prompt = f"Should I retry this request? Status: {response.status_code}, Body: {response.text}"
    answer = await claude.ask(prompt)
    return answer.strip().lower() == "yes"  # 结果不稳定!

# ✅ 用确定性代码做确定性决策
def should_retry(status_code):
    return status_code in (503, 502, 429)  # 结果永远稳定

AI 应该只做需要「判断力」的事:分类(这段文本是 bug report 还是 feature request?)、提炼(从 10 页文档里总结 3 个关键点)、生成(写一段描述性的文案)。不该做可以用 if-else 解决的事。

3.3 规则六:Token 预算是硬约束,不是建议

## Rule 6 — Token budgets are not advisory

Per-task budget: 4,000 tokens.
Per-session budget: 30,000 tokens.
If a task is approaching budget, summarize and start fresh. Do not push through.
Surfacing the breach > silently overrunning.

真实翻车场景:一次 debugging session 跑了 90 分钟。模型非常乐意围绕同一个 8KB 错误信息反复迭代,然后逐渐忘记自己已经试过哪些修复。到最后,它在建议 40 条消息之前已经被拒绝过的方案。token 预算本该在第 12 分钟就让它停下来。

问题本质:AI 模型不会自己说「我搞不定了,该停下来。」 它会永远尝试下去,因为每次尝试都有概率成功——但概率在不断下降,而上下文在不断膨胀。

Token 预算的作用不是省钱。它的作用是强制 AI 在低效区间停下来,重新开始

# 一个带 token 预算的工作流实现
class TokenBudgetGuard:
    def __init__(self, per_task=4000, per_session=30000):
        self.per_task = per_task
        self.per_session = per_session
        self.session_used = 0
        self.task_used = 0
    
    def check(self, estimated_tokens):
        if self.task_used + estimated_tokens > self.per_task:
            return "task_budget_exceeded"
        if self.session_used + estimated_tokens > self.per_session:
            return "session_budget_exceeded"
        return "ok"
    
    def on_task_complete(self, tokens_used):
        self.session_used += tokens_used
        self.task_used = 0  # 重置任务预算
    
    def on_task_reset(self):
        # 超预算时:总结当前状态,开始新任务
        self.task_used = 0
        # 不重置 session 预算——那是一个硬上限

实测数据:加了 token 预算后,debugging session 的平均时长从 45 分钟降到 18 分钟,成功率反而提高了 15%。原因很简单——在预算约束下,AI 更倾向于选择高效策略,而不是反复尝试低效方案。

3.4 规则七:暴露冲突,不要折中平均

## Rule 7 — Surface conflicts, don't average them

If two existing patterns in the codebase contradict, don't blend them.
Pick one (the more recent / more tested), explain why, and flag the other for cleanup.
"Average" code that satisfies both rules is the worst code.

真实翻车场景:一个代码库有两套错误处理模式:async/await + 显式 try/catch,和全局 error boundary。Claude 写了两者兼有的新代码——错误处理器翻倍。开发者花了 30 分钟才弄明白为什么错误被吞了两次。

问题本质:AI 面对矛盾的模式时,倾向于「两边都满足」。 但同时满足两个矛盾规则的代码,质量比只满足一个的代码更差。

// ❌ AI 的折中方案:同时用两种错误处理
try {
    const result = await fetchUserData(userId);
    return result;
} catch (error) {
    // 同时用了 try/catch 和全局 error boundary
    // 错误被处理了两次,第二次可能吞掉第一次的信息
    errorHandler.report(error);
    throw error;
}

// ✅ 正确做法:选一种,标记另一种需要清理
try {
    const result = await fetchUserData(userId);
    return result;
} catch (error) {
    // 采用 async/await + try/catch 模式(更近期、更测试覆盖)
    // TODO: migrate other handlers from global error boundary to this pattern
    logger.error("fetchUserData failed", { userId, error });
    throw new AppError("Failed to fetch user data", error);
}

3.5 规则八:先读再写

## Rule 8 — Read before you write

Before adding code in a file, read the file's exports, the immediate caller, and any obvious shared utilities.
If you don't understand why existing code is structured the way it is, ask before adding to it.
"Looks orthogonal to me" is the most dangerous phrase in this codebase.

真实翻车场景:Claude 在一个已有完全相同函数的旁边又加了一个新函数,因为它没读到那个旧函数。两个函数做同一件事。新函数因为 import 顺序获得了优先级。旧函数是 6 个月的事实来源。

这条规则是规则三「精准修改」的补充。规则三告诉 AI 不要碰无关代码,但没有告诉 AI 要先理解相关代码

# AI 没读文件就加的新函数
def get_user_name(user_id: int) -> str:
    user = db.query(User).filter(User.id == user_id).first()
    return user.name if user else "Unknown"

# 文件里已经存在的函数(6个月前写的)
def fetch_username(uid: int) -> str:
    """Fetch user display name. Returns 'Anonymous' for missing users."""
    record = UserRepo.get_by_id(uid)
    return record.display_name if record else "Anonymous"

两个函数做同一件事,但返回值不同("Unknown" vs "Anonymous")。调用方有的用新函数、有的用旧函数,行为不一致。

3.6 规则九:测试验证意图,不只是行为

## Rule 9 — Tests verify intent, not just behavior

Every test must encode WHY the behavior matters, not just WHAT it does.
A test like `expect(getUserName()).toBe('John')` is worthless if the function takes a hardcoded ID.
If you can't write a test that verifies intent, flag it for manual review.

真实翻车场景:Claude 写了一个测试 expect(getUserName()).toBe('John')。看起来测试通过了。但 getUserName() 里硬编码了 return "John"——测试永远通过,但函数完全没用。

这条规则是对规则四「目标驱动执行」的深化。规则四说「验证目标」,但没有说什么样的验证才是有效的。

# ❌ 只验证行为的测试——永远通过,但不验证功能
def test_get_user_name():
    assert get_user_name() == "John"  # 函数硬编码了 "John"

# ✅ 验证意图的测试——只有函数真正工作才通过
def test_get_user_name_from_database():
    # Setup: 在数据库里创建一个用户
    user = create_test_user(name="John Doe", id=42)
    
    # Execute: 用真实的 ID 查询
    result = get_user_name(user_id=42)
    
    # Verify: 返回值必须来自数据库,不是硬编码
    assert result == "John Doe"
    
    # Intent verification: 查一个不存在的人,应该有不同的行为
    assert get_user_name(user_id=999) != "John Doe"

3.7 规则十:Skill 加载是有序的,不是叠加的

## Rule 10 — Skills are ordered, not stacked

When loading multiple skills, define priority: which skill takes precedence when they overlap?
Do not load every available skill. Load only what the current task requires.
Loaded but unused skills consume context window and reduce adherence to active rules.

背景:2026 年 5 月的 Claude Code 生态里,Skill 系统已经成熟。一个项目可以加载多个 Skill——数据库操作、代码审查、安全扫描、文档生成……但多个 Skill 加载后,它们的规则可能互相冲突。

问题本质:每多加载一个 Skill,上下文窗口就被占掉一部分,活跃规则的遵循率就下降。 Anthropic 的数据显示,CLAUDE.md 超过 200 行后,遵循率明显下滑。如果你的项目加载了 5 个 Skill,每个 Skill 50 行规则,那就是 250 行——已经超过最佳区间了。

# ❌ 加载所有可用 Skill
skills:
  - database
  - security
  - code-review
  - documentation
  - testing
  - deployment
  - monitoring
  # 8 个 Skill = 400 行规则 = 遵循率降到 ~30%

# ✅ 只加载当前任务需要的 Skill
# 当前任务:修复一个数据库查询 bug
skills:
  - database       # 核心
  - testing        # 验证修复
  # 2 个 Skill = 100 行规则 = 遵循率 ~78%

3.8 规则十一:Hook 级联必须有权终止

## Rule 11 — Hook cascades must have a kill switch

A hook trigger should not cause another hook trigger without explicit permission.
If a hook chain exceeds 3 levels, abort and surface the chain for review.
Hooks are for side effects, not for decision-making.

真实翻车场景:一个项目配置了「文件保存时自动格式化 → 格式化后自动跑 lint → lint 失败时自动修复 → 修复后再次保存」的 hook 链。AI 改了一个文件 → 格式化 → lint 报错 → AI 修复 → 保存 → 再次格式化 → lint 又报错 → 无限循环。

Hook 系统是 2026 年 AI 编程工具的重要特性,但它引入了一种新的故障模式:级联触发。一个 hook 的输出触发另一个 hook,形成链式反应。如果链条没有终止条件,就会无限循环。

// Hook 配置示例——加了终止条件
const hooks = {
  onSave: {
    trigger: "file_save",
    actions: ["format", "lint"],
    maxCascades: 2,  // 最多级联 2 层
    abortOn: "lint_failure",  // lint 失败就停止,不自动修复
  },
  onLintFailure: {
    trigger: "lint_failure",
    actions: ["report_to_user"],  // 只报告,不自动修复
    maxCascades: 0,  // 不允许级联
  },
};

3.9 规则十二:跨 Session 状态必须显式传递

## Rule 12 — Cross-session state must be explicit

Between sessions, do not assume the model remembers prior decisions.
Summarize completed work and pending tasks in a state file at session end.
New sessions must read the state file before starting work.

真实翻车场景:一个需要 3 个 session 的任务:Session 1 完成了数据库 schema 设计,Session 2 应该基于 schema 写 API。但 Session 2 不知道 Session 1 的设计结果,从头重新设计了一套不同的 schema。

问题本质:AI 的记忆不跨 session。 每个 session 开始时,模型是全新的。除非你把上一个 session 的关键决策写到文件里,下一个 session 不会知道。

# state.md —— 每个 session 结束时写,下一个 session 开始时读

## Session 1 — 2026-06-18

### Completed
- Database schema designed: `users`, `orders`, `products` tables
- API endpoint structure: `/api/v1/users`, `/api/v1/orders`
- Auth middleware: JWT-based, implemented in `pkg/auth/jwt.go`

### Pending
- Implement CRUD handlers for orders
- Add rate limiting to public endpoints
- Write integration tests for auth flow

### Key Decisions
- Using UUID as primary key (not auto-increment)
- Soft delete pattern for all tables (`deleted_at` column)
- Max 10 items per page for list endpoints

第四部分:从 4 条到 12 条——实测数据说了什么

4.1 30 个代码库、6 周实测

Mnimiy(@Mnilax),一个专注于 AI 编程工作流的独立开发者,在 30 个代码库上花了 6 周测试这套规则。数据如下:

规则版本任务错误率规则遵循率
无规则~41%
Karpathy 4 条~15%~78%
扩展至 12 条~3%~76%

关键发现:

  1. 遵循率没有因为规则变多而大幅下降:4 条到 12 条,遵循率从 78% 到 76%。因为 12 条规则仍然是 65 行 Markdown(每条规则很短),没有超过 200 行的阈值。

  2. 错误率下降不是线性的:从 41% 到 15% 是 4 条规则的贡献;从 15% 到 3% 是 8 条新规则的贡献。新规则覆盖的是 Agent 时代的新问题,这些问题在单次对话模式下不会出现。

  3. 规则遵循率约 76-80%,不是 100%:Anthropic 的官方文档明确说,CLAUDE.md 是建议性的,大约 80% 的时间会被遵循。不要期待规则 100% 生效——那是系统级约束(比如权限控制)的工作,不是提示词的工作。

4.2 规则不是越多越好——每条规则必须对应一个失败模式

一个常见误区:「既然 12 条比 4 条好,那 50 条是不是更好?」

不是。Mnimiy 的核心方法论是:每条规则必须对应一个可观察的失败模式。 如果你不能举出一个「没有这条规则时会出错」的真实案例,这条规则就不该加。

原因:规则越多,上下文越长,遵循率越低。200 行以内遵循率约 78%,超过 200 行开始明显下滑。如果你加了 20 条「以防万一」的规则,每条都没有对应的失败案例,你在浪费上下文窗口,降低重要规则的遵循率。

# ❌ 无失败模式对应的规则(不要加)
- Always use TypeScript strict mode
- Never use var, always use const/let
- Always add JSDoc comments to all functions

# ✅ 有失败模式对应的规则(可以加)
- Do not assume the task is clear. Ask first. (失败模式:默默做假设)
- Do not add speculative features. (失败模式:过度复杂化)
- Token budget is hard. Stop when exceeded. (失败模式:无限迭代低效方案)

第五部分:生产级 CLAUDE.md 完整模板——可直接复制到你的项目

以下是经过实测验证的 12 条规则 CLAUDE.md,可以直接放进你的项目根目录。总行数约 80 行,在 200 行阈值之内。

# CLAUDE.md — AI 编程行为规范

## Rule 1 — Think Before Coding
Before making changes:
- List your assumptions about the code and the task.
- If anything is ambiguous, ask instead of assume.
- If there are multiple interpretations, present them and ask which to pursue.
- When proposing a change, state the trade-off you're making.

## Rule 2 — Simplicity First
- Use the simplest solution that solves the problem correctly.
- Do not add speculative features, abstractions, or complexity.
- Do not create one-time abstractions for single-use code.
- If a senior engineer would say "this is over-engineered," simplify.

## Rule 3 — Surgical Changes
- Make the smallest change that fixes the problem.
- Do not reformat, update comments, rename variables, or "improve" adjacent code.
- Do not refactor code unrelated to the change.
- Match existing code style, even if you think it's "better."

## Rule 4 — Goal-Driven Execution
- Define success criteria before starting.
- Loop until criteria are met: verify fix worked, adjust if not.
- Do not prescribe steps; tell the goal and let the model iterate.

## Rule 5 — Use the model only for judgment calls
- Use for: classification, drafting, summarization, extraction.
- Do NOT use for: routing, retries, status-code handling, deterministic transforms.
- If code already answers the question, use code.

## Rule 6 — Token budgets are not advisory
- Per-task: 4,000 tokens. Per-session: 30,000 tokens.
- Approaching budget → summarize and start fresh. Do not push through.
- Surfacing the breach > silently overrunning.

## Rule 7 — Surface conflicts, don't average them
- If patterns contradict, pick one (more recent / more tested).
- Explain why, flag the other for cleanup.
- "Average" code satisfying both is the worst code.

## Rule 8 — Read before you write
- Read file exports, immediate caller, shared utilities before adding code.
- If you don't understand existing structure, ask before modifying.
- "Looks orthogonal to me" is the most dangerous phrase.

## Rule 9 — Tests verify intent, not just behavior
- Every test must encode WHY the behavior matters.
- A hardcoded-value test is worthless.
- If you can't verify intent, flag for manual review.

## Rule 10 — Skills are ordered, not stacked
- Define priority when skills overlap.
- Load only skills the current task requires.
- Unused skills waste context and reduce adherence.

## Rule 11 — Hook cascades must have a kill switch
- A hook trigger must not cause another without explicit permission.
- Chain exceeding 3 levels → abort and surface for review.
- Hooks are for side effects, not decision-making.

## Rule 12 — Cross-session state must be explicit
- Do not assume the model remembers prior decisions.
- Summarize completed work + pending tasks in state file at session end.
- New sessions read the state file before starting.

5.1 怎么根据你的项目精简

上面是通用模板。实际使用时,你应该根据项目具体痛点精简。方法:

  1. 先跑一周无规则的 AI session,记录每种失败模式的频率
  2. 只加频率最高的 3-5 条规则
  3. 跑一周,看效果,再加频率次高的规则

比如,如果你的项目是个人博客,主要问题是 AI 过度复杂化——那你只需要规则 2 和 3。如果你的项目是企业级 SaaS,AI 的主要问题是不验证和不读代码——那你需要规则 4、8、9。


第六部分:跨工具适配——Claude Code、Codex、Cursor 三种入口

6.1 三种工具读取规则的方式不同

工具规则文件推荐位置作用域
Claude CodeCLAUDE.md项目根目录 / ~/.claude/CLAUDE.md项目级 / 用户级
CodexAGENTS.md项目根目录 / ~/.codex/AGENTS.md项目级 / 全局级
Cursor.cursor/rules/*.mdcAGENTS.md.cursor/rules/ / 项目根目录项目规则 / Agent 指令

核心内容是一样的——12 条行为准则。只是文件名和位置不同。

6.2 为什么需要三份文件

三个工具的规则加载机制不同:

  • Claude Code 在 session 开始时自动读取 CLAUDE.md(项目级 + 用户级合并)
  • Codex 在任务开始前读取 AGENTS.md(全局 → 项目 → 当前目录)
  • Cursor 在 Agent 模式下读取 .cursor/rules/*.mdc(Project Rules),同时新版也支持 AGENTS.md

你可以维护一份核心规则,然后:

# 从一份核心规则生成三个工具的配置
cp core_rules.md CLAUDE.md
cp core_rules.md AGENTS.md
# Cursor 的 .mdc 格式需要加一点元数据头部
echo "---\ndescription: Karpathy-style AI coding guidelines\nglobs: **/*\n---" > .cursor/rules/karpathy-guidelines.mdc
cat core_rules.md >> .cursor/rules/karpathy-guidelines.mdc

第七部分:性能优化——如何让规则遵循率最大化

7.1 上下文窗口是稀缺资源

Claude Code 的上下文窗口约 200K token。其中:

  • 系统提示占约 5K
  • CLAUDE.md 占约 2-3K(80 行规则)
  • 对话历史动态增长
  • 代码文件内容动态增长

规则遵循率和上下文利用率的关系:

  • 规则占上下文 < 2% → 遵循率约 78%
  • 规则占上下文 > 5%(>200 行)→ 遵循率开始下滑到 ~50%
  • 规则占上下文 > 10% → 遵循率降到 ~30%

所以:规则越短越好。 每条规则一句话就够了,不需要写三段解释。

7.2 规则的位置有讲究

Anthropic 的数据显示,CLAUDE.md 中靠前的规则遵循率高于靠后的规则。原因:模型的注意力分配在序列开头更集中。

所以:把最重要的规则放在前面。 如果你只保留 5 条规则,把它们排在 1-5 位,不要排在 8-12 位。

7.3 项目级规则 > 用户级规则

CLAUDE.md 有两个位置:项目级(./CLAUDE.md)和用户级(~/.claude/CLAUDE.md)。两者会被合并读取。

最佳实践:

  • 用户级 CLAUDE.md:放通用偏好(语言偏好、代码风格偏好)
  • 项目级 CLAUDE.md:放项目特定规则(架构约束、禁止修改的模块、部署流程)
# ~/.claude/CLAUDE.md(用户级——跨项目通用)
- Prefer Go for backend, TypeScript for frontend.
- Use conventional commits format.
- Always add error handling, never ignore errors.

# ./CLAUDE.md(项目级——特定项目规则)
- This project uses PostgreSQL. Do not suggest MongoDB alternatives.
- The auth module (pkg/auth/) is frozen. Do not modify it.
- All API changes must maintain backward compatibility.

第八部分:总结与展望——AI 编程纪律的未来

8.1 从「提示词工程」到「纪律工程」

Karpathy Skills 项目的爆发,标志着 AI 编程领域的一个重要转向:从「怎么让 AI 写更多代码」转向「怎么让 AI 写更可靠的代码」。

这个转向的本质是:我们不再只优化 AI 的能力,开始优化 AI 的行为。

能力优化是模型训练的事——更大的模型、更好的数据、更聪明的架构。行为优化是开发者的事——规则文件、工作流设计、约束机制。

两者缺一不可。最强的模型配上最差的行为约束,结果比中等模型配上良好的行为约束更不可靠。

8.2 规则会进化,但底层逻辑不会变

从 4 条到 12 条,规则的内容变了。但底层逻辑一直是同一个:

每条规则必须对应一个可观察的失败模式。

这个逻辑不会因为模型变强而失效。即使 2027 年的模型「默认」就会先思考再写代码,你仍然需要规则来约束那些新的失败模式。失败模式会随 AI 能力的进化而变化,但「失败模式一定存在」这件事不会变。

8.3 下一步:从规则文件到系统级约束

CLAUDE.md 是提示词级约束——建议性的,遵循率约 80%。对很多场景来说够用了。

但生产级系统需要更强的约束:

  • 权限控制:AI 不能修改某些文件(系统级,100% 有效)
  • 审批流程:AI 的修改必须经过人类确认才能提交(流程级,100% 有效)
  • 测试门禁:AI 的修改必须通过所有测试才能合并(CI/CD 级,100% 有效)

这三层约束加上 CLAUDE.md 的行为约束,形成一个完整的 AI 编程安全网:

  1. 事前约束:CLAUDE.md 规则(80% 遵循率)
  2. 事中约束:权限控制(100% 有效)
  3. 事后约束:审批 + 测试门禁(100% 有效)

Karpathy 的 65 行 Markdown 解决了第一层。第二层和第三层,需要你在项目基础设施里实现。


附录:快速参考

A. 按失败模式索引规则

失败模式对应规则一句话总结
默默做假设Rule 1先说假设,再写代码
过度复杂化Rule 2能简单就不要复杂
乱改无关代码Rule 3只碰必须碰的
不验证结果Rule 4定义目标,循环验证
AI 做确定性决策Rule 5判断用 AI,路由用代码
无限迭代低效方案Rule 6Token 预算是硬约束
折中两种矛盾模式Rule 7选一种,不要平均
不读就写Rule 8先理解再动手
测试只验证行为Rule 9测试要验证意图
Skill 加载过多Rule 10只加载需要的
Hook 级联无限循环Rule 11级联必须有权终止
跨 Session 遗忘Rule 12状态必须显式传递

B. 最小可用版本(3 条规则)

如果你的项目刚开始用 AI 编程,不确定需要哪些规则,先用这 3 条:

# CLAUDE.md — Minimal Version

- Think before coding. If anything is ambiguous, ask.
- Make the smallest change that fixes the problem. Do not touch unrelated code.
- Define success criteria. Verify the fix worked. Iterate if not.

这 3 条覆盖了最常见的 ~25% 失败模式。一周后,根据实际翻车情况再加。


项目链接multica-ai/andrej-karpathy-skills

12 条规则来源:Mnimiy (@Mnilax) 的实测扩展,基于 30 个代码库 6 周数据

Anthropic 官方文档Claude Code Memory

Codex 官方文档Codex AGENTS.md

复制全文 生成海报 AI编程 Karpathy CLAUDE.md Codex Cursor

推荐文章

跟着 IP 地址,我能找到你家不?
2024-11-18 12:12:54 +0800 CST
关于 `nohup` 和 `&` 的使用说明
2024-11-19 08:49:44 +0800 CST
Vue3中如何实现状态管理?
2024-11-19 09:40:30 +0800 CST
Vue3中的v-slot指令有什么改变?
2024-11-18 07:32:50 +0800 CST
Golang Sync.Once 使用与原理
2024-11-17 03:53:42 +0800 CST
MyLib5,一个Python中非常有用的库
2024-11-18 12:50:13 +0800 CST
HTML和CSS创建的弹性菜单
2024-11-19 10:09:04 +0800 CST
程序员茄子在线接单