第 19 章 | CLAUDE.md——项目宪法

更新于 2026/5/11
💡 进群学习加 wx: agentupdate
(申请发送: agentupdate)

第 19 章:CLAUDE.md——项目宪法

学习目标

写一份让任何 main Claude 进入项目都能立刻按规则办事的 CLAUDE.md。

CLAUDE.md 是什么

每个项目根目录可以放一份 CLAUDE.md。Claude Code 启动时自动读它,等于给 main Claude 加上"项目专属说明书"。

flowchart LR
    Start["claude 启动"] --> Read["自动读取
CLAUDE.md"] Read --> Context["进入会话
(已知道项目规则)"] Context --> Work["按规则办事"] style Read fill:#fff9c4 style Work fill:#c8e6c9

完整启动加载顺序

sequenceDiagram
    participant CC as Claude Code
    participant FS as 文件系统
    participant MC as main Claude

    Note over CC: 用户敲 claude
    CC->>FS: 读 ~/.claude/settings.json (用户级)
    CC->>FS: 读 .claude/settings.json (项目级)
    CC->>FS: 读 .claude/settings.local.json (本地)
    Note over CC: settings 合并完成
    CC->>FS: 读 CLAUDE.md
    CC->>FS: 索引 .claude/agents/*.md
    CC->>FS: 索引 .claude/commands/*.md
    CC->>FS: 注册 hooks (settings.json 里指定的)
    CC->>MC: 启动 main Claude
注入合并规则 + CLAUDE.md Note over MC: 我现在知道
- 我是 dispatcher
- 7 个 agent 可调度
- /dev 命令存在
- bypassPermissions 模式

改 CLAUDE.md 必须重启会话才会重新加载(这就是 Q11 的答案的来源)。

CLAUDE.md 的必备章节

flowchart TB
    CLAUDE["CLAUDE.md"] --> S1["1. 项目概况
(一句话 + 技术栈)"] CLAUDE --> S2["2. 唯一真相
(specs / changes 在哪)"] CLAUDE --> S3["3. 角色调度
(谁是 dispatcher,谁干啥)"] CLAUDE --> S4["4. 状态机
(怎么读状态,怎么转移)"] CLAUDE --> S5["5. dispatch 协议
(每次 dispatch 的 briefing 模板)"] CLAUDE --> S6["6. 不做的事
(硬约束)"] CLAUDE --> S7["7. 命令速查"] style CLAUDE fill:#fff9c4

核心戒律:dispatcher,不是 doer

CLAUDE.md 必须写死这句话:

你(main Claude)是 dispatcher,不是 doer。
你的工作是调度 4 个 subagent,不亲自改 src/、tests/、openspec/specs/。

→ 没这一句,main Claude 会顺手自己写代码——多 agent 设计形同虚设

实例:我们的 CLAUDE.md(简化版)

# doc2video — Project Rules

把 markdown 教学文档编译为带配音、字幕、真实终端操作的视频。
主语言 Python 3.11+,平台 macOS(MVP)。

## 唯一真相

| 信息 | 文件 |
|---|---|
| 系统当前承诺 | openspec/specs/ |
| 进行中变更 | openspec/changes/<active>/ |
| 当前任务 | openspec/changes/<active>/tasks.md |

## 角色调度(你是 dispatcher,不是 doer)

| Agent | 职责 | 可写 |
|---|---|---|
| developer | 实现 tasks | src/、tasks.md(仅勾选)|
| tester | 写单元测试 | tests/、test-reports/ |
| ... |

禁止:你自己 Edit src/ 或 tests/。

## 任务粒度:按"组"走

dispatch 单位是 ## N. 标题划分的组,不是单条 task。

## 状态机

PENDING → DEVELOPING → TESTING → REVIEWING → GROUP_DONE
            ↑          ↓ FAIL    ↓ REJECT
            └──────────┴─────────┘

## 状态读取(每轮重读文件,不维护内存状态)

| 想知道 | 读什么 |
|---|---|
| 组 N 是否 DEV 完成 | tasks.md ## N. 下所有 - [ ] 都变 - [x] |
| 组 N 测试通过 | test-reports/N.md 含 **Status:** PASS |
| ...

## 一组的 dispatch 协议

[每个阶段 dispatch 时附带的 briefing 模板...]

## 不做的事

- 不直接 Edit src/、tests/、openspec/specs/
- 不让 developer 写测试
- ...

为什么状态读取要写得这么细

没写状态读取规则:
  main Claude 不知道"如何判断组 N 完成"
  → 可能凭直觉乱判
  → 一会儿说完成,一会儿说没完成
  
写死状态读取规则:
  "看 tasks.md 的勾选 + review/N.md 的 Status 字段"
  → 不依赖直觉
  → 文件状态变 → main Claude 立刻知道

基于文件的状态机是这套系统的可靠性基础(Ch 20 详讲)。

CLAUDE.md 的写法约定

约定 为什么
用表格而不是段落 main Claude 解析表格更准
用列表而不是散文 更容易扫到关键点
把"不做的事"单独成节 反模式必须显眼
在 dispatch 协议里给 briefing 模板 让 main Claude 知道"具体说什么"

反模式

❌ CLAUDE.md 写成 README              ("项目用 Python 写,跑 pytest 跑测试")
   → README 是给开发者读的;CLAUDE.md 是给 main Claude 读的,关注调度规则

❌ 没有"你是 dispatcher" 的硬约束
   → main Claude 会自己写代码

❌ 状态读取用模糊词 ("看一下进度")
   → 没法机械执行

❌ 把所有 agent 的 system prompt 复制进来
   → 重复+维护噩梦,agent 文件已经独立

❌ 太长 (>500 行)
   → 占用主对话上下文,每次会话开销大

CLAUDE.md vs agent 文件的边界

CLAUDE.md 写:    跨 agent 的协议(谁先谁后、状态机、读哪些文件)
agent 文件写:    单个 agent 的具体行为(输入、工作流、输出格式)

❌ 把 agent 内部行为写进 CLAUDE.md
❌ 把状态机重复写进每个 agent 文件

你现在能做什么

  • 写出 7 段式的 CLAUDE.md
  • 解释为什么必须有"dispatcher 戒律"
  • 区分 CLAUDE.md 与 agent 文件的内容边界

下一章把"基于文件的状态机"讲透——这是整个系统可靠性的来源。