Claude Code 进阶/settings.json 全局 vs 项目层级
Claude Code 进阶

settings.json 全局 vs 项目层级

理解 Claude Code 的 settings 三层模型(用户级 / 项目级 / local)的合并规则、覆盖优先级与最常踩的坑

难度 215 分钟concept更新于 2026-04-22

内容摘要

Claude Code 的所有配置——能允许哪些工具、敏感目录要不要拦、用哪个模型、要不要挂钩子、要不要自动加 `Co-Authored-By`——最终都汇聚到一个名字叫 `settings.json` 的 JSON 文件里。但这个文件不止一份。Claude Code 把它**沿用户、项目、个人覆盖三层叠起来**,叫法不严格统一,本卡用三个固定的中文称呼:

settings.json 全局 vs 项目层级

基础概念

Claude Code 的所有配置——能允许哪些工具、敏感目录要不要拦、用哪个模型、要不要挂钩子、要不要自动加 Co-Authored-By——最终都汇聚到一个名字叫 settings.json 的 JSON 文件里。但这个文件不止一份。Claude Code 把它沿用户、项目、个人覆盖三层叠起来,叫法不严格统一,本卡用三个固定的中文称呼:

  • 用户级(user / global):跟着你这个人走,所有项目共用。位置 ~/.claude/settings.json
  • 项目级(project / shared):跟着这个仓库走,会进 git,团队所有人共享。位置 <repo>/.claude/settings.json
  • local 级(local / personal):跟着"你 + 这个仓库"走,默认进 .gitignore,只属于你自己这台机器。位置 <repo>/.claude/settings.local.json

在团队 / 企业场景之上,还有一层 企业 managed settings,由 IT 推下来强制生效,普通用户不能改、也不能覆盖;放在 macOS 的 /Library/Application Support/ClaudeCode/managed-settings.json、Linux 的 /etc/claude-code/managed-settings.json、Windows 的 C:\Program Files\ClaudeCode\managed-settings.json(也支持 MDM / 注册表)。本卡聚焦个人/团队最常打交道的那三层,企业 managed 只在"覆盖优先级"那张图里提一下。

为什么要分这么多层?核心动机就一个:让"团队约定"和"个人偏好"互不打架,又能互相补强。比如团队希望所有人都禁止 curl 工具直接访问外网(写在项目级),但你个人喜欢用 iTerm2 + acceptEdits 模式跑得更顺手(写在 local),而你所有项目都希望默认显示中文(写在用户级)。三层叠起来,互相不冲突。

三层叠加的合并方向

正在渲染 Mermaid 图表…

阅读这张图的两条规则:

  1. 从上往下,下面的覆盖上面的。 用户级是地板,local 级是顶(在你能改的范围里),命令行是临时插队,managed 是天花板谁都顶不动。
  2. 不是整份 JSON 互相替换,而是按字段合并。 标量字段(如 model)由高优先级的那层赢;对象字段(如 env)逐键合并;数组字段(如 permissions.allow / permissions.deny)会被拼接 + 去重,不是覆盖。这一点最容易踩坑,单独抽出来在"常见误区"里讲。

核心要素

要素三层各自的位置适合放什么
用户级~/.claude/settings.json跨项目通用偏好:默认 modeloutputStyleincludeCoAuthoredBy、个人想全局放行的 permissions.allow(比如 Bash(ls *)
项目级<repo>/.claude/settings.json团队约定:项目硬性 permissions.deny(拦 .env、拦 curl)、项目的 hooks、绑定的 model、是否自动信任 .mcp.json
local 级<repo>/.claude/settings.local.json个人临时放行:试某个新工具时的一次性 allow、本地特殊路径(Read(/Volumes/...))、个人想覆盖团队默认的 defaultMode
企业 managed/Library/.../managed-settings.json公司硬性策略:白名单模型 availableModels、强制登录方式 forceLoginMethodallowManagedHooksOnly

基础用法

第一步:看清三份文件分别在哪、有没有

# 用户级(全局,所有项目共用)
ls -la ~/.claude/settings.json

# 项目级(要在仓库根目录跑)
ls -la .claude/settings.json

# local 级(同样在仓库根目录)
ls -la .claude/settings.local.json

如果文件不存在很正常——Claude Code 第一次需要写入时会自动创建。.claude/settings.local.json 在被首次创建时,Claude Code 会自动把它追加到项目的 .gitignore,不需要你手动 ignore,但养成检查习惯没坏处:

grep -n "settings.local.json" .gitignore || echo "未找到,建议手动加一行 .claude/settings.local.json"

第二步:查看当前真正生效的配置

进 Claude Code 内部,输入:

/status

/status 会列出所有 settings 来源(包括是否有企业 managed),帮你确认哪一层在生效。要交互式调配置则用:

/config

/config 提供菜单式编辑,所有改动落到对应的 JSON 文件里。

第三步:典型字段配在哪一层

示例 A:用户级(所有项目通用偏好)

// ~/.claude/settings.json
{
  "$schema": "https://json.schemastore.org/claude-code-settings.json",
  "model": "claude-sonnet-4-6",
  "outputStyle": "concise-zh",
  "permissions": {
    "allow": [
      "Bash(ls *)",
      "Bash(cat *)",
      "Read(~/.zshrc)"
    ],
    "defaultMode": "default"
  },
  "attribution": {
    "commit": "Co-Authored-By: Claude <[email protected]>"
  }
}

示例 B:项目级(团队共享,进 git)

// <repo>/.claude/settings.json
{
  "permissions": {
    "deny": [
      "Bash(curl *)",
      "Read(./.env)",
      "Read(./.env.*)",
      "Read(./secrets/**)"
    ],
    "allow": [
      "Bash(npm run lint)",
      "Bash(npm run test *)",
      "Bash(npm run build)"
    ]
  },
  "hooks": {
    "PreToolUse": [
      { "matcher": "Bash", "hooks": [{ "type": "command", "command": "scripts/log-bash.sh" }] }
    ]
  },
  "enabledMcpjsonServers": ["filesystem", "github"]
}

示例 C:local 级(仅你这台机器,不进 git)

// <repo>/.claude/settings.local.json
{
  "permissions": {
    "allow": [
      "Bash(docker compose *)",
      "Read(/Volumes/external-dataset/**)"
    ],
    "defaultMode": "acceptEdits"
  },
  "env": {
    "MY_LOCAL_DEBUG_FLAG": "1"
  }
}

合并以后实际生效:

  • model 取用户级的 claude-sonnet-4-6(项目和 local 都没改)。
  • permissions.deny 完全保留项目级那 4 条(用户和 local 都没写 deny)。
  • permissions.allow = 用户的 3 条 + 项目的 3 条 + local 的 2 条,8 条全部生效,去重之后即是结果
  • defaultMode = local 的 acceptEdits 赢(覆盖了用户级的 default)。
  • env.MY_LOCAL_DEBUG_FLAG=1 生效。

同类工具对比

不同终端 Agent 都有自己的"全局 vs 项目"配置模型。理解差异有助于在多工具切换时不踩坑:

维度Claude CodeCodex CLI(OpenAI)Gemini CLI(Google)Cursor
配置文件名settings.jsonconfig.tomlsettings.json.cursor/rules/*.mdc + Settings UI
用户级路径~/.claude/settings.json~/.codex/config.toml~/.gemini/settings.jsonCursor 应用内 Settings → User Rules
项目级路径<repo>/.claude/settings.json<repo>/.codex/config.toml会向上递归查找<repo>/.gemini/settings.json<repo>/.cursor/rules/*.mdc
个人/local 层settings.local.json(自动 gitignore)⚠️ 只能用 -c 命令行覆盖或额外 profile❌ 没有独立 local 文件❌ 无独立 local 概念
企业/managed 层✅ macOS plist / Linux /etc / Windows 注册表requirements.toml(强约束)+ managed_config.toml(默认值)✅ system overrides 作为最高优先级✅ Team Rules(仅 Team/Enterprise)
数组字段合并行为拼接 + 去重同名键由优先级高的覆盖(按 toml key)数组合并、mcpServers 同名取高优规则文件叠加进 system prompt
项目层是否受信任开关保护❌ 默认信任✅ 项目未 trust 时跳过 .codex/⚠️ 取决于工作区信任⚠️ 取决于工作区信任

核心区别用一句话说:Claude Code 是"个人 / 团队 / 个人覆盖团队"三明治结构,且 local 层默认 gitignore;Codex 没有专门 local 层,靠 profile + -c 替代;Gemini 走"系统覆盖一切"路线,企业管控更强;Cursor 没有标量 settings 合并问题,规则全部叠加进 prompt。

迁移建议:从 Cursor 转 Claude Code 的人最容易把所有规则塞进项目级,忘了 local;从 Codex 转过来的人则容易忽略"数组合并 vs 字段覆盖"这条差异。

常见误区

误区准确理解
以为项目级和用户级是"二选一"——配了项目就不读用户三层一直都在叠加。即便项目级写了 model,用户级里的 outputStyleenvhooks 仍然生效,只是同名字段被项目级覆盖
以为 permissions.allow 在项目级写一遍就会覆盖用户级数组字段是"拼接 + 去重",不是覆盖。要"撤销"用户级的某项 allow,只能用项目级的 permissions.deny,因为 deny > allow
把敏感个人路径(如 Read(/Volumes/work-secrets/**))写到项目级项目级会进 git,团队人手一份。涉及个人本地路径、机器特有目录、临时实验放行,统统写到 settings.local.json
以为 .claude/settings.local.json 必须自己手动 gitignoreClaude Code 在首次创建该文件时会自动追加到 .gitignore。但接手已有仓库时仍建议 grep 一下确认,避免历史 commit 残留
claude config 改完之后找不到改了哪一层没有指定 scope 时默认改用户级。要指定具体层,需要直接编辑文件,或在 /config 菜单里看清"Source"列。/status 是排错神器
把 hooks 写到 local 级,期望队友也能用local 不进 git,队友拉不到。团队级 hooks 必须写项目级 .claude/settings.json,local 只用来个人临时挂钩
以为修改用户级 ~/.claude/settings.json 立刻全局生效Claude Code 进程启动时读取一次,热重载支持有限。改完关键字段(permissions / hooks / model)建议重启 Claude Code 或重新进入 session
把企业 managed 当成"高级用户级"managed 是强制天花板,普通 settings 改不动。如果 IT 在 managed 里写了 availableModels: ["claude-haiku-4-5"],你在用户级写 model: "claude-opus-4-7" 也启动不了

优劣势分析

优势劣势
三层结构刚好对应"个人 / 团队 / 例外",覆盖了真实协作场景三层都可能有同名字段,新手容易迷失"现在到底哪层在生效",需要 /status 才能确认
数组拼接 + 去重的合并策略,让团队和个人各加各的 allow,互不删除对方数组合并机制不直观——想"用项目级关掉用户级的某条 allow"做不到,只能 deny 反制
settings.local.json 自动 gitignore,避免最常见的"个人路径泄露到 git"事故自动追加 .gitignore 只在首次创建时执行,接手历史仓库要自己检查
企业 managed 层支持 MDM/plist/注册表/远程下发,大企业可以做到强治理企业 managed 一旦覆盖,普通用户完全无法看到自己被加了什么策略,排错全靠 /status
JSON Schema 已上线https://json.schemastore.org/claude-code-settings.json),编辑器有补全和校验settings 字段在快速演进,includeCoAuthoredBy 已被 attribution 替代,跟不上版本就会写错配置
跨项目偏好(用户级)和项目约定(项目级)独立演进,切项目时模型/语言不会被重置local 级不会自动同步到任何地方,换电脑要手动迁移

思考题

初级:项目级里写了 `permissions.allow: ["Bash(npm run *)"]`,但我作为团队的一员,这台机器上已经在用户级写了 `permissions.allow: ["Bash(npm run lint)"]`,那进入这个项目以后,我能跑 `npm run test` 吗?

参考答案:

能。数组字段是合并不是覆盖,所以最终生效的 permissions.allow 是:

["Bash(npm run lint)",  // 来自用户级
 "Bash(npm run *)"]     // 来自项目级

通配符 Bash(npm run *) 已经包含了 npm run test,所以放行。

需要警惕的反向场景:如果项目级写了 permissions.deny: ["Bash(curl *)"],而你在用户级写了 permissions.allow: ["Bash(curl *)"]deny 永远赢 allow,所以你这台机器上的 curl 仍然会被拦——这就是为什么团队约定优先放在 deny 而不是删 allow

中级:团队规定所有人都不能让 Agent 自动 push 到 main,但我个人做了一个发布机器人,需要在某个特定仓库下放行 `Bash(git push origin main)`,最佳实践是把这条规则放在哪一层?为什么不能放用户级?

参考答案:

最佳实践:放在该仓库的 .claude/settings.local.json。理由有三层:

  1. 不能放用户级。用户级会污染你所有项目——只要你在任何仓库打开 Claude Code,git push origin main 都会被放行,等于绕过了团队约定在所有项目上的兜底。
  2. 不能放项目级。项目级会进 git,等于把你的"个人例外"推给了团队所有人,违背团队规则。
  3. local 级正好合适:仅你这台机器、仅这个仓库、不进 git。即便如此还要再叠一层保护——团队的项目级 .claude/settings.json 通常会写 permissions.deny: ["Bash(git push origin main)"],而 deny 优先级高于 allow,所以 local 级的 allow 反而会被项目级 deny 压住。

正确做法是和团队沟通后,在项目级用更细粒度的规则,比如:

// 项目级 deny 改为更精确的形式,给"机器人 user 名"开一个口子
{
  "permissions": {
    "deny": ["Bash(git push origin main)"],
    "allow": ["Bash(GIT_AUTHOR_NAME=release-bot git push origin main)"]
  }
}

或者使用 hooks 在 PreToolUse 阶段动态判断,这部分见 /cli/cards/lifecycle-hooks

结论一句话:local 级解决"我个人例外",但当例外和团队 deny 冲突时,必须回到项目级用更精确的 allow 规则,而不是去 local 里偷偷绕过。

参考资料

  1. Claude Code 官方 settings 文档:https://code.claude.com/docs/en/settings(查询日期 2026-04-22)
  2. Claude Code 官方 IAM / 权限文档:https://code.claude.com/docs/en/iam(查询日期 2026-04-22)
  3. Claude Code GitHub Issue #18964 - settings 与 memory 优先级一致性讨论:https://github.com/anthropics/claude-code/issues/18964(查询日期 2026-04-22)
  4. eesel AI - Claude Code settings.json 完整指南(2026 版):https://www.eesel.ai/blog/settings-json-claude-code(查询日期 2026-04-22)
  5. Egghead - Organizing Personal and Project Settings in Claude Code:https://egghead.io/organizing-personal-and-project-settings-in-claude-code~q7qsw(查询日期 2026-04-22)
  6. Codex CLI 配置参考(用于横向对比):https://developers.openai.com/codex/config-reference(查询日期 2026-04-22)
  7. Gemini CLI 配置参考(用于横向对比):https://geminicli.com/docs/reference/configuration/(查询日期 2026-04-22)
  8. Cursor Rules 官方文档(用于横向对比):https://cursor.com/docs/context/rules(查询日期 2026-04-22)

延伸阅读

优先展示同分类且标签更接近的内容,方便继续串联学习。

Claude Code 进阶难度 219 分钟实践
01

在 CLI Agent 里挂 MCP server

在终端 Agent 里挂 MCP server 的两种方式 —— claude mcp add 命令 vs settings.json 配置文件,含 stdio 与远程 server 的踩坑要点

MCPClaude Codeclaude mcp add配置集成
更新于 2026-04-22configure-mcp-in-cli
Claude Code 进阶难度 314 分钟模式
02

用 CLI Agent 跑 TDD 工作流

用 CLI Agent 跑"红 - 绿 - 重构"循环:先写测试 → 让 Agent 写实现 → 自动跑测试 → 验证通过 → 重构的完整工作流

TDD测试驱动工作流Claude Code质量
更新于 2026-04-22tdd-with-cli-agent
Claude Code 进阶难度 217 分钟工具
03

Claude Code 入门

Anthropic 官方终端 Agent,原生支持工具调用、MCP、Skills 与 Hooks,2026 年生态最完整的 CLI Agent

Claude CodeAnthropic终端 AgentCLI入门
更新于 2026-04-22claude-code-overview