Claude Code 的四层配置:settings.json 放什么、.claude.json 放什么、谁覆盖谁
配置文件有四个作用域,加上命令行参数一共五级。从高到低:managed(企业管理策略)、命令行参数、.claude/settings.local.json、.claude/settings.json、~/.claude/settings.json。managed 层压过一切,包括命令行参数。
标量值(字符串、布尔、数字)按这个顺序覆盖;数组值(如 permissions.allow)跨层拼接去重,不覆盖。这个区别是配置调试里最容易踩的一处:以为项目层的 deny 规则会替换用户层的,实际是两边的规则都在生效。
settings.json 和 .claude.json 是两个不同的文件,职责不重叠。往错的那个文件里写 key,Claude Code 启动时静默忽略,不报错。
五级优先级,以及为什么 managed 压过命令行
Section titled “五级优先级,以及为什么 managed 压过命令行”优先级从高到低:
| 级别 | 位置 | 谁能改 |
|---|---|---|
| managed | 服务端下发 / MDM 策略 / 系统目录下的 managed-settings.json | IT 管理员 |
| 命令行参数 | --settings <file-or-json>、--permission-mode 等 | 当前这次会话 |
| local | 仓库根的 .claude/settings.local.json | 你自己,仅这个仓库 |
| project | .claude/settings.json | 提交进 git,全团队共享 |
| user | ~/.claude/settings.json | 你自己,所有项目 |
命令行参数通常是优先级最高的,这里不是。managed 层的定位是「组织策略不可绕过」,所以它必须压过 --settings,否则任何人加一个命令行参数就能解掉安全策略。
managed 层在不同平台的落地位置不同:
- macOS:
/Library/Application Support/ClaudeCode/managed-settings.json - Linux 和 WSL:
/etc/claude-code/managed-settings.json - Windows:
C:\Program Files\ClaudeCode\managed-settings.json
Windows 上的旧路径 C:\ProgramData\ClaudeCode\managed-settings.json 自 v2.1.75 起不再被读取。如果之前部署在那里,需要迁移。
标量覆盖,数组合并
Section titled “标量覆盖,数组合并”这是配置调试里最常被误解的一条。
标量值按优先级覆盖。用户设置里 spinnerTipsEnabled 是 true、项目设置里是 false,最终生效的是 false(项目层优先级更高)。
数组值跨层拼接去重。managed 层把 sandbox.filesystem.allowWrite 设成 ["/opt/company-tools"],你在用户层加了 ["~/.kube"],最终两个路径都在。低优先级的层可以往数组里添加条目,不会被高优先级层清空。
权限规则也走合并这条路。所以「项目层写了 permissions.deny,就能覆盖掉用户层的 deny」这个预期是错的:两边的 deny 规则都在生效,实际拦截范围是并集。
两个数组字段是例外,不参与合并:
fallbackModel:这是一条有顺序含义的链,位置本身携带信息。定义它的最高优先级文件提供整条链的值。availableModels:最高优先级的 managed 源定义它时,那份列表原样生效,用户 / 项目 / local 层的条目无法扩展它。非 managed 的几层之间照常合并。
settings.json 与 .claude.json 的分工
Section titled “settings.json 与 .claude.json 的分工”settings.json 是行为配置文件:env、permissions、hooks、model、statusLine 这些都写在这里。
~/.claude.json 是 CLI 自身维护的状态文件,内容包括:
- OAuth 会话(登录态)
- MCP 服务器的 local scope 和 user scope 配置
- 每个项目的状态:已批准的工具、workspace 信任记录
- 各类缓存
project scope 的 MCP 服务器不在这里,单独放在项目根的 .mcp.json。
有一组 key 只认 ~/.claude.json,写进 settings.json 会被静默忽略:
| key | 作用 |
|---|---|
autoConnectIde | 从外部终端启动时是否自动连接正在运行的 IDE |
autoInstallIdeExtension | 在 VS Code 终端里运行时是否自动装 IDE 扩展 |
diffTool | 连了 IDE 时 diff 显示在哪:auto 走 IDE 的 diff 视图,terminal 留在终端 |
externalEditorContext | 用 Ctrl+G 打开外部编辑器时,是否把上一条回复作为 # 注释带进去 |
permissionExplainerEnabled | Bash 权限提示上按 Ctrl+E 时是否给出命令解释 |
teammateDefaultModel | agent team 里 teammate 的默认模型 |
v2.1.119 之前,一批 /config 偏好项也存在 ~/.claude.json 而非 settings.json 里,包括 theme、verbose、editorMode、autoCompactEnabled、preferredNotifChannel。跨版本抄配置片段时这是一个容易踩的差异点。
改完配置怎么确认它生效了
Section titled “改完配置怎么确认它生效了”配置改完不要靠「行为看起来对了」来判断,因为同一个行为可能由别的层决定。跑一次会话后执行:
/statusStatus 标签页里有一行 Setting sources,列出当前会话加载的每一层来源,例如 User settings、Project local settings。managed 层会额外标出下发渠道,形如 Enterprise managed settings (remote)、(plist)、(HKLM)、(HKCU)、(file)。
这一行有两个限制要知道:
- 只有「已加载且至少含一个 key」的来源才会出现。JSON 语法坏掉的文件不出现在列表里,即使它有内容。所以某一层没出现,第一件事是查那个文件的 JSON 是否合法。
- 它只告诉你哪些来源被读了,不告诉你某一个具体 key 最终由哪一层提供。
要看每一条错误的细节,用:
claude doctor大多数 key 改完立即生效,两个例外
Section titled “大多数 key 改完立即生效,两个例外”Claude Code 监听设置文件,改动后会重载,多数 key 不需要重启会话。permissions、hooks、apiKeyHelper 这些都在重载范围内,user / project / local / managed 四层都监听。每检测到一次改动,ConfigChange hook 会触发一次。
两个 key 是启动时读一次的:
model:会话中途要换模型用/modeloutputStyle:它属于系统提示的一部分,系统提示只在/clear或重启时重建
一个容易误判的场景:defaultMode: auto 不生效
Section titled “一个容易误判的场景:defaultMode: auto 不生效”在 .claude/settings.json 或 .claude/settings.local.json 里写 "permissions": {"defaultMode": "auto"},会话仍然以 default 模式启动,而且不报错。
这不是 bug。Claude Code v2.1.142 及以后版本会忽略来自项目层和 local 层的 auto 值,避免一个仓库通过提交配置文件的方式给自己授予 auto mode。要让它生效,把这一项移到 ~/.claude/settings.json。
同类的「按来源忽略」规则还有几处,都是同一个防御思路,防止克隆下来的仓库通过自带配置提权:
| 字段 | 忽略哪些来源 |
|---|---|
permissions.defaultMode: "auto" | 项目、local |
autoMode(分类器规则) | 项目、local |
pluginConfigs | 项目、local |
footerLinksRegexes | 项目、local |
vimInsertModeRemaps | 项目、local |
skipDangerousModePermissionPrompt | 项目 |
enableArtifact | 项目、local |
判断方法一致:这个字段一旦被仓库自带的配置控制,会不会让仓库获得它本不该有的权限或对你的输入 / 凭据的影响力。会,就只从用户层和 managed 层读。
让编辑器帮你校验
Section titled “让编辑器帮你校验”在 settings.json 顶部加一行 $schema,VS Code、Cursor 这类支持 JSON schema 的编辑器就能给出补全和内联校验:
{ "$schema": "https://json.schemastore.org/claude-code-settings.json", "permissions": { "allow": ["Bash(npm run lint)"], "deny": ["Read(./.env)", "Read(./secrets/**)"] }}这份公开 schema 是定期更新的,可能不包含最近几个版本新加的字段。所以一个刚出现在文档里的字段被编辑器标黄,不代表配置真的无效,对照官方文档确认即可。
- 在用户层和项目层各写一条
permissions.deny,然后跑/permissions看列表里是不是两条都在。这能直接验证「数组合并」而不是覆盖。 - 故意把
.claude/settings.json的 JSON 写坏(少一个逗号),看/status的Setting sources里这一层会不会消失,再用claude doctor看它报的是什么。
还没确认的点
Section titled “还没确认的点”~/.claude.json的完整字段结构。官方文档说明了它的角色和几个 key,没有逐条列出全部字段。本文列的 key 来自官方 settings 文档的 Global config settings 一节,不代表这就是全部。- 配置文件的自动备份机制。文档提到 Claude Code 会创建带时间戳的备份并保留最近五份,具体的备份文件命名和位置没有查到明确说明。
- 各版本之间 key 归属的迁移细节。只核实到 v2.1.119 这一次变化,更早的版本没有跟踪。