第 19 章 | CLAUDE.md——项目宪法
💡 进群学习加 wx: agentupdate
(申请发送: 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 文件的内容边界
下一章把"基于文件的状态机"讲透——这是整个系统可靠性的来源。