05. 权限模型入门
权限是工程纪律的第一道防线。它不是"确认弹窗"那么简单——它是你把 Claude Code 从问答工具升级为可验证工程代理时,唯一能在自动化与安全之间画线的机制。
这一章给结论:权限模型由三层构成,缺一不可。
- 规则数组——
allow/deny/ask,声明哪些工具调用自动放行、哪些拒绝、哪些询问。 - 配置文件层级——managed / user / project / local 四级,优先级从高到低,决定规则在哪里生效、谁能覆盖谁。
- 权限模式——default / acceptEdits / plan / bypassPermissions / auto / dontAsk 六种,控制"询问还是不询问"的整体策略。
核心原则一句话:让低风险命令自动跑、高风险动作必定停。配置得好,Claude 能在测试-修改-再测试的闭环里高速循环而不打断你;配置得不好,要么每条命令都弹窗把人逼疯,要么 bypassPermissions 一开,把仓库和生产环境一起送走。
本章按这三层展开,最后给出一份可直接落地的 settings.json 与一套红线清单。版本基准:2026-07-08,Claude Code v2.1.202+。
5.1 规则数组:allow / deny / ask 的语义与语法
5.1.1 三种语义
permissions 下的三个数组定义了工具调用的处置策略:
| 数组 | 语义 | 典型用途 |
|---|---|---|
allow | 自动放行,不询问 | 只读操作、测试、Lint、类型检查 |
ask | 弹窗询问,等待人工决策 | git commit、外部 curl、有副作用但非破坏性 |
deny | 直接拒绝,不询问也不可被下层覆盖 | 读凭据、git push、rm -rf、npm publish |
求值顺序固定为 deny → ask → allow。任何工具调用先过 deny 检查,命中即拒,不会被 allow 覆盖。这条顺序保证了"危险动作无论在哪个层级被允许,都能被更高层级的 deny 拦下"——这是 deny 作为兜底红线的工程含义。
5.1.2 规则语法
规则由工具名 + 括号参数组成,参数支持 gitignore 风格的通配:
{
"permissions": {
"allow": [
"Read",
"Glob",
"Grep",
"Bash(npm test)",
"Bash(npm test *)",
"Bash(git diff*)",
"WebFetch(domain:example.com)"
],
"ask": [
"Bash(git add *)",
"Bash(git commit *)",
"Bash(curl *)"
],
"deny": [
"Read(.env)",
"Read(.env.*)",
"Read(secrets/**)",
"Bash(git push *)",
"Bash(git reset --hard *)",
"Bash(rm -rf *)",
"Bash(npm publish *)"
]
}
}四个高频踩坑点(官方文档明确):
- 前缀通配必须用空格:
Bash(npm test *)匹配npm test auth.spec;而Bash(npm test*)(无空格)会连带匹配npm testcoverage这类无关命令。空格分隔的是"命令"与"参数"。 - 冒号写法是错的:
Bash(npm test:*)不工作。冒号只用于参数级匹配,如WebFetch(domain:example.com)、Agent(isolation:worktree),不用于命令前缀。 - 文件类规则遵循 gitignore 语义:
Read(.env)与Read(**/.env)等价,匹配任意层级的.env;要匹配仓库任意位置用绝对路径形式Read(//**/.env)。 Read/Edit规则不能替代操作系统级沙箱。脚本可以通过cat、curl间接读取文件,权限规则只管 Claude 直接调用的工具。要做强隔离,启用 Claude Code sandbox,并把秘密放在工作目录之外。
交互式查看当前生效规则:
/permissions5.2 配置文件层级:managed / user / project / local
5.2.1 四级优先级
规则不是写在一个文件里,而是分散在四个层级,优先级从高到低:
| 层级 | 文件位置 | 谁来维护 | 是否提交 Git | 典型用途 |
|---|---|---|---|---|
| managed policy | 企业下发(平台级) | IT / 安全团队 | 不可被用户覆盖 | 企业强制红线 |
| user | ~/.claude/settings.json | 个人 | 不提交(在 home) | 跨项目个人偏好 |
| project | .claude/settings.json | 团队 | 提交,团队共享 | 项目级规范、团队红线 |
| local | .claude/settings.local.json | 个人 | 不提交(加 .gitignore) | 个人临时偏好、实验性放行 |
优先级含义:managed 的规则不可被下层覆盖;user、project、local 之间,高优先级的 deny 可以压过低优先级的 allow,反之不行。这条机制保证了"团队的 deny 不会被个人的 allow 绕过"——也是为什么企业场景下 managed policy 能成为合规底线。
一个容易忽略的细节:四层只对"规则数组"叠加求值,不对"权限模式"叠加。权限模式取当前会话生效的那一个(通常由启动 flag 或 Shift+Tab 指定),不存在"managed 模式覆盖 user 模式"的说法。这也意味着:managed policy 锁死的是"哪些动作永远不能被允许",而不是"当前用哪种询问策略"。
5.2.2 managed policy 的企业场景
managed policy 在个人开发里很少见,但在企业、受监管行业里是合规底线。典型场景:
- 金融机构合规要求:任何代码不得读取生产数据库凭据,任何
git push不得绕过 PR 审查。IT 团队把Read(**/prod-credentials/**)、Bash(git push *)写进 managed policy,开发者无法在本地 settings.json 里用allow覆盖。 - 受监管代码库:法律要求所有变更可追溯,
Bash(git commit --amend *)、Bash(git rebase *)进 managed deny,保证 Git 历史不可篡改。
个人开发者用不到 managed policy,但理解它的存在有助于建立"权限是分层合规体系"的认知:权限不只是你个人的效率工具,也是组织级的安全边界。本书第六部分讲一人公司产品化时,会回到这个概念——当你为客户交付项目,你自己的 settings.json 就是客户资产的 managed policy。
5.2.3 project vs local:该放什么
这是新人最容易混淆的判断。判断标准只有一条:这条规则对团队里每个人都要生效吗?
- 是 → project(
.claude/settings.json,提交 Git)。例如:本项目禁止npm publish、禁止读secrets/、测试命令是npm test、Lint 命令是npm run lint。这些是项目级共识,新人 clone 下来就有保护。 - 否 → local(
.claude/settings.local.json,不提交)。例如:你个人临时允许Bash(docker compose up *)做本地联调,但同事用 Podman 不需要;你个人偏好自动接受某个实验性脚本。这些放 local,不要污染团队配置。
一个常见反例:把个人偏好的 Bash(pnpm *) 写进 project 的 settings.json,结果团队里用 npm 的同事也被强行套上 pnpm 规则。项目配置只放共识,个人偏好回 local。
.claude/settings.local.json 应当在 .gitignore 里显式忽略,避免误提交:
.claude/settings.local.json5.3 权限模式:六种策略
规则数组定义了"哪些动作放行/拒绝/询问",权限模式定义了"整体上问还是不问"。两者叠加,决定了 Claude 的实际行为。
5.3.1 六种模式
| 模式 | 行为 | 适用场景 | 风险 |
|---|---|---|---|
default(Manual) | 每个有副作用的工具调用都弹窗询问 | 新项目、陌生仓库、首次探索 | 低,但打断频繁 |
acceptEdits | 自动接受工作区内文件编辑,其他命令仍询问 | 信任范围内的代码修改 | 中,误编辑不会被拦 |
plan | 只读分析,禁止任何文件改动与有副作用命令 | 方案设计、影响评估、代码审查 | 极低 |
bypassPermissions | 取消全部控制面,等价 --dangerously-skip-permissions | 极少推荐;一次性沙箱实验 | 极高,见 5.6 |
auto(新,research preview) | 后台分类器自动审核,约 93% 提示被批准,高风险动作仍拦截 | 熟悉项目后的日常开发 | 中,残余 7% 风险 |
dontAsk | 未显式允许的工具自动拒绝(不弹窗),allow 列表仍可用 | CI、headless、非交互脚本 | 低,但会拒绝部分有用工具 |
auto 模式标注为 research preview(2026-07-08 核对)。它的"93% 批准率"是官方公布的统计值,意味着大约每 14 次工具调用有 1 次仍会弹窗或拒绝。不能把它当 bypassPermissions 用。
5.3.2 切换方式
两种切换路径:
交互式(会话内):Shift+Tab 在六种模式间循环切换,状态栏显示当前模式。适合开发中根据任务阶段动态调整——读代码时切 plan,动手改时切 acceptEdits,跑完整流程时切 auto。
启动时指定(命令行 flag):
claude --permission-mode plan
claude --permission-mode acceptEdits
claude --permission-mode auto适合脚本化场景。CI 里跑 headless 审查,固定用 plan 或 dontAsk:
claude -p --permission-mode dontAsk \
--max-turns 10 \
"审查当前 git diff,只报告高置信度问题,不修改文件"dontAsk 在这里的妙处:未显式允许的工具调用不会被弹窗卡住(脚本环境无法响应弹窗),而是直接拒绝,让 Claude 知道这条路不通,转而走 allow 列表里的只读工具。这是 headless 场景下既安全又不卡死的正确姿势。
5.3.3 规则与模式如何叠加
这是新人最困惑的问题:allow 里的命令在 default 模式下还会问吗?在 dontAsk 下呢?答案是按"模式先判断,规则再兜底"的顺序求值。
具体叠加矩阵:
| 模式 \ 规则命中 | deny | ask | allow | 未匹配任何规则 |
|---|---|---|---|---|
default | 拒绝 | 询问 | 放行 | 询问 |
acceptEdits | 拒绝 | 询问 | 放行 | 文件编辑放行,其他询问 |
plan | 拒绝 | 拒绝 | 拒绝(有副作用者) | 拒绝 |
auto | 拒绝 | 分类器判断 | 放行 | 分类器判断 |
dontAsk | 拒绝 | 拒绝 | 放行 | 拒绝 |
bypassPermissions | 仍拒绝 | 放行 | 放行 | 放行 |
两个关键结论:
deny在任何模式下都生效,包括bypassPermissions。这是为什么deny是兜底红线——即使你疯了开bypassPermissions,Bash(rm -rf *)仍然会被拦。但要注意:bypassPermissions之所以危险,是因为它放行了所有"未匹配规则"的动作,而你的deny列表不可能穷举所有危险命令。plan模式比default更严格。plan下连allow里的有副作用命令也会被拒——因为它要保证"只读分析"的语义。plan是唯一一个"allow 不总生效"的模式。
理解了这张矩阵,你就能预判任何配置下的实际行为,不用反复试错。
5.4 一份可直接落地的 settings.json
下面是 project 级 .claude/settings.json 的完整可用模板,覆盖一个典型 Node.js 项目的日常开发。复制即用,按需调整命令名(Python 项目换成 Bash(pytest *)、Go 项目换成 Bash(go test *))。
{
"$schema": "https://json.schemastore.org/claude-code-settings.json",
"permissions": {
"allow": [
"Read",
"Glob",
"Grep",
"Bash(npm test)",
"Bash(npm test *)",
"Bash(npm run test)",
"Bash(npm run test *)",
"Bash(npm run lint)",
"Bash(npm run lint *)",
"Bash(npm run typecheck)",
"Bash(npm run typecheck *)",
"Bash(npm run build)",
"Bash(git status)",
"Bash(git status *)",
"Bash(git diff)",
"Bash(git diff *)",
"Bash(git log)",
"Bash(git log *)",
"Bash(git branch)",
"Bash(git branch *)"
],
"ask": [
"Bash(git add *)",
"Bash(git commit *)",
"Bash(curl *)",
"Bash(docker *)",
"Bash(make *)"
],
"deny": [
"Read(.env)",
"Read(.env.*)",
"Read(secrets/**)",
"Read(**/credentials.json)",
"Read(**/*.pem)",
"Bash(git push *)",
"Bash(git push -f *)",
"Bash(git push --force *)",
"Bash(git reset --hard *)",
"Bash(git rebase *)",
"Bash(git checkout -- *)",
"Bash(rm -rf *)",
"Bash(rm -rf /)",
"Bash(sudo *)",
"Bash(npm publish *)",
"Bash(npx publish *)",
"Bash(pnpm publish *)"
]
}
}这套配置的意图,按动作分类:
| 动作 | 策略 | 原因 |
|---|---|---|
| 读源码、搜索符号、git 只读命令 | allow | 低风险且高频,放行以构成自动闭环 |
| 跑测试、Lint、类型检查、构建 | allow | 构成"改-测-改"自动修正闭环 |
git add / git commit / curl / docker | ask | 有持久或外部副作用,但非破坏性,人工确认 |
| 读凭据、推送、重写历史、删除、发布 | deny | 不应由项目级配置放行 |
注意 deny 里的 Bash(sudo *)——任何提权操作都应被拦下,因为 sudo 一旦执行,后续命令绕过的是操作系统权限,Claude 的权限规则不再有效。sudo 是权限模型的逃生舱,必须锁死。
5.5 分层授权原则:读 / 写 / 破坏性
权限配置的本质是按"动作风险"分层。三层原则:
第一层:读操作全部自动允许。
Read、Glob、Grep、git status、git diff、git log——这些不产生任何副作用,Claude 越多读越准,拦下它们只会拖慢闭环、逼 Claude 凭记忆猜。唯一例外:凭据文件(.env、secrets/、*.pem),这些进 deny,不是因为读本身危险,而是读进上下文后续可能被写进 commit 或日志。
第二层:写操作按项目约定放开。
Edit、Write 是否自动允许,取决于项目成熟度。新项目、个人项目:用 acceptEdits 或 auto 模式,自动接受编辑。遗留项目、生产代码:用 default 模式,每个编辑都确认。测试与 Lint 命令(npm test、npm run lint)属于"写但低风险",放 allow——它们是闭环的一部分,拦下它们就等于不让 Claude 自我验证。
第三层:破坏性操作永远不自动允许。
删除、推送、重写历史、发布、数据库变更、提权——这些动作的失败成本不可逆。无论项目多成熟、模式多激进,它们都必须进 deny 或至少 ask。理由不是"不信任 Claude",而是"不信任任何自动化对不可逆动作的判断"。一次 rm -rf 的代价,远高于一辈子为它按 n 的成本。
5.6 安全红线意识:六类必须二次确认
借鉴一位资深用户的 CLAUDE.md 红线边界理念(本教程作者也采用),以下六类操作即使在 auto-accept 模式下也必须绝对中止并二次确认:
- 破坏性修改:删除文件、删除目录、篡改 Git 历史(
git rebase、git reset --hard、git push --force)。 - 凭据安全:修改
.env文件、密钥、Token 或 CI/CD 配置。严禁密钥进入代码、commit 或日志。 - 数据安全:执行数据库 Schema 变更或数据迁移(
DROP TABLE、ALTER TABLE、DELETE FROM不带WHERE)。 - 风险命令:
git push、git rebase、git reset --hard、强制推送。 - 环境污染:安装新的全局依赖(
npm install -g)、修改系统级配置。 - 公开发布:
npm publish、部署到生产环境、发布文章。
这六类的共同特征:动作外部化、影响不可逆、超出当前仓库边界。Claude Code 的权限模型管的是"工作区内工具调用",但 git push 把变更送到了远端、npm publish 把包送到了公共注册表、生产部署把代码送到了线上——这些动作的后果已经超出权限模型能回收的范围。
在 settings.json 里,这六类全部进 deny。在 CLAUDE.md 里,用自然语言再强调一次,让 Claude 在调用工具前主动核对。规则变更顺序:先改文档,再改代码实践,严禁倒置。
一个补充:bypassPermissions(即 --dangerously-skip-permissions)不在日常推荐之列。它取消的是人类控制面,不是模型犯错的可能性。Claude 在 bypassPermissions 下仍然会幻觉、会误删、会推错分支——只是没人拦它。唯一可接受的场景是一次性、可丢弃的沙箱实验,且工作区内没有任何敏感文件、不挂载任何凭据。把它当日常捷径,迟早翻车。
5.6.1 在 CLAUDE.md 里用自然语言强化红线
settings.json 的 deny 是机器可执行的硬规则,但 Claude 在调用工具前也会读 CLAUDE.md。两层防线互相补充:deny 拦下已知的危险命令,自然语言红线拦下"deny 列表没穷举到"的边缘动作。
在 CLAUDE.md 里加一段:
## 红线边界(Autonomous Boundaries)
注意:以下操作即使在 auto-accept 模式下,也必须绝对中止并向我二次确认!
1. 破坏性修改:删除文件、目录或篡改 Git 历史。
2. 凭据安全:修改 .env 文件、密钥、Token 或 CI/CD 配置(严禁密钥进入代码、commit 或日志)。
3. 数据安全:执行数据库 Schema 变更或数据迁移。
4. 风险命令:执行 git push、git rebase、git reset --hard 或强制推送。
5. 环境污染:安装新的全局依赖或修改系统级配置。
6. 公开发布:执行 npm publish、部署到生产环境或发布文章。这段自然语言的作用,是让 Claude 在"工具调用前的推理阶段"就主动核对:它要执行的下一个动作是否触及这六类。如果触及,它应当先停下来询问,而不是执行后等你拦。deny 是事后硬拦截,CLAUDE.md 红线是事前软拦截——两层叠加,才构成完整的工程纪律。
规则变更顺序:先改 CLAUDE.md,再改 settings.json 实践,严禁倒置。先有共识,再有执行。
5.7 失败边界:过宽、过烦、auto 的残余风险
权限配置的三种典型失败模式:
失败一:过宽——bypassPermissions 误用。
症状:Claude 跑得很顺,直到某天它自信地删掉了关键文件、推到了 main 分支、或者把测试日志里的 secret push 到了远端。
根因:把"不打断"当成目标,忽略了"打断"是唯一的安全阀。bypassPermissions 不是效率工具,是紧急逃生通道——平时不用,用了就要承担全部后果。
补救:立即退出该会话,用 git reflog 恢复历史,检查 git log -p 找回被删文件。长期解药:删除 bypassPermissions 的所有使用,改用 auto 或 acceptEdits + 精心维护的 deny 列表。
失败二:过烦——每条命令都弹窗。
症状:开发一小时,按了 40 次 y,注意力被切碎,开始无脑按 y——这是最危险的状态,比 bypassPermissions 还危险,因为人已经丧失了判断力。
根因:allow 列表太空,或者用了 default 模式跑长闭环。
补救:用 /permissions 查看当前规则,把高频低风险命令补进 allow。本书附录会介绍 /fewer-permission-prompts 自定义 skill,它能扫描会话历史里频繁出现的只读命令,生成 allowlist 候选。短期解法:跑长闭环前切 acceptEdits 或 auto。
失败三:auto mode 的 93% 批准率与残余风险。
症状:用 auto 模式,大部分时候顺畅,偶尔 Claude 调用某个边界工具被拦截,任务卡住。
根因:auto 的后台分类器基于风险预测,不是规则匹配。93% 批准率意味着 7% 的工具调用仍会被拦——这 7% 里既有真正危险的动作(好事),也有误判的安全操作(烦事)。
补救:把误判频繁的安全命令显式加进 allow(显式 allow 优先于 auto 的分类器判断)。不要因为 auto 偶尔拦就把这些命令移到 deny 之外做特殊处理——保持 deny 干净,只放真正的红线。
auto mode 是 research preview,行为可能随版本变化。生产关键路径上不要完全依赖它,保留人工 review 作为最后一道关。
5.8 小结
权限模型三层,记住一张图:
规则数组(allow/deny/ask) —— 静态声明:哪些工具调用放行/拒绝/询问
+
配置层级(managed/user/project/local) —— 动态生效:规则在哪里、谁能覆盖谁
+
权限模式(六种) —— 整体策略:问还是不问
=
Claude 的实际行为落地三条:
- project 配置放共识,local 配置放个人。项目级
.claude/settings.json提交 Git,个人偏好回.claude/settings.local.json。 - 读操作放行,写操作按项目定,破坏性永远 deny。这是分层授权的核心。
- 六类红线不自动。破坏性修改、凭据、数据、风险命令、环境污染、公开发布——即使
auto-accept也必须二次确认。
下一章进入工程篇,讲 Claude Code 的核心心智模型与命令真实性——为什么"工具调用是事实来源,记忆不是",以及如何识破 Claude 的幻觉。