
1. 为什么你的 Claude Code 总在关键时刻弹确认框Claude Code 权限系统是一套围绕settings.json展开的访问控制机制它决定了 Claude 在读写文件、执行 Shell、访问网络时是直接放行、弹窗询问还是干脆拒绝。如果你刚把 Claude Code 接进日常开发流大概率遇到过这种场景让它跑一遍测试它先问你「是否允许执行 pytest」让它改个配置文件它又停下来等你点确认。一天下来确认框点了上百次效率反而被拖慢。问题不在于 Claude Code 太谨慎而在于默认权限模式是default——每一次文件修改、每一条 Bash 命令都要人工确认。这套设计对陌生代码库是保护对天天打交道的项目就是噪音。真正要做的是把「哪些操作可以放心自动放行、哪些必须拦下来」这件事用配置固化下来而不是靠每次手点。这篇聚焦 Claude Code 权限系统的落地从settings.json的权限模式与沙盒模式入手梳理工具调用白名单、目录访问边界与审批策略。我会给出可直接复制的配置片段并用一次越权读写和一次正常调用做对照验证让你在本地和 CI 里都能稳定复现权限行为。适合已经装好 Claude Code、想把它从「玩具」变成「团队工具」的开发者。先明确一个认知权限系统不是一道墙而是三层防线。第一层是权限模式决定默认行为是问还是不问第二层是工具权限规则用 allow/ask/deny 精确控制每个工具第三层是沙盒模式在操作系统层面兜底。三层配合才能既少打断、又不失控。2. 五层配置层级与权限模式settings.json 到底谁说了算Claude Code 的settings.json遵循严格的五层优先级体系优先级从高到低依次是Managed/etc/claude-code/managed-settings.json企业 IT 下发开发者无法绕过、命令行参数当前会话临时覆盖、Local.claude/settings.local.json个人项目覆盖自动 gitignore、Project.claude/settings.json团队共享提交 git、User~/.claude/settings.json个人全局。核心规则只有一条高优先级永远覆盖低优先级而 deny 规则尤其强硬——任何层级的 deny 都无法被更低层级的 allow 覆盖。这意味着团队可以在 Project 层写死「禁止读取 .env」即便某个成员在 User 层写了 allow也照样被拦。每一层该放什么我建议这样分工Managed 放企业安全策略比如禁用危险 Shell、禁止访问密钥文件命令行参数用于一次性测试Local 放本机特定路径和个人偏好Project 放团队共识比如允许哪些测试命令、禁止直接 push mainUser 放你所有项目的个人默认值。权限模式由permissions.defaultMode控制三种取值行为差异很大。default每次操作都询问最安全但最打断acceptEdits文件编辑无需确认、Bash 命令仍询问这是大多数日常开发的合理选择bypassPermissions跳过所有确认只应在完全受控的 CI 环境使用。如果企业要禁止任何人开启 bypass可以在 Managed 层写disableBypassPermissionsMode: disable。{ permissions: { defaultMode: acceptEdits } }工具权限规则用 allow、ask、deny 三个列表控制具体行为评估顺序是 deny 优先然后 ask最后 allow第一个匹配的规则生效。语法上Bash匹配所有 Bash 调用Bash(git *)只匹配 git 开头的命令Read(./.env)只匹配读取 .envRead(./secrets/**)匹配 secrets 目录下所有文件WebFetch(domain:x.com)只允许访问特定域名。{ permissions: { allow: [ Bash(git status), Bash(git diff *), Bash(uv run pytest *), Bash(ruff *) ], ask: [ Bash(git push *) ], deny: [ Read(./.env), Read(./.env.*), Bash(rm -rf *), Bash(sudo *), WebFetch ] } }这段配置的效果是常用 git 只读命令和 Python 工具链自动放行push 前仍询问危险命令和密钥文件全部拒绝。注意 deny 里同时写了Read(./.env)和Read(./.env.*)后者覆盖.env.local、.env.production这类变体只写一条会漏。3. 可复制配置沙盒模式与工具白名单的完整 settings.json沙盒模式是权限系统里最容易被忽略的一层。权限规则控制「Claude 被允许做什么」沙盒控制的是「操作系统层面实际能访问什么」。它通过 macOS 的 Sandbox 或 Linux/WSL2 的 Landlock 在内核层面隔离 Bash 命令即便规则配置写错了沙盒也能兜底。{ sandbox: { enabled: true, network: { allowedDomains: [github.com, *.pypi.org, *.githubusercontent.com], allowLocalBinding: true }, excludedCommands: [git, docker], autoAllowBashIfSandboxed: true } }逐项说明enabled开启沙盒network.allowedDomains是出站域名白名单不在名单里的网络请求会被拦allowLocalBinding允许绑定 localhostmacOS 上跑开发服务器必须开excludedCommands里的命令在沙盒外运行适合 git、docker 这类需要访问主机网络的工具autoAllowBashIfSandboxed让沙盒内的 Bash 命令自动批准不再弹确认——这是减少打断的关键开关。如果你在 Docker 里跑 Claude CodeLinux/WSL2 上开启沙盒需要额外加enableWeakerNestedSandbox: true否则嵌套沙盒会失败。下面是一份可以直接落地的项目级配置放在.claude/settings.json提交给团队{ permissions: { defaultMode: acceptEdits, allow: [ Bash(git status), Bash(git diff *), Bash(git log *), Bash(git add *), Bash(git commit *), Bash(uv *), Bash(ruff *), Bash(mypy *), Bash(pytest *), Bash(python -m *) ], ask: [ Bash(git push *), Bash(git merge *) ], deny: [ Read(./.env), Read(./.env.*), Write(./production.config.*), Bash(sudo *), Bash(rm -rf *) ], additionalDirectories: [../shared-lib, ../docs] }, env: { PYTHONPATH: ./src, ENVIRONMENT: development, BASH_DEFAULT_TIMEOUT_MS: 30000 }, sandbox: { enabled: true, network: { allowedDomains: [*.pypi.org, github.com], allowLocalBinding: true }, autoAllowBashIfSandboxed: true } }additionalDirectories允许 Claude 访问项目目录之外的路径Monorepo 和跨仓库场景常用。env里的键值对会在每个会话启动时自动注入不用改 shell 配置。如果你要把 Claude Code 接入第三方模型网关来统一管理 Key 和额度可以在环境变量里指定 Base URL 和 Key模型 ID 用claude-sonnet-4-5这类标识。TaoToken 的接入文档在 https://taotoken.net/api 有完整说明API Key 在 https://taotoken.net/api-keys 申请。配置时三件套要写全Base URL、Key、Model ID缺一个都会报 401。4. 验证请求一次越权读写与一次正常调用的对照配置写完必须验证否则你不知道规则到底生效没有。我设计了两组对照实验你可以直接复现。第一组越权读写测试。在项目根目录放一个.env文件内容随便写个SECRETtest。然后启动 Claude Code让它执行「读取 .env 文件内容」。因为 deny 里有Read(./.env)预期结果是直接被拒绝Claude 会告诉你该操作被权限规则拦截。如果它真的读出来了说明你的 deny 规则没生效检查是不是写在了被更高优先级覆盖的层级或者路径写法不对。第二组正常调用测试。让 Claude 执行「运行 git status 并总结当前改动」。因为 allow 里有Bash(git status)预期结果是直接执行、不弹确认框。如果它还是问你说明defaultMode没设成acceptEdits或者这条规则被某个 ask/deny 覆盖了。验证沙盒是否生效可以让 Claude 执行一条访问未在白名单里的域名的命令比如curl https://example.com。沙盒开启且域名不在allowedDomains里时请求会被内核层拦截。反过来curl https://github.com应该能通。查看当前生效的完整配置用/config命令。在界面里能看到所有层级的配置汇总以及每一条规则最终判定是 allow 还是 deny。这是排查「为什么这条规则没生效」最快的方式。如果你在 CI 里跑建议用命令行参数临时覆盖不写文件claude -p 运行测试并修复失败用例 \ --permission-mode bypassPermissions \ --allowedTools Read,Grep,Glob,Bash(uv run pytest *)--permission-mode bypassPermissions跳过所有确认--allowedTools限定当前会话只允许这些工具。CI 环境完全无人值守bypass 是合理的但一定要配合沙盒限制网络范围避免数据泄露。5. 常见报错排查401、local proxy failed 与 reading choices权限配置过程中有几类报错特别高频我按实际遇到的顺序整理。401 Unauthorized。这通常不是权限规则的问题而是模型接入的鉴权失败。检查三件套Base URL 是否写对注意结尾不要多斜杠、API Key 是否有效、Model ID 是否拼写正确。如果你用的是第三方网关确认 Key 是在对应平台申请的而不是混用了别家的。TaoToken 的 Key 在 https://taotoken.net/api-keys 管理接入文档在 https://taotoken.net/doc。local proxy failed。这个报错多出现在沙盒模式开启后Claude 尝试访问网络但被拦截。先确认目标域名是否在sandbox.network.allowedDomains白名单里。如果是本地开发服务器检查allowLocalBinding是否为 true。如果 Claude Code 跑在 Docker 里Linux/WSL2 上还要加enableWeakerNestedSandbox。reading choices 相关报错。这类错误通常出现在模型返回格式异常时根源可能是 Model ID 不匹配或网关返回了非预期结构。确认你配置的 Model ID 和网关支持的模型一致不要用编辑器里看到的别名去填。OAuth 相关报错。如果你用的是需要 OAuth 的接入方式token 过期后会报鉴权失败。重新走一遍授权流程或者改用 API Key 方式接入后者在 CI 里更稳定。权限规则不生效。最常见的原因是层级搞错了。deny 写在 User 层但 Project 层有 allow结果 deny 被覆盖——不对deny 优先级最高不会被覆盖。真正的原因是路径写法不匹配比如Read(./.env)匹配不了Read(.env)相对路径的写法要统一。用/config看最终判定结果最直接。CC Switch / Cline MCP / Codex auth.json 场景。如果你在多个工具间切换注意每个工具的配置文件是独立的。CC Switch 管的是 Claude Code 的配置切换Cline MCP 管的是 Cline 的 MCP 服务器Codex 的auth.json是另一套。切换工具时Base URL、Key、Model ID 三件套要重新确认不要以为配了一个就通用。排查顺序建议先看/config确认规则判定再看报错类型定位是权限问题还是鉴权问题最后检查沙盒网络白名单。大部分「权限不生效」其实是路径写法或层级问题不是规则本身写错。6. 把权限配置沉淀成团队资产权限系统真正的价值不在于你一个人少点几次确认框而在于团队能共享一套可复现的安全边界。Project 层的.claude/settings.json提交进 git 后新成员 clone 下来就自动继承团队规则哪些命令自动放行、哪些必须确认、哪些绝对禁止全部一致。这比口头约定「别乱跑 rm -rf」可靠得多。我的建议是把配置分三份维护User 层放个人全局偏好比如语言、模型、全局禁止访问~/.sshProject 层放团队共识比如测试命令白名单、禁止读取密钥文件、沙盒网络白名单Local 层放本机特定覆盖比如你个人的 push 免确认不提交。CI 环境用命令行参数临时覆盖不写文件避免污染仓库。沙盒模式在 CI 里尤其值得开。无人值守场景下 bypassPermissions 是必要的但网络访问必须收窄到白名单否则一个被注入的指令就可能把数据发到外部。autoAllowBashIfSandboxed配合域名白名单能在不打断流程的前提下守住最后一道防线。最后提醒一点改完配置记得重启 Claude Code部分设置不会热加载。改坏了也别慌.claude/目录下会自动保留最近 5 份带时间戳的备份直接恢复即可。权限配置不是一次写完就完事随着项目演进白名单和 deny 规则都需要定期 review——尤其是当团队新增了工具链、或者项目引入了新的敏感文件时。