跳转至

配置调试

本文你会学到

  • 如何使用内置诊断命令确认配置是否真正加载
  • settings.json 多层级冲突的排查思路
  • CLAUDE.md 加载顺序导致指令不生效的解决方案
  • 权限规则、MCP 服务器、环境变量不生效的常见原因
  • 通过具体案例掌握配置冲突的排查方法

为什么配置会"不生效"?

你写好了 CLAUDE.md,配好了权限规则,启动 Claude Code 后却发现——它完全没按你的指令来。这种情况几乎每个 Claude Code 用户都遇到过,原因通常不是软件有 bug,而是**配置文件没有被加载、从你预期之外的位置加载,或者被另一个配置覆盖了**。

好消息是,Claude Code 提供了一组内置诊断命令,能让你精确看到每个配置的加载状态。掌握这些工具,绝大多数配置问题都能在几分钟内定位。

配置调试的七个核心命令

当你发现配置不生效时,第一步不是改配置文件,而是**先用诊断命令确认当前状态**。

命令 用途 典型场景
/context 查看当前上下文窗口中加载的所有内容 CLAUDE.md 指令是否被加载
/memory 查看加载了哪些 CLAUDE.md 和规则文件 排查记忆文件遗漏
/status 查看活跃的设置源和托管设置状态 确认配置层级优先级
/permissions 查看当前生效的允许和拒绝规则 权限规则不生效
/doctor 检测配置文件中的无效键和 schema 错误 配置文件有语法问题
/hooks 查看当前会话注册的所有 Hook Hook 不触发
/mcp 查看 MCP 服务器连接状态 MCP 工具不可用

诊断原则:先用命令确认现象,再根据现象定位原因,最后修改配置。不要凭猜测改配置,否则可能越改越乱。

settings.json 冲突和优先级问题

症状

你在某个 settings.json 中设置了配置项,但 Claude Code 的行为完全不符合预期。比如你允许了某个 Bash 命令,它仍然弹出权限提示。

诊断步骤

运行 /status 查看当前活跃的设置源。Claude Code 的配置优先级从高到低依次为:

优先级 层级 文件位置 说明
1(最高) Managed(托管) 系统管理员配置 组织级强制策略,不可被下级覆盖
2 CLI 参数 启动命令 单次会话的临时覆盖
3 Local(本地) .claude/settings.local.json 个人偏好,不提交 git
4 Project(项目) .claude/settings.json 团队规范,提交 git 共享
5(最低) User(用户) ~/.claude/settings.json 全局个人偏好

当多个层级对同一个键设置了不同的值时,高优先级的值会静默覆盖低优先级的值,不会给出任何警告。

运行 /doctor 检查配置文件中是否存在无效键或 schema 错误。

解决方案

  • 确认你的修改在正确的文件中:检查 /status 输出的活跃设置源列表
  • 注意 settings.local.json 会覆盖 settings.json:如果你在项目 settings.json 中设置了某个值,但 settings.local.json 中也有同名的键,后者的值会生效
  • 不要把配置放到 ~/.claude.json~/.claude.json 保存的是应用状态和 UI 切换,permissionshooksenv 应放在 ~/.claude/settings.json 中,这是两个不同的文件
  • 检查是否有托管设置:组织管理员可以通过 Managed 层强制覆盖你的配置,运行 /status 确认托管设置是否启用

CLAUDE.md 加载顺序问题

症状

你修改了 CLAUDE.md 中的某条指令,但 Claude 的行为没有变化。或者你在某个子目录下新建了 CLAUDE.md,里面的规则完全没起作用。

诊断步骤

运行 /memory 查看当前会话加载了哪些 CLAUDE.md 文件。如果文件不在列表中,说明它没有被加载。

解决方案

子目录 CLAUDE.md 是按需加载的,而不是在会话启动时加载。 它们只在 Claude 使用 Read 工具读取该目录中的文件时才会被加载,在启动时、写入文件时或创建文件时都不会加载。

如果你希望某条指令在会话开始时就生效,必须将其放在项目根目录或 ~/.claude/CLAUDE.md 中。

如果 /memory 确认文件已加载,但 Claude 仍然不遵循特定指令,问题可能出在指令的编写方式上:

  • 指令太模糊:当指令有多种解释方式时,Claude 可能选择了你预期之外的解读
  • 文件间存在矛盾:两个 CLAUDE.md 对同一件事给出了相反的指导
  • 文件过长导致注意力稀释:单个 CLAUDE.md 文件越长,每条规则被遵守的概率越低

CLAUDE.md 和权限解决的是不同的问题。CLAUDE.md 告诉 Claude 你的项目如何工作,让它做出好的决定。权限和 Hook 则无论 Claude 做什么决定都强制执行限制。对于"我们这里这样做"的规范,使用 CLAUDE.md;对于安全边界和任何必须永远不会发生的事情,使用权限或 Hook。

权限规则不生效

症状

你在 settings.json 中配置了 permissions.deny 拒绝某个命令,但 Claude 仍然能够执行它。或者你配置了 permissions.allow,但还是收到权限提示。

诊断步骤

运行 /permissions 查看当前实际生效的允许和拒绝规则,确认你的规则是否出现在最终解析结果中。

解决方案

前缀规则只匹配字面命令字符串,不匹配底层可执行文件。 例如 Bash(rm *) 只会匹配以 rm 开头的命令,不会匹配 /bin/rmfind -delete。如果需要拦截底层可执行文件,需要为每个变体添加显式模式,或者使用 PreToolUse Hook 来获得更可靠的拦截。

检查权限模式的匹配语法

  • Bash(npm run lint) — 精确匹配 npm run lint
  • Bash(npm run *)* 通配符匹配任意字符序列
  • Bash(curl *) — 匹配所有以 curl 开头的命令
  • Read(./.env) — 匹配 .env 文件的读取
  • Read(./secrets/**) — 递归匹配 secrets/ 下所有文件

注意范围覆盖:如果你在用户级 settings.json 中允许了某个操作,但在项目级 settings.json 中拒绝了它,项目级的拒绝规则会生效(项目级优先级高于用户级)。

MCP 服务器连接失败

症状

你在 .mcp.json 中配置了 MCP 服务器,但 /mcp 显示服务器状态异常,或者工具列表为空。

诊断步骤

运行 /mcp 查看每个服务器的连接状态和工具数量。根据状态不同,排查方向也不同:

解决方案

服务器显示为"失败":最常见的 cause 是 commandargs 中使用了相对路径。.mcp.json 中的相对路径是相对于你启动 Claude Code 的当前工作目录解析的,而不是相对于 .mcp.json 文件的位置。解决方法是使用绝对路径,或者确保使用的是 PATH 上的可执行文件(如 npxuvx)。

服务器已连接但工具数量为零:服务器成功启动但没有返回工具列表。从 /mcp 选择"重新连接"。如果工具数量仍然为零,运行 claude --debug mcp 查看服务器的 stderr 输出,定位服务端问题。

服务器完全不出现

  • 确认 .mcp.json 在存储库根目录下,而不是在 .claude/ 目录内
  • 项目级 MCP 服务器需要一次性批准,如果批准提示被关闭,服务器会保持禁用状态,运行 /mcp 手动批准

服务器启动时缺少环境变量settings.json 中的 env 配置不会传播到 MCP 子进程。如果 MCP 服务器需要特定环境变量,必须在 .mcp.json 中为该服务器单独设置 env 字段。

环境变量不生效

症状

你设置了环境变量,但在 Claude Code 会话中或 MCP 服务器中读取不到。

诊断步骤

在 Claude Code 会话中运行 Bash 工具执行 echo $VAR_NAMEenv | grep VAR_NAME,确认变量是否在 Claude Code 的进程环境中可用。

解决方案

环境变量的设置位置决定了它的作用域

  • Shell 环境变量(在 .bashrc.zshrc 或系统环境变量中设置):对 Claude Code 进程本身可用,也会被 Bash 工具执行的命令继承
  • settings.json 中的 env:只影响 Claude Code 自身的行为,不会传播到 MCP 子进程
  • .mcp.json 中的 env:只影响对应的 MCP 服务器进程

如果你的目的是让 MCP 服务器使用某个环境变量(比如 API Key),必须在 .mcp.json 的服务器配置中设置,而不是在 settings.json 中。

CLI 参数和环境变量的覆盖顺序:某些设置也可以通过命令行标志或环境变量设置,它们作为额外的覆盖层生效。当 settings.json 中的值似乎被忽略时,检查是否有同名的环境变量或 CLI 参数在覆盖它。

托管设置与本地设置冲突

症状

你修改了配置,但行为始终不符合预期,无论怎么改都没有效果。运行 /status 发现托管设置处于启用状态。

诊断步骤

运行 /status 查看是否启用了托管设置。托管设置由组织管理员控制,优先级最高,不能被任何下级配置覆盖。

解决方案

如果你是普通开发者:托管设置是组织的安全策略,你无法覆盖它。如果某些配置与你的工作流冲突,需要联系组织管理员调整托管设置。

如果你是组织管理员:托管配置支持两种方式:

  • JSON 文件:在管理员指定的路径下放置 managed-settings.json
  • 分片配置目录(v2.1.83 新增):使用 managed-settings.d/ 目录,将配置拆分成多个文件,便于管理和分发

分片配置目录的结构示例:

1
2
3
4
/etc/claude-code/managed-settings.d/
├── 01-permissions.json     # 权限策略
├── 02-env.json             # 环境变量
└── 03-mcp-servers.json     # MCP 服务器配置

每个 JSON 文件包含完整的 managed-settings 结构中对应的部分,Claude Code 会按文件名排序依次加载并合并。

修改托管配置后,运行 /doctor 验证配置格式是否正确。

配置调试的方法论

从症状到根因

面对配置问题,按以下顺序排查:

  • 第一步,确认加载状态:运行 /memory/status/mcp/hooks/permissions,确认你期望加载的配置是否真的出现在当前会话中
  • 第二步,检查优先级覆盖:如果配置已加载但行为不符预期,检查是否有更高优先级的配置在覆盖它
  • 第三步,验证语法正确性:运行 /doctor 检查 JSON schema 错误、无效键值
  • 第四步,查看详细日志:对于难以复现的问题,使用 claude --debug hooksclaude --debug mcp 启动调试模式,查看实时日志

常见误区

误区 事实
"配置改了应该立即生效" settings.json 的编辑在短暂的文件稳定延迟后生效,不需要重启。但 CLAUDE.md 的变更需要新会话才能生效
"~/.claude.json 就是全局配置" ~/.claude.json 保存的是应用状态,不是配置。全局配置在 ~/.claude/settings.json
"子目录 CLAUDE.md 启动时就加载" 子目录 CLAUDE.md 只在 Claude 读取该目录文件时按需加载
"权限规则能拦截所有执行方式" 前缀规则只匹配字面命令字符串,不匹配底层可执行文件的别名或间接调用
"settings.json 中的 env 对 MCP 服务器有效" settings.jsonenv 不会传播到 MCP 子进程,必须在 .mcp.json 中单独设置

子代理配置不继承项目记忆

如果你发现子代理(sub-agent)忽略了 CLAUDE.md 中的某些指令,这是因为子代理不总是继承项目记忆。解决方法是将关键规则放在代理配置文件的文件体中,它会成为子代理的系统提示,确保每次调用都能读取到。

例如,在 .claude/commands/my-agent.md 中:

.claude/commands/my-agent.md
1
2
3
4
5
6
7
8
你是一个专注于代码审查的助手。

规则:
- 所有输出必须使用中文
- 检查每个函数是否有 JSDoc 注释
- 安全敏感代码必须标记提醒

请审查以下代码变更。