Claude Code 配置改了不生效:配置优先级与官方给的诊断动作
配置改了不生效,是多层配置的命令行工具都有的老毛病:你在一个文件里写了值,工具从另一个文件读到另一个值,两边都不报错。Claude Code 官方文档专门给了一页 code.claude.com/docs/en/debug-your-config 讲这件事,开篇给出的判断是——原因通常是文件没加载、从你没预期的位置加载了、或者被另一个文件覆盖了。
三种原因的排查手段不同。下面按「先看加载了什么,再看谁覆盖了谁」过一遍,最后说什么情况可以排除优先级这条线。
一、现象:改了,但表现没变
典型的几种表现:settings.json 里加的 permissions 规则没起作用;写好的 hook 从来不触发;CLAUDE.md 里的约定被无视;某个 MCP 服务器配好了却拿不到工具。共同点是——没有任何报错,所以很容易被当成产品 bug。
先别急着改。文档给的第一步不是改,是看。
二、怎么确认:官方文档列出的可执行判定动作
/context 是入口命令。文档写明它会展示当前会话占用上下文窗口的全部内容,按类别拆开:system prompt、system tools、MCP tools、自定义 subagent(并标出各自从哪个来源加载)、memory 文件、skills,以及会话消息。先跑它,确认你的 CLAUDE.md、规则、skill 描述到底在不在里面。
想看某一类的细节,文档给了对应的专用命令:
| 命令 | 文档写明它展示什么 |
|---|---|
/memory | 用户与项目两个 scope 下的 memory 文件位置,可逐个在编辑器中打开;另有 auto memory 文件夹与 auto memory 开关 |
/skills | 来自 project、user、plugin 三种来源的可用 skills |
/hooks | 当前生效的 hook 配置 |
/mcp | 已连接的 MCP 服务器及其状态 |
/permissions | 当前实际生效的 allow 与 deny 规则(已解析后的结果) |
/doctor | 安装健康度、无效的 settings 文件、未使用的扩展、同一目录下重名的 subagent,以及可从代码库推导出的、被签入的 CLAUDE.md 内容,并给出待确认的修复建议 |
/debug [issue] | 为当前会话打开 debug 日志,并让 Claude 结合日志输出与 settings 路径做诊断 |
/status | 当前生效的 settings 来源,包括 managed settings 是否在起作用 |
这张表是本篇的第一个落点:它把「配置没生效」拆成了八个可以分别验证的子问题,而不是让你去猜。表里 /doctor 那一行还有个版本分界,文档写明 CLAUDE.md 的精简检查需要 v2.1.206 或更新版本;在 v2.1.205 之前,文档写明 /doctor 打开的是只读的诊断视图,要按 f 才把报告交给 Claude 去修。终端里还有一个不进会话的形式:claude doctor 会直接打印只读的安装与设置诊断。
三、优先级:谁覆盖谁
确认文件确实加载了、但值不对,就轮到优先级。官方 settings 文档(code.claude.com/docs/en/settings)给出的顺序是,从高到低:
- Managed settings——server-managed 交付、MDM/OS 级策略,或 managed settings 文件
- 命令行参数——只对本次会话生效
- Local project settings(
.claude/settings.local.json) - Shared project settings(
.claude/settings.json) - User settings(
~/.claude/settings.json)
文档明确写了 managed 这一层「没有其它层级能覆盖它,命令行参数也不行」,但同时留了一份《Exceptions to managed settings precedence》例外表,里面是几个安全敏感键:disableClaudeAiConnectors、isolatePeerMachines、remoteControlAtStartup、crossSessionInbound——这四个键上,Claude Code 会接受来自低层级的更严格的值。这不是「低层能覆盖高层」的通例,只是这几个键的定向开口。
还有一条最容易被误判的规则:数组类的键是合并,不是替换。文档举的例子是 sandbox.filesystem.allowWrite 与 permissions.allow:同一个数组键在多个 scope 里都写了,Claude Code 会把它们拼接并去重,而不是让高优先级那份把低的顶掉。也就是说,你在 user settings 里加一条 allow,并不会因为项目里也有一份就失效——反过来说,你想靠改高层把低层的某条 allow 拿掉,是拿不掉的。文档同时点名了两个不走合并的数组键:fallbackModel 是有序链条,位置本身有含义,取定义它的最高优先级那份整体值;availableModels 在最高优先级的 managed 源里定义时,用户、项目、本地层加的条目会被忽略。
四、managed 那一层内部还有一次排序
如果你所在的组织同时下发了多种 managed 配置,docs/en/settings 里《Precedence within the managed tier》给了这一层内部的顺序:
- 远端下发(server-managed settings,或 Claude apps gateway 下发的策略)
- MDM 或 OS 级策略
- Managed settings 文件(
managed-settings.d/*.json与managed-settings.json合并后作为一份) - HKCU 注册表(仅 Windows)
关键在后半句:这四个源不合并,Claude Code 取第一个交付了非空配置的源,其余直接忽略。code.claude.com/docs/en/server-managed-settings 把同一件事又说了一遍:server-managed 只要交付了任何键,其它 endpoint-managed 设置就被忽略;server-managed 什么都没交付时,endpoint-managed 才生效。这意味着一个很反直觉的情形——管理员在控制台里留了一个键,MDM 里那一整份策略就都不作数了。
例外是少量「跨源键」:sandbox 的两个锁键 sandbox.network.allowManagedDomainsOnly 与 sandbox.filesystem.allowManagedReadPathsOnly(及其配套 allowlist)、allowAllClaudeAiMcps、sandbox 二进制路径 sandbox.bwrapPath 与 sandbox.socatPath、forceRemoteSettingsRefresh,以及 env 块。文档写明 env 是按变量逐个合并的:每个环境变量取自定义了它的最高优先级源,低优先级源补上高层没设的那些;这一行为需要 v2.1.223 或更新版本,在此之前只应用被选中那个源的整块 env。另外 policyHelper 配置之后会抢在管理层其它源前面:文档写明它输出 managedSettings 时,那份对象就是本次运行唯一的管理层配置,远端、MDM、文件三种源一并被忽略;而它退出码为 0 却没有输出 managedSettings 时,则不贡献任何管理层设置,其它源照常生效。这个键只在 MDM 或系统 managed-settings.json 里被认。
五、和优先级无关、但同样让人以为「改了没生效」的坑
文档《Check common causes》那张表里,有几条纯属位置问题:
~/.claude.json不是~/.claude/settings.json。 文档写明前者存放应用状态与 UI 开关,permissions、hooks、env属于后者。写错文件,全局配的这些会被静默忽略。settings.local.json覆盖settings.json,两者又都覆盖~/.claude/settings.json。 一个settings.json的值看着没生效,先去看同名键是不是也写进了 local。- hook 没有独立文件。 文档写明项目与用户配置里不存在单独的 hooks 文件,hook 要放在 settings 文件的
"hooks"键下;只有 plugin 才加载独立的hooks/hooks.json。 .mcp.json要放在仓库根目录,不是.claude/里面;settings.json也不读mcpServers键。- skill 要放成文件夹:
.claude/skills/name/SKILL.md,而不是.claude/skills/name.md。 - 子目录里的
CLAUDE.md是按需加载的——文档写明它在 Claude 用 Read 工具读取该目录下某个文件时才加载,不是会话启动时,也不是在那里写文件或建文件时。 - 内置的 Explore 与 Plan agent 会跳过
CLAUDE.md;自定义 subagent 才与主对话一样加载它。
还有一条是「规则语义」而非「配置层级」:文档写明 Bash(rm *) 这类前缀规则匹配的是字面命令串,不是底层可执行文件,拦不住 /bin/rm 或 find -delete。要硬保证,文档指向 PreToolUse hook 或 sandbox。
六、Windows 侧要单独看的几处
~/.claude在 Windows 上解析为%USERPROFILE%\.claude。- MDM 策略走注册表:
HKLM\SOFTWARE\Policies\ClaudeCode键下的Settings值(REG_SZ 或 REG_EXPAND_SZ),内容是 JSON;用户级的是HKCU\SOFTWARE\Policies\ClaudeCode,文档标注它是最低的策略优先级,只有在不存在任何管理员级来源时才被使用。 - 文件式 managed settings 的 Windows 路径是
C:\Program Files\ClaudeCode\。旧路径C:\ProgramData\ClaudeCode\managed-settings.json自 v2.1.75 起不再受支持,文档要求把文件迁移过去。如果你的策略至今没生效,这条值得先查。 - WSL 是单独一档:
wslInheritsWindowsSettings只在 Windows managed settings 中有效,置true时 WSL 上的 Claude Code 会在/etc/claude-code之外再读 Windows 策略链,且 Windows 源优先。文档写明它只有设在 HKLM 注册表键或C:\Program Files\ClaudeCode\managed-settings.json里才被认(两者都需要 Windows 管理员权限才能写),要让 HKCU 策略也在 WSL 生效还得在 HKCU 里也设一遍;对原生 Windows 无效。另外server-managed-settings那页把wslInheritsWindowsSettings与policyHelper一起列为「不能通过 server-managed 下发」的键。
七、二分法:先证明问题出在自定义层
前面都定位不到时,文档给了两级「清空对照」。
第一级是 claude --safe-mode:文档写明它启动一个禁用了全部自定义的会话,包括 CLAUDE.md、skills、plugins、hooks、MCP 服务器,以及自定义命令与 agent;认证、模型选择、内置工具与权限照常工作。注意它不是全清——文档明说组织下发的 managed hooks 与 settings policy 在 safe mode 下仍然生效,被关掉的是 managed 的 plugins、skills、CLAUDE.md 与 MCP 服务器。
第二级是换一个空的配置目录:
cd /tmp && CLAUDE_CONFIG_DIR=/tmp/claude-clean claude
这条命令原样来自官方文档:把 CLAUDE_CONFIG_DIR 指向空目录以绕过 ~/.claude 下的一切,并从没有 .claude 文件夹、.mcp.json 与 CLAUDE.md 的目录启动,让项目配置一并跳过。官方文档只给了这一条 bash 形式,没有给 PowerShell 或 cmd 的等价写法,Windows 上要照做需要按你自己 shell 的语法设置同名环境变量与工作目录,这属于通用做法、不是该产品官方文档的内容。
文档还提示了这个干净会话的几个特征:首次启动会出现首次运行的设置流程(从主题选择开始),看到它就说明干净配置目录确实生效了;同一目录再次启动会跳过,因为 onboarding 状态存在那里。另外——组织下发的 managed settings 依旧生效,因为它们位于 ~/.claude 之外的系统路径;在 Linux 与 Windows 上你会被要求重新登录,因为凭据存在配置目录下;macOS 上凭据在 Keychain 里,会带到干净会话。
八、处置之后怎么验证
- 改完 settings 文件,跑
/status。文档写明它会列出Setting sources,逐个列出本次会话加载的层;managed settings 生效时,条目会在括号里标出交付通道,例如(remote)、(plist)、(HKLM)、(HKCU)、(file)。一个来源只有在「至少加载了一个键」之后才会出现在列表里,所以 JSON 写坏的文件根本不会出现——列表里没有它,本身就是信号。 - 要注意
Setting sources的边界:文档明说它只确认哪些来源被读取,不显示每个具体的键是由哪一层提供的。所以「谁覆盖了谁」最终还是得靠前面那个优先级顺序自己推。 - 权限类改动可以用
/permissions看解析后的结果;hook 用/hooks看是否注册。文档写明改settings.json后,正在运行的会话会在一个短暂的文件稳定延迟后应用,不需要重启;若/hooks几秒后还显示旧定义,再跑一次/hooks刷新视图。 - 少数键是启动时读一次的:
model与outputStyle。文档给的做法是用/model中途切换模型,outputStyle属于 system prompt 的一部分,在/clear或重启时重建。这两个键改了当场不变,是文档写明的行为,不是没生效。 - managed 配置改动,文档建议先在测试机上跑
claude doctor验证再全量推。还有一条差异要记住:managed settings 解析是容错的,某一条校验失败会被剥掉、其余继续强制执行;而用户、项目、本地这三类 settings 文件是严格的,整份文件校验不过就整份被拒。所以同一个写法错误,在两边的表现完全不同。
九、什么情况说明不是「优先级」这个原因
这一节最重要:顺着错误方向排查最费时间。
/context里根本找不到你的 memory 文件——那不是被覆盖,是没加载。按文档的《how CLAUDE.md files load》核对位置;如果是子目录里的CLAUDE.md,那是按需加载,属预期行为。/context确认加载了,但 Claude 就是不照做——文档给的判断是:问题更可能出在指令怎么写,而不是有没有加载。文档列举了三种降低遵循度的情况:指令含糊到有多种解释、两个文件给了冲突的方向、文件长到单条规则分不到注意力。这条线上再怎么调优先级都没用。- hook 在
/hooks里能看到,却不触发——文档写明 matcher 是最常见的原因,并列了几种写法错误:matcher写成 JSON 数组(属 schema 错误)、工具名拼错、工具名用了小写(匹配区分大小写,工具名首字母大写:Bash、Edit、Write、Read)。还有一条版本分界:matcher用,作分隔符在 v2.1.191 之前会落到正则求值、永远匹配不上,文档建议用|,例如"Edit|Write"。 - MCP 服务器显示已连接但工具数是 0——文档写明这是启动成功但没返回工具列表,处置是从
/mcp里选 Reconnect;数量仍为 0 就跑claude --debug=mcp,去~/.claude/debug/<session-id>.txt里读该服务器的 stderr。项目级服务器则是另一回事:.mcp.json里的服务器需要一次性批准,批准提示被关掉的话它会一直是禁用状态。 - skill 在
/skills里出现了,但 Claude 从不主动调它——文档给的两个原因是 frontmatter 里有disable-model-invocation: true,或者描述与你提问的措辞对不上;/skills里带 “user-only” 标记的就不会被模型自行触发。 - 在
--safe-mode下问题依然存在——说明原因不在被它关掉的那些自定义面上。此时文档的指引是继续往干净配置目录走;如果在干净会话里也复现,那原因在你的用户与项目配置之外,跑/status看 managed settings 是否在起作用,再查环境变量。
最后补一句关于 CLAUDE.md 边界的原话性质提醒:文档专门用一个 Note 区分了两件事——CLAUDE.md 用来告诉 Claude 你的项目怎么运作,让它做出好的决策;permissions 与 hooks 才是不论 Claude 怎么决策都强制生效的限制。文档给的说法是,「我们这儿是这么做的」用 CLAUDE.md,需要保证而不是指引的安全边界与绝不能发生的事,用 permissions 或 hooks。把安全约束写在 CLAUDE.md 里然后抱怨它不生效,是选错了工具,不是配置层级问题。
本文依据 Claude Code 官方文档(code.claude.com/docs)于 2026-08-17 的公开内容整理。
该产品闭源,本文只复述官方文档写明的机制,不推断其内部实现;
我们没有对文中涉及的功能做过实测,因此不涉及界面外观、操作手感与运行速度的任何描述。
该产品迭代频繁,文中涉及的命令、配置项与默认值随版本变动,请以官方文档最新内容为准。
本文不涉及价格、额度与限流的具体数值,相关信息请以官方定价与用量说明页为准。
安全与合规相关做法请结合自身环境评估,本文不构成安全方案建议。