CLAUDE.md 单文件膨胀到数百行时,指令遵循率会出现肉眼可见的下滑。要把”文件大”压回”指令稳”,生态里被反复验证的两种主流做法是:把规则拆到 .claude/rules/ 并用 paths 字段做路径限定,以及把多步骤流程从 CLAUDE.md 抽离到 Skills 实现按需加载。两条路径并不互斥,区别在于”什么时候把规则拉进上下文窗口”,理解清楚再选才能既省 token 又不丢指令。
一、为什么 CLAUDE.md 一旦变长就开始”失灵”
CLAUDE.md 是会话启动时被完整读入上下文窗口的”前置指令”,并不是被强制执行的配置。文件越长,挤占给对话本身的 token 越多;规则越多越密,模型在”读完整段”之后越容易”挑着遵循”,相互冲突的旧规则甚至会与新规则打架。官方建议每份 CLAUDE.md 控制在 200 行以内,超过这个量级,遵循率会出现可感知的下降,常见表现是:原本要求用 2 空格缩进的位置出现 4 空格,明确要求跑测试再提交的操作被跳过。
更隐蔽的代价是”被读多次”。CLAUDE.md 在每次会话启动时都会重新读入,导入的 @path 文件同样会被展开,多个文件轮替加载,膨胀得越快,月度累计 token 账单越夸张。所以”把文件压短”从来不是审美问题,是直接的成本与质量工程。
二、两种策略速览
| 策略 | 落地位置 | 加载时机 | 主要收益 | 主要代价 |
|---|---|---|---|---|
| 路径限定规则 | .claude/rules/<topic>.md 带 paths 字段 |
仅当 Claude 读写匹配文件时才加载 | 命中文件场景下不浪费 token,未命中时完全无感 | 需要先想清楚每条规则”针对哪些文件生效” |
| Skills 化流程 | .claude/skills/<name>/SKILL.md |
用户调用 /<name> 时按需加载 |
一次性长流程不进上下文,零成本待命 | 多步骤流程要被显式触发,自动化程度降低 |
简单记:路径限定规则解决”只对某类文件生效的规则”,Skills 化流程解决”只在某个阶段才用得上的长流程”。
三、策略一:.claude/rules/ + paths 字段做路径限定
.claude/rules/ 是一组按主题拆分的 Markdown 文件,每个文件用 YAML frontmatter 声明 paths 字段,只有当 Claude 读写的文件路径命中该 glob 时,对应规则才被加载到上下文里。这是相对更”省 token”的做法,因为未命中的文件根本不进入上下文。
落地通常分四步:
- 在仓库根目录新建
.claude/rules/目录,按主题分文件,例如testing.md、api.md、database.md; - 给每份规则文件加上 frontmatter,
paths字段用 glob 描述”哪些文件读/写时加载”; - 把原 CLAUDE.md 中”只针对某类文件”的段落整段搬过去,正文继续用 Markdown 写具体规则;
- 用
/memory复查当前会话实际加载了哪些规则文件,确认路径匹配与预期一致。
下面是一段典型的测试规则文件示例,写的是”只要改测试就加载”:
---
paths:
- "tests/**/*.py"
- "**/*_test.py"
---
# 测试规范
- 用 pytest fixture 而不是 setUp / tearDown;
- 外部依赖用 `responses` 库做 mock,不要打真实网络;
- 测试函数命名以 `test_` 开头并描述场景,例:`test_login_with_expired_token_returns_401`;
- 一次断言只覆盖一个行为,定位失败时不要靠注释。
把这段放进 .claude/rules/testing.md 后,Claude 在写业务代码时完全不会读到它;改测试文件时它才会被自动拉进上下文。同一份 CLAUDE.md 因此可以同时挂多份”按需加载”的规则文件,零侵入、不打架。
四、策略二:把多步骤流程搬到 Skills
当一段内容是”部署清单 / 数据库迁移 / 发布流程”这种需要被调用才执行的多步骤流程时,它根本不该住在 CLAUDE.md 里。Skills 是一类按需加载的内容:用户显式调用(/db-migrate、/release)或者 Claude 主动识别出应当触发时,完整流程才进入上下文;不被调用时就是零成本。
迁移路径很简单,按四步走:
- 在
.claude/skills/<name>/下新建SKILL.md; - 把原 CLAUDE.md 中的多步骤流程整段搬进
SKILL.md,保留步骤、模板、校验点; - 在原 CLAUDE.md 中删掉对应段落,只留一行提示(”数据库迁移流程见 /db-migrate 技能”);
- 必要时在 frontmatter 里用
description字段告诉 Claude 何时主动调用。
迁移前后的对比能直接看出收益:
## 数据库迁移流程
1. 生成迁移文件并写 SQL;
2. 找同事 review 变更;
3. 在 staging 跑一遍并校验;
4. 维护窗口内执行生产;
5. 跑完回滚预案确认可还原。
这段留在 CLAUDE.md 里意味着每次会话启动都要付出 5 行的固定成本,但 99% 的会话根本不会触发它。搬到 Skills 后,这 5 行只在需要时被显式拉入。
五、两种策略怎么选:决策表
| 你的规则类型 | 推荐策略 | 理由 |
|---|---|---|
| 测试规范、API 命名约定 | .claude/rules/ + paths |
自动按文件类型触发,免去人工调用 |
| 部署、迁移、发布流程 | Skills | 调用频率低、步骤长,按需加载省 token |
| 团队代码风格、个人快捷键 | 根 CLAUDE.md | 始终生效,不必做路径限定 |
| 大段参考文档(API 表、Schema) | @path 导入 |
仍然每次启动加载,但组织上更清晰 |
| 个人偏好、不进版本库 | CLAUDE.local.md + .gitignore |
团队不污染,个人设置保留 |
三条决策线索:第一看”是不是只对某类文件生效”,是则优先规则目录;第二看”是不是多步骤流程”,是则优先 Skills;第三看”是不是始终要生效”,是则留在根 CLAUDE.md。
六、落地时的三个易错点
第一,规则文件不要”无脑抄 CLAUDE.md”。直接把整段长规则搬进 .claude/rules/ 而不写 paths,效果等同于换了个位置的全量加载,没有任何收益。第二,@path 导入不会省 token。导入文件在每次启动时仍会被展开,作用是组织而不是省 token;如果目标是省 token,必须走规则目录或 Skills。第三,规则之间不要矛盾。两条规则对同一类文件给出相反要求时,模型会”自己挑一条”,最终谁生效不可预测。定期跑 /memory 复查加载列表,把过时的、冲突的、重复的清理掉。
常见问题(FAQ)
Q1:路径限定规则和 Skills 可以同时用吗?
可以,二者不冲突:路径限定规则管”改特定文件时自动生效”,Skills 管”用户显式调用才生效”。
Q2:怎么确认规则真的按预期被加载?
在会话内运行 /memory 或 /context,会列出当前实际加载的 CLAUDE.md、.claude/rules/ 文件及其命中路径。
Q3:@path 导入是不是也能省 token?
不能。导入文件在每次会话启动时仍会被展开进上下文,它的价值在组织而不是省 token。