用过一段时间 Claude Code 的人,多少都会遇到类似的情况:同一个项目,换台电脑启动,它记住的东西不一样了;明明配置好的自定义命令,换个目录就消失了。这些问题背后,其实都指向同一件事——文件层级机制。Claude Code 不只是一个跑在终端里的对话机器人,它是一套有完整“内政体系”的编程代理,而文件层级就是这个体系的骨架:配置文件按作用域分层,记忆文件按目录递归,技能和命令按存放位置决定可见性。这篇文章,我会从全局目录结构讲起,把用户级、项目级、目录级这几层的关系彻底拆开,然后分别拆解 CLAUDE.md 的记忆机制、settings.json 的合并规则、skills 与 commands 的存放边界,最后给出我平时排查“配置不生效”的完整思路。无论你刚装好 Claude Code,还是已经在团队里推广它,这几层关系搞清楚了,很多玄学问题会直接变成明牌。
1. 先从全局视角看:Claude Code 装完后你的文件系统变成了什么样
很多人第一次用 Claude Code,只知道在终端敲一个claude就进去了,对背后落盘的东西毫无概念。直到某天你想备份配置、迁移机器,或者单纯想看看它到底在自己的电脑里写了什么,才发现~/.claude这个目录庞杂得像一间杂物间。要理解文件层级机制,第一步就是先把这张“城市地图”画出来。
1.1 系统层:全局命令与安装包落在哪里
Claude Code 最常见的安装方式是通过 npm 全局安装,也就是npm install -g @anthropic-ai/claude-code。这一步做完,你的系统里会多出一个claude可执行文件,通常被放在 npm 的全局 bin 目录下,比如 macOS/Linux 的/usr/local/bin/claude或~/.npm-global/bin/claude,Windows 上则在 npm 全局路径对应的目录里。这个位置属于“系统层”,它只负责一件事:让你在任何目录下都能直接敲出claude命令。
但注意,这个可执行文件本身只是启动器。Claude Code 真正的源码包、依赖、内置资源存放在 npm 的全局 node_modules 里,更新版本时也是替换这一块。卸载的时候,很多人只删了~/.claude,结果claude命令还在,真正该做的是npm uninstall -g @anthropic-ai/claude-code。这个系统层平时你不会去碰它,但它决定了“命令从哪来”。
系统层的另一块是缓存目录,不同平台上会落在~/.cache/claude-code或类似位置。里面装着版本更新缓存、临时文件、部分 telemetry 数据。这块体积可能会悄悄涨到几百 MB,长期不清理也属于正常现象。不过我不建议没事就删,因为某些缓存删掉后,下次启动反而会重新下载,体验更差。
1.2 用户层:~/.claude/ 是你的个人工作台
系统层装完后,第一次运行claude,它会在你的用户主目录下创建~/.claude/,这是整个文件层级机制里最重要的一层。它不属于任何项目,只属于你这台机器、这个用户。
我把它称为“个人工作台”,因为只要是这台机器上跑的 Claude Code 会话,无论你在哪个目录启动,都会加载这一层里的内容。几个核心成员如下:
| 路径 | 作用 | 生命周期 |
|---|---|---|
~/.claude/CLAUDE.md | 用户级长期记忆 | 每个会话开始时加载 |
~/.claude/settings.json | 用户级配置 | 所有项目合并生效 |
~/.claude/commands/ | 全局自定义斜杠命令 | 所有项目可用 |
~/.claude/skills/ | 全局技能包 | 按语义触发时可用 |
~/.claude/projects/ | 各项目的会话 JSONL 记录 | 用于 --resume、回滚 |
~/.claude/history/ | 终端输入历史 | 类似 shell history |
这里最容易忽略的是projects/。它里面不是按项目名直接存放,而是按“项目路径的哈希值”分目录。每个会话对应一个.jsonl文件,里面完整记录了每一次消息、每一次工具调用、每一次文件修改。你之后想用claude --resume找回上次会话,实际上就是在扫描这个目录。
用户层的定位是“跨项目的公约数”。你个人偏好的代码风格、常用命令、通用技能,都应该放在这一层。它不跟着项目走,只跟着人走。
1.3 项目层:.claude/ 和散落在各级目录的 CLAUDE.md
当你进入某个项目目录启动 Claude Code 时,它会寻找项目根目录下的.claude/目录,以及散落在各层的CLAUDE.md文件,这就是项目层。
.claude/目录里还有几个固定的位置:
| 项目内路径 | 作用 |
|---|---|
.claude/settings.json | 项目级配置,团队共享 |
.claude/settings.local.json | 项目级个人配置,不提交 Git |
.claude/commands/ | 项目专属斜杠命令 |
.claude/skills/ | 项目专属技能包 |
.claude/plugins/ | 项目内安装的插件及其缓存 |
注意,项目层并不等于“只有.claude这一个文件夹”。你的仓库根目录下的CLAUDE.md、子目录下的CLAUDE.md,同样属于项目层的记忆体系。它们和.claude/CLAUDE.md在功能上等价,都可以被加载。区别在于,.claude/是个隐藏目录,适合放机器配置;而根目录的CLAUDE.md更显眼,适合放给人看的项目说明,同时也能被 Claude 读取。
项目层和用户层最大的区别在于协作属性。.claude/settings.json应当提交到 Git,因为它是团队共识;.claude/settings.local.json则必须进.gitignore,因为它是个人私有。
1.4 三层之间的边界:从哪个目录启动,就继承哪一层
搞懂三层之后,最重要的一句话是:Claude Code 的配置加载是“自下而上合并”的。你从哪个目录启动,决定了你能继承到哪几层。
- 从
~目录启动:只有用户层,没有项目层,Claude 对你的项目一无所知。 - 从项目根目录启动:用户层 + 项目根层 + 该目录链上所有 CLAUDE.md。
- 从项目子目录启动:用户层 + 项目根层 + 子目录层。Claude Code 会向上查找 git 根目录来判断项目边界,一旦找到就加载根级配置。
我用一个生活类比:用户层是你的“手机通讯录”,无论你在哪个城市都带着;项目层是“公司通讯录”,进了公司才能用;而子目录层的 CLAUDE.md 是“部门内部备忘录”,只有当你在那个部门办公时,才拿出来看。这个边界感,就是整个文件层级机制的第一块基石。
2. CLAUDE.md 的递归加载:记忆不是平面的,而是分级的
CLAUDE.md 是 Claude Code 最核心的记忆载体。很多人把它当成一个简单的“项目说明文件”,往根目录一放就完事了。但实际上,CLAUDE.md 是有层级结构的,而且会递归加载。理解这一点,你才算真正开始上手文件层级机制。
2.1 三类 CLAUDE.md 各自管什么
按官方设计和社区实践,CLAUDE.md 至少分成三类:
- 用户级
~/.claude/CLAUDE.md:存放你不会写进任何项目的个人规则。比如“代码注释一律用中文”“函数命名优先用动词开头”“回复时不要重复我的问题”。它对这台机器上的所有项目生效。 - 项目根级
./CLAUDE.md或.claude/CLAUDE.md:存放团队和项目的公约。比如技术栈说明、构建命令、目录结构、提交规范、测试要求。 - 子目录级
<子目录>/CLAUDE.md:存放局部上下文。比如某个模块的历史包袱、某个服务的部署注意点、某个目录里不该碰的文件名单。
这三类的加载优先级并不是“后写覆盖先写”,而是全部塞进上下文。也就是说,Claude 每次会话开始时,会把它能找到的、与你当前所在路径相关的所有 CLAUDE.md 都读一遍。用户级在最前面,随后是项目根级,然后是工作目录链上每一层的 CLAUDE.md。这个机制的设计意图很清楚:让模型在回答任何问题时,都拥有从“个人偏好”到“项目全局”再到“局部细节”的完整背景。
2.2 从项目根到子目录的递归加载规则
递归加载的规则,比我见过的大多数人理解的更微妙。它并不是“扫描整个仓库所有 CLAUDE.md 一次性全读”,而是“只读从项目根到当前工作目录这条链上的文件”。
举个例子,假设仓库结构是这样的:
my-project/ ├── CLAUDE.md ├── src/ │ ├── CLAUDE.md │ └── core/ │ ├── CLAUDE.md │ └── engine.go └── docs/ └── CLAUDE.md- 如果你在
my-project根目录启动,加载的是根级CLAUDE.md,用户级也会加载。 - 如果你先
cd src/再启动,会加载用户级、根级、src/CLAUDE.md。 - 如果你进入
src/core/,还会继续加载core/CLAUDE.md。 - 但
docs/CLAUDE.md永远不会加载,除非你从docs/目录启动。
这个设计意味着:你越是深入某个模块,Claude 就越能“看到”这个模块独有的注意事项。反过来说,如果你希望某条规则在任意位置都生效,就别把它放在子目录,直接放到根级 CLAUDE.md 里。
还有一个小技巧:当你想让 Claude 主动参考某个地方的说明时,可以直接在对话中用@路径引用具体文件,这比依赖自动递归加载更可控。比如@docs/deployment.md 按这里的步骤部署,Claude 就会把那个文件也读进来。
2.3 所谓“优先级”其实不是覆盖,而是注意力距离
我在社区里看到不少人在争论:“根级 CLAUDE.md 和子目录 CLAUDE.md 冲突时,到底谁说了算?”这个问题本身问得就有偏差。
CLAUDE.md 不是一个配置文件,不存在“后加载的覆盖先加载的”这种覆盖语义。它更像文本拼接:所有文件都被转换成文本,按顺序进入模型的上下文窗口。真正影响行为的是表述明确度和上下文距离。子目录的 CLAUDE.md 因为离当前任务更近、描述更具体,所以往往更容易被模型采纳;但这不是必然,如果根级文件里写的是“绝对禁止”,子目录写的是“可以尝试”,模型仍然可能犹豫。
所以在实际写作时,我的原则是:
- 根级 CLAUDE.md 放“不可违背”的硬规则,语气用“必须”“禁止”“永远不要”。
- 子目录级 CLAUDE.md 放“模块内特有”的软规则,语气用“建议”“优先考虑”“这里有个坑”。
- 尽量避免不同层之间出现同一主题的互相矛盾表述。一旦矛盾,结果就是模型随机站边,比不写更糟。
2.4 一套拿来即用的 CLAUDE.md 分层模板
下面是我在多个中大型仓库里验证过的一套分层策略,你可以直接抄:
# 根级 CLAUDE.md - 项目一句话说明 - 技术栈清单 - 如何运行测试 - 如何构建 - 提交信息规范 - 目录地图(告诉 Claude 去哪找什么) - 全局禁止事项# services/ 下的 CLAUDE.md - 本目录包含哪些服务 - 服务之间的调用契约 - 环境变量说明 - 启动顺序# services/auth/ 下的 CLAUDE.md - 认证模块的已知限制 - 密钥轮换注意事项 - 这个模块里哪些文件不能改(历史原因)用户级~/.claude/CLAUDE.md则放:
- 我的代码风格偏好 - 我常用的工具链 - 回复风格偏好(比如“先给结论再解释”)这套模板的精髓在于:知识放在离问题最近的地方。根级解决“这个项目是什么”,子目录解决“这个模块有什么坑”。Claude 召回的准确率,会明显比把所有内容塞进一个巨型 CLAUDE.md 高得多。
3. settings.json 的四层合并:从全局默认到项目私有
CLAUDE.md 管记忆,settings.json 管行为。权限、模型选择、hooks、环境变量,全都由它控制。而 settings.json 的文件层级机制,比 CLAUDE.md 更严格,因为它存在真正的“合并优先级”。
3.1 四层 settings 文件的优先级顺序
先给结论,settings.json 的优先级从低到高是:
内置默认值 < 用户级~/.claude/settings.json< 项目级.claude/settings.json< 本地开发.claude/settings.local.json< 企业策略
这里有三个容易踩的坑:
第一,企业策略不是你能改的。如果你的 Claude Code 被企业托管,最高层会被锁定,你在本地怎么配都覆盖不过去,而且不会报错。很多人折腾半天“为什么我改了不生效”,最后发现是管理员从上层锁死了。
第二,本地开发文件settings.local.json的优先级高于项目级settings.json。这是刻意的设计——方便你在不污染团队配置的前提下,做个人调试。比如团队规定默认模型是opus,你想本地试sonnet,只需要在settings.local.json里覆盖一个model字段即可。
第三,优先级跟物理层级不同。~/.claude在物理路径上比你项目里的.claude高,但在合并顺序上反而是更底层。这一点和我上面说的 CLAUDE.md 的递归加载逻辑刚好相反,别搞混。
3.2 字段级合并:env、permissions、hooks 的表现不一样
很多人以为 settings 合并是整个文件“谁级别高谁赢”,其实不对。它不是整文件覆盖,而是按字段做深度合并。不同字段的行为规则也完全不同:
| 字段 | 合并行为 | 实际效果 |
|---|---|---|
model | 高优先级覆盖低优先级 | 本地设了 sonnet,项目设了 opus,本地赢 |
env | 同 key 高优先级覆盖,其余合并 | 上层 env 不会被下层清空 |
permissions.deny | 任意层 deny 都生效 | 只要有一层禁止,就禁止 |
permissions.allow | 高优先级层优先,但可被 deny 拦截 | 项目 allow 了,本地 deny 了,本地赢 |
hooks | 按层合并,同一事件可触发多个 hook | 用户层 hook 和项目层 hook 都会跑 |
permissions的 deny 是“一票否决”这个逻辑,对我解决实际问题帮助很大。举个例子:团队不允许任何人跑git push --force,在项目级的settings.json里写一条 deny 规则。就算某个开发者在自己的settings.local.json里 allow 了这条命令也没用,deny 永远拦在前面。这其实就是文件层级机制在安全边界上的体现。
env字段值得一提。它允许你在 settings 里直接定义环境变量。比如有些团队通过兼容协议接入第三方语言模型,会设置ANTHROPIC_BASE_URL、ANTHROPIC_MODEL之类的端点配置。这类变量放在不同层,影响范围完全不同——放用户层是跨项目生效,放项目层是团队共享,放 local 层是个人调试专用。
3.3 用 /config 做实时验证
配置最怕的就是“我觉得我改了,但它好像没读到”。所以我养成了一个习惯:任何 settings 改动之后,第一步就是运行/config命令。
/config是 Claude Code 内置的配置查看器,它会列出当前会话实际生效的合并后配置。你不需要自己手工去逐层核对,它直接展示最终结果。如果你发现某个字段的值和自己预期不一样,再用“内置 < 用户 < 项目 < 本地 < 企业”这个顺序倒推,看是哪一层覆盖了你的设置。
但/config有个局限:它显示的是“当前会话启动时”的配置。如果你修改了 settings.json,已经开启的会话不会自动重新加载全部字段。我的建议是,改完任何 settings 文件,先退出会话,再重新启动,然后/config验证。一次完整的“改-重启-验证”流程下来,能省掉大量自我怀疑的时间。
另外一个实用命令是claude config,它可以在命令行直接读写用户级配置的通用项,比如设置主题、调整输出模式。这种命令写进去的其实就是~/.claude/settings.json,和手动编辑效果一样。
3.4 密钥、环境变量与第三方模型端点的配置层级
现在很多团队会把 Claude Code 接到其他模型供应商上,技术上通常就是通过环境变量指定兼容的 API 端点和模型名。这里就涉及一个层级选择问题:这些配置到底放哪一层?
我的建议分三种场景:
- 你个人所有项目都用的端点:放在用户级
~/.claude/settings.json的env字段里。好处是只配置一次,所有项目都能识别。 - 团队统一指定的端点:放在项目级
.claude/settings.json的env字段里,并且提交到 Git。这样团队成员拉下代码就能直接跑,不用各自配。 - 只在你本机调试、不想影响同事:放在
.claude/settings.local.json里,并且确保它被.gitignore忽略。
这里有一条安全红线:settings.local.json绝对不能提交到 Git 仓库。因为它就是设计来放个人私货的——你的个人 token、你本地调试用的端点地址、你临时改的模型参数。一旦提交,等于把密钥发给全团队。我在实际项目里见过不止一次因为这种疏漏导致的密钥泄露事故。
补充一个.gitignore模板片段:
.claude/settings.local.json .claude/.cache/ .claude/plugins/如果团队里大家都很依赖 Claude Code,我会建议仓库里统一放一份.claude/settings.json,里面只写公共规则,同时在 README 里说明“个人覆盖请写入 settings.local.json”。这个约定清晰之后,配置冲突会少很多。
4. Skills 与 Commands:文件放在哪一层,能力就在哪一层生效
CLAUDE.md 和 settings.json 解决的是“模型知道什么、能做什么”。而 skills 和 commands 解决的是“模型会什么高级技能、你有哪些快捷指令”。这两类东西同样被文件层级机制管着,而且存放位置直接决定能力边界。
4.1 技能的三种存放位置与可见边界
Skills 是 Claude Code 的“可插拔能力包”,本质是一个包含SKILL.md的目录。它有三种存放位置:
| 层级 | 路径 | 可见范围 |
|---|---|---|
| 用户级 | ~/.claude/skills/<技能名>/ | 所有项目可用 |
| 项目级 | .claude/skills/<技能名>/ | 仅当前项目 |
| 企业级 | 企业托管策略指定 | 企业内所有受管机器 |
我个人的使用习惯是:把通用技能放用户级,把业务相关技能放项目级。比如“PDF 摘要生成器”“批量代码格式化器”属于通用技能,放用户级;而“解析本项目的配置模板并生成新模块脚手架”这种强业务相关的,放项目级。
用/skills命令可以列出当前会话可用的全部技能。你会清楚地看到哪些来自用户级、哪些来自项目级。这个列表是排查“为什么某个技能没生效”的第一现场。
4.2 SKILL.md 的格式与触发逻辑
一个技能目录长得像这样:
~/.claude/skills/pdf-summarizer/ ├── SKILL.md ├── scripts/ │ └── summarize.py └── references/ └── layout-guide.mdSKILL.md是这个技能的核心,采用 Markdown 格式,前面是 YAML frontmatter,后面是正文指令。最关键的是description字段:
--- name: pdf-summarizer description: 当用户需要总结 PDF 文档、提取 PDF 内容、或者询问 PDF 中的关键信息时使用。适用于本地 PDF 文件。 --- 你是一个 PDF 摘要专家。用户会提供 PDF 路径,你需要按以下步骤处理: 1. 先用 scripts/summarize.py 提取文本 2. 然后生成包含核心结论、数据点、行动项的结构化摘要description为什么是“最关键”字段?因为 Claude 判断“什么时候该用这个技能”,靠的就是它。它会在对话中持续对比当前用户的意图和所有可用技能的 description,一旦匹配就加载对应技能目录。所以 description 里要写清楚“触发场景、输入条件、输出目标”,而不是写空泛的“这个技能可以帮你处理 PDF”。
Skills 和 CLAUDE.md 的区别也很关键:CLAUDE.md 是常驻上下文,每次会话都占 token;skills 是按需加载,不触发就完全不在上下文里。换句话说,文件层级机制在这里帮你实现了“知识常驻 vs 能力按需”的平衡。
4.3 斜杠命令:只占一个目录,却能省掉大量重复劳动
斜杠命令(Slash Command)是 Claude Code 里你输入/名称就能触发的一段预置指令。内置的比如/compact压缩上下文、/haha开启趣味模式,而自定义命令则是你自己写的。
自定义命令的存放位置同样分两层:
- 用户级:
~/.claude/commands/,所有项目可用。 - 项目级:
.claude/commands/,仅当前项目可用。
命令文件就是普通的.md文件,文件名去掉.md就是命令名。举个例子,你创建一个~/.claude/commands/pr-review.md,里面写:
--- description: 生成一次完整的 PR 审查意见 model: sonnet --- 你要扮演资深代码审查者,对当前分支的改动进行逐文件审查。重点检查: - 安全问题 - 逻辑漏洞 - 样式一致性 - 测试覆盖是否充分 输出格式:按严重程度分级列出,每项给出文件路径和建议改法。之后你在任何项目里输入/pr-review,Claude 就会加载这段指令执行。这个机制非常适合放你反复要用、但又不希望常驻上下文的流程。
命令里还可以用$ARGUMENTS占位符接收用户输入。比如你想写一个“创建新组件”的命令,可以在说明里用$ARGUMENTS接“组件名”,Claude 会把它替换为用户敲的内容。这个能力让命令从一个死模板,升级成一个可交互的小工具。
4.4 同名冲突时到底谁赢
如果用户级和项目级存在同名的 skill 或 command,按照文件层级机制的惯例,项目级优先。也就是说,.claude/skills/deploy会盖过~/.claude/skills/deploy,.claude/commands/review.md会盖过~/.claude/commands/review.md。插件提供的同名能力,通常优先级更低一些。
但我必须提醒一句:依赖覆盖规则是一种坏味道。一旦你依赖“同名覆盖”,很可能过几个月你自己都忘了哪层是哪层。更好的做法是给名字加上业务前缀,比如公司名或项目名开头,从命名上就避免冲突。文件层级机制应该是最后的兜底,而不是日常依赖的手段。
5. 会话历史与项目状态:藏在 ~/.claude 深处的数据
如果说 CLAUDE.md 和 settings.json 是 ClCode 的“口粮”,那么~/.claude/projects/就是它的“日记本”。这一层看似不起眼,实际却在日常使用中扮演着极其重要的角色。
5.1 projects 目录:会话记录为什么按哈希存放
Claude Code 把每个项目的会话记录保存在~/.claude/projects/<项目路径哈希>/目录下,每个会话一个.jsonl文件。之所以不直接用项目名,而是用路径哈希,是为了避免特殊字符、路径长度和隐私问题——毕竟你的完整目录路径本身可能就是信息。
这个目录有什么用?最直观的就是claude --resume。你输入这个命令,它会列出该项目的历史会话,你可以按序号一键恢复。恢复之后,Claude 能记得上下文,你也能继续之前的对话。另一个场景是/rewind,它允许你回退到之前某个状态,底层同样依赖于这些 JSONL 文件里的完整记录。
一个 JSONL 文件里,每一行是一个对象,包含消息类型、角色、时间戳、内容、工具调用结果等结构。技术型用户可以自己写脚本去分析“我哪类问题占用了最多 token”。不过我更建议普通用户别直接动这些文件,容易把会话数据改坏。
5.2 历史记录带来的管理与隐私问题
会话历史会带来两个实际问题:磁盘占用和隐私泄露。
先说磁盘。你可能意识不到,一个高强度用了几周的 Claude Code,projects 目录可能轻轻松松涨到几个 GB。尤其是经常跑大文件、频繁做代码审查的会话,每条消息都很大。我见过有人 macOS 上这个目录涨到 10GB 以上,连 Time Machine 备份都变慢了。
再说隐私。.jsonl文件里存的是你所有对话的明文,包括代码片段、API 密钥如果被讨论过、内部架构讨论等。如果你把~/.claude整个打包发给别人,就等于把项目机密全部交出去了。很多团队用 Claude Code 很久之后才发现,成员的~/.claude/projects/里积累了大量外包项目的完整对话记录,一旦笔记本丢失,泄露面相当大。
所以我的建议很直白:
- 定期清理超过一定天数的会话记录,比如只保留最近 30 天。
- 离开外包项目或客户项目时,手动删除对应的哈希目录。
- 笔记本电脑要送修或转手前,先全局清理
~/.claude/projects/。
清理时直接删目录就行,Claude Code 下次会自动重建。不过删之前确认一下你不需要--resume找回那段对话了,因为删除不可逆。
5.3 备份与迁移:把哪一层装进压缩包才最有价值
当你换电脑、重装系统,或者想给新同事同步一套好用的配置时,你会面临一个问题:~/.claude那么大,哪些值得备份?
我的备份清单是这样的:
~/.claude/CLAUDE.md ~/.claude/settings.json ~/.claude/commands/ ~/.claude/skills/这四样是你个人工作台的核心资产,体积小、价值高。打包迁移后,新机器上直接放进~/.claude/就能恢复你的“内政体系”。
我不建议备份~/.claude/projects/和~/.claude/history/。会话记录体积大、含敏感信息,而且迁移价值低——你已经不记得上个项目的上下文了,把几 GB 的 JSONL 搬到新机器也只是占空间。同理,各种缓存目录(~/.cache/claude-code之类的)也不需要备份,它自己会重新生成。
如果你用的是公司配发的电脑,离职前我建议把上面四样资产备份走,同时把~/.claude/projects/里涉及公司业务的部分彻底清除。既能带走自己的经验,又能保证项目数据留在公司,这个边界值得细琢磨。
6. 层级机制的排错指南:当 Claude Code 没有按预期行为工作时
最后这部分是我踩坑最多的领域,也是最值得分享的实操经验。遇到“Claude Code 不听话”的时候,绝大多数问题不在模型能力,而在于文件层级错位。
6.1 第一个检查点:从哪个目录启动决定了你处在哪个“项目上下文”
有一次我在一个微服务仓库的services/auth子目录里启动 claude,想让它基于整个仓库做一次架构审查。结果它对其他服务模块一问三不知,因为它没有加载根级 CLAUDE.md 里关于整体架构的描述。这让我差点以为配置坏了。
后来才意识到,问题出在“启动目录”。从子目录启动时,Claude Code 会向上查找 git 根目录,找到后加载根级配置,但工作目录链上的子目录 CLAUDE.md 也会叠加进来。当时我以为它加载根级了就万事大吉,忽略了子目录文件可能带来的“局部视野偏置”。
所以我现在的工作习惯很固定:做全局任务就在项目根目录启动,做模块任务就 cd 到对应目录再启动。如果你发现自己需要频繁在一个固定子目录里做全仓操作,那就把相关说明写进子目录的 CLAUDE.md,让 Claude 知道“在这里启动时,别忘了看整个仓库”。
6.2 第二个检查点:配置改了不生效,先查这三件事
“我改了 settings.json,但它就是不管用”是我被问到最多的问题。按这套流程走,基本三步内定位:
第一,你改对层级了吗?如果你写的是用户级~/.claude/settings.json,而项目级.claude/settings.json里有同名字段,那自然项目级赢。先跑/config看当前实际生效值,再对照“内置 < 用户 < 项目 < 本地 < 企业”的优先级逐层定位。
第二,你重启会话了吗?settings.json 的很多字段在会话启动时才读取,你改完文件但会话还开着,它不会实时变化。这一点和 CLAUDE.md 不同,CLAUDE.md 在会话过程中也可能被新的@引用重新加载,但 settings 的稳定性更强。改完配置,别犹豫,退出重进。
第三,有没有被企业策略锁死?如果你的环境是企业托管,管理员可以通过策略强制覆盖用户和项目配置。遇到无论如何都改不动的字段,优先怀疑这一层。用/config看的时候,如果某个字段显示锁定或来源是企业策略,那就别再跟它较劲了。
6.3 两条底层心得:层级本质上是边界设计
踩过这么多坑之后,我越来越确信,Claude Code 的文件层级机制不是一个实现细节,而是一个核心设计哲学:它在用文件系统帮你划分边界。
第一条心得是:把 CLAUDE.md、settings.json、skills、commands 当作四个独立的“抽屉系统”。CLAUDE.md 放常驻知识,settings 放行为约束,skills 放按需能力,commands 放高频动作。这四套抽屉各自都有层级,但层级规则不同:CLAUDE.md 是递归合并,settings 是优先级覆盖,skills/commands 是就近生效。不要用 settings 的思维去写 CLAUDE.md,也不要用 CLAUDE.md 的思路去配 skills。
第二条心得是:给每一层定一个明确的 owner。用户层属于你个人,项目层属于团队,local 层属于你的私密空间。当你把个人习惯写进项目级配置,把团队机密写进用户级文件,层级机制就会反过来坑你。反过来,如果你能像管理代码模块一样管理这些文件——给每层定义好职责边界,定期清理,保持精简——Claude Code 会越用越顺手,你会明显感觉到它在不同目录、不同项目里都保持着一贯的稳定表现。
文件层级机制这层窗户纸捅破之后,剩下的全是收益。先把文件放在对的层级,Claude Code 才真正算是你的编程搭档,而不是一个偶尔聪明、经常懵圈的对话窗口。