前两篇讲 Claude Code 记忆体系时,.claude/rules/只是记忆系统这张大地图里的一个小角落——一段话、一张表就带过了。但它其实是一套值得单独拆解的机制:当项目规则从几十行长成几百行,当前端规则和后端规则开始互相打架,当你希望某条规则只在Claude 碰后端代码时才出现——解决这些问题的,正是它。本文只讲一件事:.claude/rules/到底怎么工作、为什么这么设计,以及怎么把它用对。一、起点:CLAUDE.md 是一个文件,不是一套系统CLAUDE.md 的加载逻辑很朴素:向上遍历目录树,把沿途所有 CLAUDE.md 全文拼接进上下文。这个模型有一个隐含假设——你的所有项目规则,不管相不相关,都值得每次会话全量加载。小项目里这个假设成立。但项目一大就会浮现两个具体矛盾:膨胀矛盾:前端规范、后端规范、测试规范、安全规范全部塞进一个文件,官方建议的 200 行上限很快被击穿,而眼下用得上的 API 规则和根本用不上的 React 规则占着同样的上下文权重。无关性矛盾:你正在改一个 Python 脚本,却要让 Claude 每次都读一遍与之无关的 TypeScript 组件规范——这些 token 白白消耗,还可能引入指令噪音,增加规则之间互相矛盾的概率。.claude/rules/的价值主张正是针对这两点:先拆分,再按需。拆分解决膨胀(一个主题一个文件,而不是一整块文本);按需解决无关性(通过路径匹配,只有 Claude 真正接触到相关文件时,规则才进入上下文)。这两个能力是独立的——拆分本身不减少 token,真正省 token 的能力来自第三节的路径作用域。二、基础形态:目录即规则库把 Markdown 文件放进项目的.claude/rules/目录,每个文件对应一个主题:your-project/ ├── .claude/ │ ├── CLAUDE.md # 主项目说明 │ └── rules/ │ ├── code-style.md # 代码风格 │ ├── testing.md # 测试约定 │ └── security.md # 安全要求几个基础特性:递归发现:目录下所有.md文件都会被找到,包括嵌套子目录,所以可以按团队结构组织成rules/frontend/react.md、rules/backend/api.md这样的层级。一文件一主题:文件名要能望文生义,因为排查加载情况时,文件名往往是唯一线索。不带paths字段的规则文件等同无条件加载,加载优先级与.claude/CLAUDE.md完全相同。也就是说,把一份 CLAUDE.md 拆成十个 rules 文件,只要都不写paths,对上下文的实际消耗和拆分前一模一样——收益纯粹是组织结构上的可维护性,不是省 token。三、核心设计:路径作用域规则这是.claude/rules/存在的真正理由。在文件头部加一段 YAML frontmatter,声明paths字段:--- paths: - src/api/**/*.ts --- # API 开发规范 - 所有接口必须做输入校验 - 使用标准错误响应格式 - 补充 OpenAPI 文档注释paths字段是一个字符串数组,支持标准 glob 模式,也支持花括号扩展一次匹配多个后缀:模式匹配范围**/*.ts任意目录下的所有 TypeScript 文件src/**/*src/目录下的所有文件*.md项目根目录下的 Markdown 文件src/components/*.tsx特定目录下的 React 组件src/**/*.{ts,tsx}同时匹配.ts和.tsx触发机制:客户端确定性匹配,而不是模型的语义判断理解这条规则的关键在于弄清楚谁在做加载判断、依据什么做判断。路径作用域规则不是在每次工具调用时触发,而是在 Claude 实际读取、编辑到匹配路径的文件时触发——这个匹配是 Claude Code客户端做的确定性 glob 比对:某次文件操作命中了模式,规则内容就被注入上下文;命中不了,这份规则就完全不占用 token,也不会进入模型的视野。整个过程模型不参与决策,它甚至意识不到要不要加载这条规则这件事存在。这一点和 Skills 的加载机制形成了鲜明对比:Skills 的相关性判断是交给模型自己完成的——模型根据当前任务和技能描述,自主判断某个技能是否值得调用。而路径作用域规则从设计上刻意避开了这种语义判断,换成了纯粹的、可复现的文件系统事实匹配。设计取舍:为什么绑的是文件路径,不是用户输入的语义这是一个值得深究的设计决策,背后是两种触发信号可靠性上的根本差异。路径匹配是确定性的:一个文件要么命中 glob,要么不命中,可测试、可复现、没有歧义。绑定用户输入语义则要靠模型去判断这句话是不是在说 API 相关的事,天然是概率性的,既可能漏判也可能误判。更现实的问题是用户的措辞和代码的实际归属经常脱节:用户可能只是说把登录报错修一下,完全没提API或TypeScript,但改动最终落在某个 API 目录下的文件里——如果触发条件绑的是用户提到了相关字眼,这种情况会被直接漏掉;反过来,用户嘴上提到了某个技术词,但实际操作的是完全无关的文件,绑语义又可能被误触发。绑路径问的始终是一个客观事实,两种情况都不会出错。这也顺带划清了 rules 和 Skills 的分工边界:Skills 本就承担着判断任务语义相关性的职责,rules 没必要重复做同一件事。把 rules 锚定在文件系统事实上,和 Skills 的任务语义相关性恰好构成了两条互不重叠的触发轴。再往底层看,glob 匹配是纯客户端的字符串比对,零推理开销、零额外 token 成本;如果换成语义判断,则意味着每一轮都要让模型多做一次相关性推理,既不确定又更贵。frontmatter 是这套机制里最脆弱的一环路径作用域规则的失败模式很特殊:它不报错,只是静默地不生效。规则文件安安静静地待在目录里,你以为它在工作,实际上从未进入过上下文——原因可能是 glob 模式写错了、frontmatter 格式不被当前版本正确解析,或者规则所在的作用域层本身就不支持条件加载。这种失败比报错更危险,因为它不会在任何地方留下痕迹提醒你。因此,写完一条路径作用域规则后,不要假设格式写对了就万事大吉。稳妥的做法是:主动打开一个匹配路径下的文件,触发一次规则应该生效的场景,再去确认它是否真的进入了当次上下文。把验证生效当成写规则流程里不可省略的最后一步,比记住任何具体的版本号或语法细节都更可靠。四、作用域与优先级:用户级与项目级如何叠加.claude/rules/不止能放在项目内部,也支持用户级:层级位置作用范围加载顺序用户级~/.claude/rules/你本机上的所有项目先加载项目级项目根/.claude/rules/随仓库共享给团队后加载用户级规则先于项目规则加载背后的逻辑,和 CLAUDE.md 的分层哲学是一致的:离当前工作场景更具体的内容排在后面,在模型注意力上通常权重略高,所以项目规则实际上拥有比你个人全局偏好更高的话语权。适合放进用户级目录的是那些与具体项目无关、只关乎个人习惯的内容,比如你偏好的代码风格、你惯用的工作流程。需要提醒的是:这只是一种软性倾向,官方从未承诺过严格的后者覆盖前者语义——所有指令都会被同时看到并综合权衡。规则之间如果真的互相矛盾,Claude 依然可能任选其一,不能指望加载顺序替你消除冲突。五、跨项目复用:用符号链接共享一套规则如果你在多个项目上维护统一的团队标准(比如统一的安全审查清单),没必要在每个仓库里都复制一份。.claude/rules/目录原生支持符号链接,链接会被正常解析和加载,循环链接也会被检测并妥善处理:# 链接一整个共享目录ln-s~/shared-claude-rules .claude/rules/shared# 也可以只链接单个文件ln-s~/company-standards/security.md .claude/rules/security.md这个能力和 CLAUDE.md 里的import语法定位不同:import是把外部文件内容钉进当前文件的引用语法;符号链接则是在文件系统层面让多个项目物理共享同一份文件——改一处,所有链接到它的项目同步更新,不需要每个项目单独维护导入语句。在 Windows 上创建符号链接需要管理员权限或开启开发者模式,这是维护跨项目共享方案时需要提前考虑的限制。六、Monorepo 治理:claudeMdExcludes 该配置在哪在单一仓库容纳多个团队代码的场景下,向上遍历目录树会把其他团队的CLAUDE.md 和 rules 一并收进上下文——它们可能与你正在做的事完全无关,纯粹浪费 token 甚至引入冲突指令。claudeMdExcludes设置项可以按 glob 精确排除这些文件:{claudeMdExcludes:[**/monorepo/CLAUDE.md,/path/to/monorepo/other-team/.claude/rules/**]}这个设置写在settings.json/settings.local.json里,支持四个层级,各自的适用场景不同:层级影响范围适合的场景用户级设置只影响你本人,所有项目你个人在所有仓库里都想排除某类无关文件项目级设置(随仓库共享)进版本控制,全队共享团队达成一致,长期排除某些路径,需要经过 review项目本地设置(不进版本控制)只影响你在这一个项目里临时或个人化的排除,不希望影响其他成员托管策略(组织级)全公司所有机器,个人无法覆盖IT / 管理员要统一排除某类路径几个实操细节:匹配是针对绝对路径的 glob 匹配,写排除规则时要确认路径写全了。各层的排除数组是合并去重关系,不是覆盖关系——多层同时配置会叠加,不会互相打架。唯一的例外是:托管策略自己的 CLAUDE.md 永远不能被任何层的claudeMdExcludes排除,这是刻意设计,确保组织级底线规则任何人都绕不过去。选层的经验法则很简单:只影响自己且是临时性的,放本地设置;团队达成共识要长期生效,放项目级共享设置并走 review;需要全公司统一执行,交给托管策略层。七、边界:rules 不是万能容器.claude/rules/解决的是指令模块化 按路径懒加载这一个具体问题,不该用它承担别的职责。放在一起对比,更容易看清每种机制该管什么:机制加载时机谁来触发适合放什么CLAUDE.md会话启动时全量加载客户端,无条件全项目通用的规范、架构决策.claude/rules/(无paths)会话启动时全量加载客户端,无条件效果等同 CLAUDE.md,仅用于拆分组织.claude/rules/(带paths)Claude 读取匹配路径文件时客户端,按路径确定性触发只对特定目录/文件类型生效的规范Skills被调用或判断相关时模型自主判断相关性,或用户显式调用多步骤操作流程Hooks固定生命周期事件客户端强制执行,不依赖模型判断必须每次都执行的硬性动作这张表里最容易被混淆的一点是:rules(哪怕是路径作用域的)本质上仍然是影响 Claude 的行为倾向,而不是阻止 Claude 做某事的硬约束。如果你的需求是绝对不能让 Claude 碰某类敏感文件,不该写成一条规则寄希望于模型自觉遵守,而应该用权限拒绝规则或生命周期钩子做客户端强制拦截——规则文件管不住这种红线,它能做的只是提高模型遵循某种约定的概率。八、调试:如何确认规则真的生效了排查.claude/rules/相关问题时,按下面顺序检查,能覆盖绝大多数情况:先确认文件被发现和加载:列出当次会话已加载的全部记忆与规则文件。如果目标文件没出现在列表里,说明它压根没被发现或没被触发加载,不必急着怀疑规则内容本身写得对不对。确认触发条件真的满足:如果是路径作用域规则,先检查是否真的让 Claude 接触过匹配路径的文件——它不是无条件加载的,不触碰匹配文件就永远不会出现。怀疑 frontmatter 格式问题时,做最小化验证:去掉复杂的 glob 组合,先用一个最简单的模式单独测试是否生效,再逐步加回复杂度,定位到底是哪一部分格式导致了静默失败。用生命周期日志辅助排查:如果客户端提供了指令加载相关的钩子或日志,善用它记录哪些指令文件在何时、因为什么原因被加载,这比反复靠猜测验证更可靠。排查规则之间的冲突:多个规则文件之间,或规则与 CLAUDE.md 之间如果给出矛盾的指令,模型可能任选其一——这不是加载失败,而是权重博弈的结果,需要靠人工审查消除冲突,而不是指望加载顺序替你决定一切。结语.claude/rules/本质上是给 CLAUDE.md 补上了两个它天生缺乏的能力:模块化组织(一个主题一个文件,而不是一整块文本)和条件加载(路径匹配触发,而不是无条件常驻)。理解它的关键在于分清两种形态——不带paths的规则就是拆分过的 CLAUDE.md,图的是可维护性;带paths的规则才是真正的增量能力,图的是上下文效率。而路径作用域规则的设计本身也传递出一个更普遍的原则:能用确定性的客观信号解决的触发判断,就不要交给概率性的语义判断去做。文件路径是稳定、可验证、零成本的信号;用户意图是模糊、需要推理、有成本的信号。Claude Code 把这两类判断分别交给了 rules(路径匹配)和 Skills(语义相关性),各司其职,而不是让一种机制包办所有触发场景。用好.claude/rules/,记住三条:小项目不必用,先用一份 CLAUDE.md;规则膨胀或出现明显的路径相关性时再拆分;拆分后凡是只对某类文件生效的部分,一定补上paths,否则拆分本身不省一分 token。写完之后,养成主动验证生效与否的习惯,比记住任何具体的语法细节都更可靠。
claude_rules 深度解析:Claude Code 的模块化路径作用域规则
发布时间:2026/7/18 16:01:02
前两篇讲 Claude Code 记忆体系时,.claude/rules/只是记忆系统这张大地图里的一个小角落——一段话、一张表就带过了。但它其实是一套值得单独拆解的机制:当项目规则从几十行长成几百行,当前端规则和后端规则开始互相打架,当你希望某条规则只在Claude 碰后端代码时才出现——解决这些问题的,正是它。本文只讲一件事:.claude/rules/到底怎么工作、为什么这么设计,以及怎么把它用对。一、起点:CLAUDE.md 是一个文件,不是一套系统CLAUDE.md 的加载逻辑很朴素:向上遍历目录树,把沿途所有 CLAUDE.md 全文拼接进上下文。这个模型有一个隐含假设——你的所有项目规则,不管相不相关,都值得每次会话全量加载。小项目里这个假设成立。但项目一大就会浮现两个具体矛盾:膨胀矛盾:前端规范、后端规范、测试规范、安全规范全部塞进一个文件,官方建议的 200 行上限很快被击穿,而眼下用得上的 API 规则和根本用不上的 React 规则占着同样的上下文权重。无关性矛盾:你正在改一个 Python 脚本,却要让 Claude 每次都读一遍与之无关的 TypeScript 组件规范——这些 token 白白消耗,还可能引入指令噪音,增加规则之间互相矛盾的概率。.claude/rules/的价值主张正是针对这两点:先拆分,再按需。拆分解决膨胀(一个主题一个文件,而不是一整块文本);按需解决无关性(通过路径匹配,只有 Claude 真正接触到相关文件时,规则才进入上下文)。这两个能力是独立的——拆分本身不减少 token,真正省 token 的能力来自第三节的路径作用域。二、基础形态:目录即规则库把 Markdown 文件放进项目的.claude/rules/目录,每个文件对应一个主题:your-project/ ├── .claude/ │ ├── CLAUDE.md # 主项目说明 │ └── rules/ │ ├── code-style.md # 代码风格 │ ├── testing.md # 测试约定 │ └── security.md # 安全要求几个基础特性:递归发现:目录下所有.md文件都会被找到,包括嵌套子目录,所以可以按团队结构组织成rules/frontend/react.md、rules/backend/api.md这样的层级。一文件一主题:文件名要能望文生义,因为排查加载情况时,文件名往往是唯一线索。不带paths字段的规则文件等同无条件加载,加载优先级与.claude/CLAUDE.md完全相同。也就是说,把一份 CLAUDE.md 拆成十个 rules 文件,只要都不写paths,对上下文的实际消耗和拆分前一模一样——收益纯粹是组织结构上的可维护性,不是省 token。三、核心设计:路径作用域规则这是.claude/rules/存在的真正理由。在文件头部加一段 YAML frontmatter,声明paths字段:--- paths: - src/api/**/*.ts --- # API 开发规范 - 所有接口必须做输入校验 - 使用标准错误响应格式 - 补充 OpenAPI 文档注释paths字段是一个字符串数组,支持标准 glob 模式,也支持花括号扩展一次匹配多个后缀:模式匹配范围**/*.ts任意目录下的所有 TypeScript 文件src/**/*src/目录下的所有文件*.md项目根目录下的 Markdown 文件src/components/*.tsx特定目录下的 React 组件src/**/*.{ts,tsx}同时匹配.ts和.tsx触发机制:客户端确定性匹配,而不是模型的语义判断理解这条规则的关键在于弄清楚谁在做加载判断、依据什么做判断。路径作用域规则不是在每次工具调用时触发,而是在 Claude 实际读取、编辑到匹配路径的文件时触发——这个匹配是 Claude Code客户端做的确定性 glob 比对:某次文件操作命中了模式,规则内容就被注入上下文;命中不了,这份规则就完全不占用 token,也不会进入模型的视野。整个过程模型不参与决策,它甚至意识不到要不要加载这条规则这件事存在。这一点和 Skills 的加载机制形成了鲜明对比:Skills 的相关性判断是交给模型自己完成的——模型根据当前任务和技能描述,自主判断某个技能是否值得调用。而路径作用域规则从设计上刻意避开了这种语义判断,换成了纯粹的、可复现的文件系统事实匹配。设计取舍:为什么绑的是文件路径,不是用户输入的语义这是一个值得深究的设计决策,背后是两种触发信号可靠性上的根本差异。路径匹配是确定性的:一个文件要么命中 glob,要么不命中,可测试、可复现、没有歧义。绑定用户输入语义则要靠模型去判断这句话是不是在说 API 相关的事,天然是概率性的,既可能漏判也可能误判。更现实的问题是用户的措辞和代码的实际归属经常脱节:用户可能只是说把登录报错修一下,完全没提API或TypeScript,但改动最终落在某个 API 目录下的文件里——如果触发条件绑的是用户提到了相关字眼,这种情况会被直接漏掉;反过来,用户嘴上提到了某个技术词,但实际操作的是完全无关的文件,绑语义又可能被误触发。绑路径问的始终是一个客观事实,两种情况都不会出错。这也顺带划清了 rules 和 Skills 的分工边界:Skills 本就承担着判断任务语义相关性的职责,rules 没必要重复做同一件事。把 rules 锚定在文件系统事实上,和 Skills 的任务语义相关性恰好构成了两条互不重叠的触发轴。再往底层看,glob 匹配是纯客户端的字符串比对,零推理开销、零额外 token 成本;如果换成语义判断,则意味着每一轮都要让模型多做一次相关性推理,既不确定又更贵。frontmatter 是这套机制里最脆弱的一环路径作用域规则的失败模式很特殊:它不报错,只是静默地不生效。规则文件安安静静地待在目录里,你以为它在工作,实际上从未进入过上下文——原因可能是 glob 模式写错了、frontmatter 格式不被当前版本正确解析,或者规则所在的作用域层本身就不支持条件加载。这种失败比报错更危险,因为它不会在任何地方留下痕迹提醒你。因此,写完一条路径作用域规则后,不要假设格式写对了就万事大吉。稳妥的做法是:主动打开一个匹配路径下的文件,触发一次规则应该生效的场景,再去确认它是否真的进入了当次上下文。把验证生效当成写规则流程里不可省略的最后一步,比记住任何具体的版本号或语法细节都更可靠。四、作用域与优先级:用户级与项目级如何叠加.claude/rules/不止能放在项目内部,也支持用户级:层级位置作用范围加载顺序用户级~/.claude/rules/你本机上的所有项目先加载项目级项目根/.claude/rules/随仓库共享给团队后加载用户级规则先于项目规则加载背后的逻辑,和 CLAUDE.md 的分层哲学是一致的:离当前工作场景更具体的内容排在后面,在模型注意力上通常权重略高,所以项目规则实际上拥有比你个人全局偏好更高的话语权。适合放进用户级目录的是那些与具体项目无关、只关乎个人习惯的内容,比如你偏好的代码风格、你惯用的工作流程。需要提醒的是:这只是一种软性倾向,官方从未承诺过严格的后者覆盖前者语义——所有指令都会被同时看到并综合权衡。规则之间如果真的互相矛盾,Claude 依然可能任选其一,不能指望加载顺序替你消除冲突。五、跨项目复用:用符号链接共享一套规则如果你在多个项目上维护统一的团队标准(比如统一的安全审查清单),没必要在每个仓库里都复制一份。.claude/rules/目录原生支持符号链接,链接会被正常解析和加载,循环链接也会被检测并妥善处理:# 链接一整个共享目录ln-s~/shared-claude-rules .claude/rules/shared# 也可以只链接单个文件ln-s~/company-standards/security.md .claude/rules/security.md这个能力和 CLAUDE.md 里的import语法定位不同:import是把外部文件内容钉进当前文件的引用语法;符号链接则是在文件系统层面让多个项目物理共享同一份文件——改一处,所有链接到它的项目同步更新,不需要每个项目单独维护导入语句。在 Windows 上创建符号链接需要管理员权限或开启开发者模式,这是维护跨项目共享方案时需要提前考虑的限制。六、Monorepo 治理:claudeMdExcludes 该配置在哪在单一仓库容纳多个团队代码的场景下,向上遍历目录树会把其他团队的CLAUDE.md 和 rules 一并收进上下文——它们可能与你正在做的事完全无关,纯粹浪费 token 甚至引入冲突指令。claudeMdExcludes设置项可以按 glob 精确排除这些文件:{claudeMdExcludes:[**/monorepo/CLAUDE.md,/path/to/monorepo/other-team/.claude/rules/**]}这个设置写在settings.json/settings.local.json里,支持四个层级,各自的适用场景不同:层级影响范围适合的场景用户级设置只影响你本人,所有项目你个人在所有仓库里都想排除某类无关文件项目级设置(随仓库共享)进版本控制,全队共享团队达成一致,长期排除某些路径,需要经过 review项目本地设置(不进版本控制)只影响你在这一个项目里临时或个人化的排除,不希望影响其他成员托管策略(组织级)全公司所有机器,个人无法覆盖IT / 管理员要统一排除某类路径几个实操细节:匹配是针对绝对路径的 glob 匹配,写排除规则时要确认路径写全了。各层的排除数组是合并去重关系,不是覆盖关系——多层同时配置会叠加,不会互相打架。唯一的例外是:托管策略自己的 CLAUDE.md 永远不能被任何层的claudeMdExcludes排除,这是刻意设计,确保组织级底线规则任何人都绕不过去。选层的经验法则很简单:只影响自己且是临时性的,放本地设置;团队达成共识要长期生效,放项目级共享设置并走 review;需要全公司统一执行,交给托管策略层。七、边界:rules 不是万能容器.claude/rules/解决的是指令模块化 按路径懒加载这一个具体问题,不该用它承担别的职责。放在一起对比,更容易看清每种机制该管什么:机制加载时机谁来触发适合放什么CLAUDE.md会话启动时全量加载客户端,无条件全项目通用的规范、架构决策.claude/rules/(无paths)会话启动时全量加载客户端,无条件效果等同 CLAUDE.md,仅用于拆分组织.claude/rules/(带paths)Claude 读取匹配路径文件时客户端,按路径确定性触发只对特定目录/文件类型生效的规范Skills被调用或判断相关时模型自主判断相关性,或用户显式调用多步骤操作流程Hooks固定生命周期事件客户端强制执行,不依赖模型判断必须每次都执行的硬性动作这张表里最容易被混淆的一点是:rules(哪怕是路径作用域的)本质上仍然是影响 Claude 的行为倾向,而不是阻止 Claude 做某事的硬约束。如果你的需求是绝对不能让 Claude 碰某类敏感文件,不该写成一条规则寄希望于模型自觉遵守,而应该用权限拒绝规则或生命周期钩子做客户端强制拦截——规则文件管不住这种红线,它能做的只是提高模型遵循某种约定的概率。八、调试:如何确认规则真的生效了排查.claude/rules/相关问题时,按下面顺序检查,能覆盖绝大多数情况:先确认文件被发现和加载:列出当次会话已加载的全部记忆与规则文件。如果目标文件没出现在列表里,说明它压根没被发现或没被触发加载,不必急着怀疑规则内容本身写得对不对。确认触发条件真的满足:如果是路径作用域规则,先检查是否真的让 Claude 接触过匹配路径的文件——它不是无条件加载的,不触碰匹配文件就永远不会出现。怀疑 frontmatter 格式问题时,做最小化验证:去掉复杂的 glob 组合,先用一个最简单的模式单独测试是否生效,再逐步加回复杂度,定位到底是哪一部分格式导致了静默失败。用生命周期日志辅助排查:如果客户端提供了指令加载相关的钩子或日志,善用它记录哪些指令文件在何时、因为什么原因被加载,这比反复靠猜测验证更可靠。排查规则之间的冲突:多个规则文件之间,或规则与 CLAUDE.md 之间如果给出矛盾的指令,模型可能任选其一——这不是加载失败,而是权重博弈的结果,需要靠人工审查消除冲突,而不是指望加载顺序替你决定一切。结语.claude/rules/本质上是给 CLAUDE.md 补上了两个它天生缺乏的能力:模块化组织(一个主题一个文件,而不是一整块文本)和条件加载(路径匹配触发,而不是无条件常驻)。理解它的关键在于分清两种形态——不带paths的规则就是拆分过的 CLAUDE.md,图的是可维护性;带paths的规则才是真正的增量能力,图的是上下文效率。而路径作用域规则的设计本身也传递出一个更普遍的原则:能用确定性的客观信号解决的触发判断,就不要交给概率性的语义判断去做。文件路径是稳定、可验证、零成本的信号;用户意图是模糊、需要推理、有成本的信号。Claude Code 把这两类判断分别交给了 rules(路径匹配)和 Skills(语义相关性),各司其职,而不是让一种机制包办所有触发场景。用好.claude/rules/,记住三条:小项目不必用,先用一份 CLAUDE.md;规则膨胀或出现明显的路径相关性时再拆分;拆分后凡是只对某类文件生效的部分,一定补上paths,否则拆分本身不省一分 token。写完之后,养成主动验证生效与否的习惯,比记住任何具体的语法细节都更可靠。