2343 字
约 7 分钟
20
S24-X05 · settings.json:用户级与项目级配置怎么分工

~/.claude/settings.json 和 .claude/settings.json 名字一样,角色完全不同:前者是你个人的默认值,后者是这个仓库的团队契约。分错地方的代价很具体——规则写到用户级,同事永远拿不到;写到项目级又掺了个人路径,别人一跑就报错。

这篇讲四件事:合并语义、常用键、权限规则怎么写、团队怎么落地,最后附上五个静默失效的坑。


1. 四个来源与合并顺序

优先级 来源 位置 谁改得动
最高 企业管理策略 管理员下发 普通用户不能
高 命令行参数 / 进程环境 启动时 当前用户
中 项目 settings.local.json .claude/ 当前用户,不进 git
中低 项目 settings.json .claude/ 团队,进 git
最低 用户 settings.json ~/.claude/ 当前用户,所有项目

结论和方法论:

  • 越具体越优先:项目覆盖用户,局部覆盖全局。这是"我在用户级改了没用"的第一解释。
  • 用户级放偏好,项目级放契约。反过来就会出现"规则只在我机器上生效"。
  • 企业管理策略是天花板,个人改不动它,这正好用来放"必须遵守"的那几条。

2. 合并语义:别指望两层拼起来

官方描述是"合并,更具体的层级优先"。实际配置时按下面理解最安全:

类型 行为 建议
标量键(model、outputStyle) 高层覆盖低层 只在需要覆盖时写
对象(env、statusLine) 按键合并,同名键覆盖 不同层写不同键,别指望拼接同一键的片段
数组(permissions.allow 等) 倾向叠加 想知道确切结果就实测
# 想知道某一层到底贡献了哪些键,直接看文件本身
jq -S . ~/.claude/settings.json
jq -S . .claude/settings.json
jq -S . .claude/settings.local.json

想验证真实生效结果,最快的方式是改一条能观察到的规则(比如临时加一条 deny),在会话里试触发,比读文档靠得住。数组到底叠加还是覆盖,各版本有调整,按当前版本核对。


3. 常用配置项

键 作用 建议放哪一级
permissions.allow / deny / ask 工具授权规则 项目级放团队规则,用户级放个人习惯
model 默认模型 用户级
env 注入会话环境变量 项目级(非敏感项),密钥走外部
hooks 生命周期钩子 项目级,团队共享
statusLine 状态栏命令与展示 用户级
outputStyle 输出风格 用户级
其他键 —— 以当前版本的设置文档为准,键名会调整
{
  "model": "MODEL_ID",
  "permissions": {
    "allow": ["Bash(pnpm test:*)", "Read(./src/**)"],
    "ask": ["Bash(git commit:*)"],
    "deny": ["Bash(git push --force:*)"]
  },
  "env": { "NODE_ENV": "development" },
  "statusLine": { "type": "command", "command": "~/.claude/status.sh" }
}

写错键名不会报错,只会被忽略——这是 settings 最容易吃亏的地方(见第 8 节)。


4. 权限规则:工具名 + 参数模式

基本形态两种:Tool(整个工具放行/禁止)与 Tool(specifier)(按参数匹配)。

写法 匹配对象 说明
Bash 所有 shell 命令 范围最大,慎用
Bash(npm run test:*) 以该前缀开头的命令 :* 是前缀匹配,不是正则
Read(./src/**) 仓库内路径 * 一层,** 递归
Edit(./docs/**) 可编辑路径 与 Read 分开写
WebFetch(domain:example.com) 域名 不带协议
mcp__server__tool MCP 工具 双下划线分隔

判定顺序要记牢:deny 优先于 allow。同一条命令同时命中 allow 与 deny,结果是拒绝。ask 是中间档——不直接拒,但要你点确认。

场景 写法 效果
只允许跑测试 allow: ["Bash(pnpm test:*)"] 其他 Bash 仍需确认
禁止强推 deny: ["Bash(git push --force:*)"] 直接拦
提交前问一句 ask: ["Bash(git commit:*)"] 每次弹确认
禁止读密钥 deny: ["Read(./.env)", "Read(./**/*.pem)"] 读不到

5. 把危险命令写进 deny

{
  "permissions": {
    "deny": [
      "Bash(rm -rf:*)",
      "Bash(rm -fr:*)",
      "Bash(git push --force:*)",
      "Bash(git push -f:*)",
      "Bash(git reset --hard:*)",
      "Bash(sudo:*)",
      "Bash(chmod 777:*)",
      "Bash(/etc/:*)",
      "Read(./.env)",
      "Read(./**/*.pem)",
      "Read(./**/id_rsa)"
    ]
  }
}

必须清楚这套规则的边界:前缀匹配防的是手滑,不是恶意绕过。rm -rf(两个空格)、/bin/rm -rf、rm -r -f、把命令塞进脚本再执行,都能绕开。所以:

  • 真正的防线是代码评审 + 分支保护 + 备份;
  • deny 的价值在于"让模型在正常路径上不做出格动作",把摩擦放在正确的位置;
  • 需要强隔离时,用容器/受限账号,而不是堆规则。

6. settings.local.json 用在哪

{
  "permissions": {
    "allow": ["Bash(./scripts/dev.sh:*)"]
  },
  "env": { "LOCAL_SDK": "/opt/sdk" }
}

它的三个正当用途:

  1. 本机才有的路径(SDK、工具链、脚本);
  2. 个人额外放行的命令(不想让团队继承你的宽松规则);
  3. 实验性开关(试完就删,别留成"幽灵配置")。

它不该承担的两件事:放密钥(换成环境变量)、放团队规则(别人拿不到等于没有)。


7. 团队统一配置怎么落地

角色 改哪个文件 流程
团队负责人 项目 settings.json 提 PR,说明"为什么加这条 deny/allow"
每个成员 settings.local.json 各自本地,不提交
新人 onboarding 只读项目 settings.json 一句话说明"规则已内置,无需配置"
管理员 企业策略 需要强制执行的合规项

落地五步:

  1. 项目 settings.json 只放团队共识(危险命令 deny、测试命令 allow、hooks);
  2. 个人差异全部下沉到 settings.local.json,并在 .gitignore 里挡住;
  3. PR 里 review 一次 .claude/ 下的改动,和 review 代码一样认真;
  4. 新成员入职跑一次 git status,确认没有 local 文件被带进来;
  5. 规则变更写进提交信息,让"为什么禁止"可追溯。
.claude/settings.local.json

8. 排错:五个静默失效

现象 原因 处理
改了配置完全没反应 JSON 语法错误(尾逗号、注释、中文引号),解析失败被忽略 jq . .claude/settings.json 先验一遍
规则写了但没拦住 键名拼错(如 permission),未知键被忽略 对照当前版本设置文档核对键名
全部命令都免确认 写了 Bash(*) 或 Bash,等于全放行 收窄到具体前缀
路径规则不生效 * 只匹配一层,跨目录要用 **;或路径基准不是仓库根 用 Read(./src/**) 这类显式写法,实测确认
Windows 上规则失效 反斜杠与正斜杠混用 规则里统一用 /
jq . .claude/settings.json          # 语法体检
jq -r '.permissions.deny[]' .claude/settings.json | head

第 1 条最坑:文件坏了不报错,只表现为"配置像没写"。养成改完就 jq 一遍的习惯,能省掉一整轮怀疑。


9. 改动何时生效

改动 生效时机
permissions 规则 新会话生效;会话内以 /permissions 显示为准(按当前版本核对)
model、outputStyle 新会话生效
hooks 新会话生效
env 新会话生效,已启动会话不回溯
claude
> /permissions          # 看当前生效的规则
> /config               # 图形化改一部分设置

改完不确定是否生效,最省事的判断是新开一个会话再看。旧会话不回溯,这是设计不是 bug。


10. 边界:哪些事不该用 settings 解决

需求 更合适的做法 理由
必须人人遵守的合规项 企业管理策略 个人配置改得动
密钥与 token 环境变量 / 密钥管理器 settings 会进 git
复杂流程编排 hooks 或自定义命令 settings 只做授权和默认值
团队文档 README / wiki 配置不是文档
完全隔离的执行环境 容器 / 受限账号 规则匹配总能被绕过
临时一次性放行 会话内确认 写进文件会长期留着

一句话:settings 管"默认信任边界",不管"绝对安全"。


11. 自测

  1. 用户级与项目级都配了 model,最终用哪个?依据是什么?
  2. 一条命令同时命中 allow 与 deny,结果是什么?
  3. Read(./src/*) 与 Read(./src/**) 差在哪?
  4. 改了 deny 规则但当前会话照旧执行,怎么判断是不是没生效?
  5. settings.json 里有个键拼错了,会报错吗?怎么提前发现?
  6. 为什么说 deny 规则"防手滑不防绕过",真正的防线该放在哪?
S24-X05 · settings.json:用户级与项目级配置怎么分工
https://www.clxhxhhr.top/posts/5697/
作者
clxstart
发布于
2024-12-31
许可协议
CC BY-NC-SA 4.0
评论
0 条
还没有评论,先写一条吧。