权限模式
权限模式从宏观上来理解是Agent拥有权限的程度,是粗粒度的权限控制。
| 权限模式 | 操作权限 | 最适合场景 | 特点 |
|---|---|---|---|
| default | 仅读取 | 入门、敏感工作 | 最保守,所有修改操作需询问 |
| acceptEdits | 读取 + 文件编辑 + 文件系统命令 | 代码审查、迭代工作 | 允许编辑但禁止危险操作 |
| plan | 仅读取 | 修改前的探索阶段 | 与 default 相同,用于规划阶段 |
| auto | 所有操作 + 后台安全检查 | 长时间任务、减少提示疲劳 | 自动批准大多数操作,后台验证 |
| dontAsk | 仅预先批准的工具 | 锁定的 CI 和脚本 | 只允许配置的工具,其他拒绝 |
| bypassPermissions | 所有操作 + 后台安全检查 | 隔离容器和虚拟机 | 最自由,仅限沙箱环境 |
| 操作类型 | default | acceptEdits | plan | auto | dontAsk | bypassPermissions |
|---|---|---|---|---|---|---|
| 读取文件 | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ |
| 编辑文件 | ❌ | ✅ | ❌ | ✅ | ❌ | ✅ |
| mkdir/touch/mv/cp | ❌ | ✅ | ❌ | ✅ | ❌ | ✅ |
| Bash 命令 | ❌ | ❌ | ❌ | ✅ | ❌ | ✅ |
| Git 操作 | ❌ | ❌ | ❌ | ✅ | ❌ | ✅ |
| Web 操作 | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ |
| 需要权限提示 | 🟢 频繁 | 🟡 偶尔 | 🟢 频繁 | 🟣 极少 | 🟢 频繁 | 🟣 无 |
| 后台安全检查 | ❌ | ❌ | ❌ | ✅ | ❌ | ✅ |
在 auto 和 bypassPermissions 模式下,系统在执行操作前会自动进行的安全验证过程,不需要用户逐一确认。
用户请求操作
↓
系统后台检查
├─ 这个操作是否危险?
├─ 是否可能破坏系统?
├─ 是否涉及敏感文件?
└─ 是否违反安全策略?
↓
✅ 安全 → 直接执行(无提示)
❌ 危险 → 拦截/警告
例如,会检查如下内容
| 检查类型 | 示例 | 结果 |
|---|---|---|
| 破坏性操作 | rm -rf /、git reset --hard |
拦截 |
| 权限操作 | sudo 命令、改变文件权限 |
拦截 |
| 敏感文件 | 修改系统文件、配置文件 | 警告/拦截 |
| 网络操作 | 上传敏感数据到外部 | 警告 |
| 安全的操作 | 正常的 npm install、文件编辑 | ✅ 通过 |
Agent 是否有权限调用某个工具
有人戏称使用claude code 进行开发的程序员为yes工程师,原因是claude在调用工具前会不断地进行询问。用户就要守在黑框框前,一直点yes。为了减少这种审批,Claude 允许用户进行配置,对某些工具的具体调用进行自动放行、自动拒绝或询问。分别对应的是 allow列表,deny列表,ask 列表。
如其名,allow 列表中配置的工具将会自动执行,deny 列表中配置的工具将会自动拒绝执行,ask 列表中配置的则每次都会询问用户。
三者的优先级从高到底依次是, deny、ask、allow。
Json配置文件中的权限配置
claude 的配置文件也可以分为多层,每层的配置方式类似。
| 优先级 | 设置来源 | 文件/方式 | 范围 | 说明 |
|---|---|---|---|---|
| 1(最高) | Managed 设置 | server-managed / MDM / OS 策略 / managed-settings.json | 企业级 | 由 IT 部门通过服务器、MDM、注册表部署,无法被任何其他层覆盖 |
| 2 | 命令行参数 | --settings <file-or-json> |
当前会话 | 临时覆盖,会与基于文件的设置合并 |
| 3 | 本地项目设置 | .claude/settings.local.json |
本地项目 | 个人项目特定设置,不纳入源代码管理 |
| 4 | 共享项目设置 | .claude/settings.json |
项目团队 | 团队共享的项目级设置,在源代码管理中 |
| 5(最低) | 用户设置 | ~/.claude/settings.json |
全局 | 个人全局设置,影响所有项目 |
看个配置的例子,这里只展示了最简单的配置方式,即是否允许调用该工具。
{
"permissions": {
"allow": [
"Read",
"Glob",
"Grep"
],
"deny": [
"Edit",
"Bash"
]
}
}md 文件与 json 文件权限配置对比
claude code 的权限不仅可以配置在配置文件中,Claude.md, SKILL.md, subagent.md 中也可以可以有自己的权限控制的。语法与json文件稍有不同
JSON 文件配置
{
"permissions": {
"allow": ["Read", "Bash"],
"deny": ["Write"],
"ask": ["Edit"]
}
}CLAUDE.md header 配置
---
permissions:
allow:
- Read
- Bash
deny:
- Write
ask:
- Edit
---列表格式支持两种写法:
allowed-tools: [Read, Grep] # 单行数组
allowed-tools: # 多行列表
- Read
- Grep这是标准 YAML 语法,SKILL, Subagent 也都支持这两种列表格式。
Skill 配置(SKILL.md)
---
name: code-reviewer
description: 代码审查
allowed-tools: [Read, Grep, Bash]
disallowed-tools: [Edit, Write]
---- 字段名:
allowed-tools和disallowed-tools(不同的命名) - 支持二分法(只有 allow/disallow,没有 ask)
Subagent 配置(agents/*.md)
---
name: fast-searcher
description: 快速搜索
tools: [Read, Bash, WebFetch]
disallowedTools: [Edit, Write, AskUserQuestion]
permissionMode: auto
---- 字段名:
tools、disallowedTools(注意驼峰式 camelCase) - 支持二分法(
tools/disallowedTools) - 额外字段:
permissionMode
| 维度 | JSON | CLAUDE.md | Skill | Subagent |
|---|---|---|---|---|
| 配置格式 | JSON | YAML | YAML | YAML |
| 字段名 | permissions |
permissions |
allowed-toolsdisallowed-tools |
toolsdisallowedTools |
| 命名风格 | snake_case | snake_case | kebab-case | camelCase |
| 权限分类 | allow/deny/ask | allow/deny/ask | allowed/disallowed | tools/disallowed |
| 权限模式字段 | ❌ | ❌ | ❌ | ✅ permissionMode |
工具权限细分
上边说的是Agent是否有权限调用某个工具,以Read工具为例,在实际使用中我们需要的还可能是,希望允许调用Read工具,但是不许允许该工具读某个具体的文件。如下是一个配置对比示例,允许读文件,但是不允许读 .env。这种就是Tool(pattern)语法。
JSON 写法:
{
"permissions": {
"allow": ["Read"],
"deny": ["Edit", "Write", "Read(/.env)"]
}
}CLAUDE.md 写法:
---
permissions:
allow:
- Read
deny:
- Edit
- Write
- Read(/.env)
---Skill 写法:
Skill 无法精细控制 .env 文件, 仅支持工具级别的权限控制,不支持精细控制
---
allowed-tools: [Read]
disallowed-tools: [Edit, Write]
---Subagent 写法:
Subagent 无法精细控制 .env 文件, 仅支持工具级别的权限控制,不支持精细控制
---
tools: [Read]
disallowedTools: [Edit, Write]
---Tool(pattern) 语法
Tool(pattern) 中的pattern写法:
Tool(param:value): 正常的kv形式- 工具特定的写法,下边会介绍到。
从 工具输入类型可以找到所有工具的param以及value。
参数匹配规则详解
1. 参数必须是工具输入的直接字段(不支持嵌套对象)
# ❌ 错误:试图访问嵌套的对象属性
permissions:
allow:
- Agent(config.model:opus) # config 是嵌套的,不行
# ✅ 正确:只能是工具参数本身的顶级字段
permissions:
allow:
- Agent(model:opus) # model 是 Agent 工具的直接参数简单说:只能用 Agent(model:...) 不能用 Agent(options.model:...)
2. 每个规则命名一个参数
# ❌ 错误:一个规则里写两个参数
permissions:
allow:
- Agent(model:opus, isolation:worktree) # 不行!
# ✅ 正确:一个参数一个规则,要限制两个就写两个规则
permissions:
allow:
- Agent(model:opus)
- Agent(isolation:worktree)3. 支持 * 通配符(匹配任何值)
permissions:
allow:
- Agent(model:opus) # 只允许 Opus
# ✅ 用通配符放宽限制
permissions:
allow:
- Agent(model:*) # 允许任何模型
- Agent(isolation:*) # 允许任何隔离类型4. 省略参数的调用不会被匹配
permissions:
allow:
- Agent(model:opus)
# 调用工具时传入的参数:
# ✅ Agent(model: "opus") → 匹配
# ❌ Agent(model: "sonnet") → 不匹配(值不同)
# ❌ Agent(isolation: "worktree") → 不匹配(省略了 model 参数)
# ❌ Agent() → 不匹配(什么都没传)关键点:规则要求 model:opus 时,调用必须包含 model 这个参数。光有其他参数不行。
5. 比较是精确匹配
permissions:
allow:
- Agent(model:opus)
# 调用工具时传入的参数:
# ✅ Agent(model: "opus") → 精确匹配
# ❌ Agent(model: "Opus") → 不匹配(大小写不同)
# ❌ Agent(model: "claude-opus") → 不匹配(字符串不同)系统不会帮你转换或规范化。比如 model ID 可能是 "claude-opus-4-8",但规则里写的是 "opus",两者不会因为"都是 Opus"而匹配。
实战对比
permissions:
allow:
- Bash(run_in_background:true) # 规则1:后台 Bash
- Bash(run_in_background:false) # 规则2:前台 Bash
# 调用工具时传入的参数:
# ✅ Bash(command: "npm test", run_in_background: true) → 匹配规则1
# ✅ Bash(command: "npm test", run_in_background: false) → 匹配规则2
# ❌ Bash(command: "npm test") → 不匹配任何规则(省略了参数)核心要点:严格、明确、不做假设。参数值必须精确相等,不会进行任何类型转换或规范化。
工具特定的 pattern 用法
Bash
支持带有 * 的通配符匹配,可在命令任何位置出现:
{
"permissions": {
"allow": [
"Bash(npm run build)", // 精确匹配
"Bash(npm run test *)", // 前缀匹配
"Bash(npm *)", // 以 npm 开头
"Bash(* install)", // 以 install 结尾
"Bash(git * main)", // 中间通配符
"Bash(* --version)", // 任何带 --version 的命令
"Bash(* --help *)" // 多个通配符
],
"deny": [
"Bash(git push *)", // 拒绝所有 git push
"Bash(rm -rf *)" // 拒绝危险删除
]
}
}只读命令(无需权限)
自动允许:ls、cat、echo、pwd、head、tail、grep、find、wc、which、diff、stat、du、cd、git(只读形式)
PowerShell
与 Bash 语法相同,但带有额外特性:
{
"permissions": {
"allow": [
"PowerShell(Get-ChildItem *)",
"PowerShell(git commit *)"
],
"deny": [
"PowerShell(Remove-Item *)"
]
}
}特性:
- 常见别名在匹配前被规范化:
PowerShell(Get-ChildItem *)也匹配gci、ls、dir - 匹配不区分大小写
- 识别管道
|、语句分隔符;、链运算符&&和|| - 规则必须匹配每个子命令
Read 和 Edit
使用 gitignore 规范的路径模式:
{
"permissions": {
"allow": [
"Edit(/src/**/*.ts)", // 项目根 src/ 下所有 .ts 文件
"Read(~/.zshrc)", // 主目录的 .zshrc
"Edit(//tmp/scratch.txt)", // 绝对路径
"Read(src/**)", // 当前目录 src/ 下的文件
"Read(*.env)", // 当前目录的 .env 文件
"Read(**/.env)" // 任何目录下的 .env(等同上一个)
],
"deny": [
"Read(.env)", // 拒绝当前目录及下级的 .env
"Read(//**/.env)", // 拒绝文件系统任何地方的 .env
"Edit(~/.ssh/**)" // 拒绝主目录 .ssh 中的所有文件
]
}
}路径前缀:
//path= 绝对文件系统路径~/path= 主目录相对路径/path= 项目根目录相对路径path或./path= 当前工作目录相对路径
Windows 特殊处理:
- 路径规范化为 POSIX:
C:\Users\alice→/c/Users/alice - 匹配所有驱动器:
//**/.env - 特定驱动器:
//c/**/.env
Glob 模式:
*匹配单个目录中的文件**递归匹配目录- 尾部
/**也匹配其命名的根
符号链接处理:
- Allow 规则:符号链接路径和目标都必须匹配
- Deny 规则:符号链接路径或目标任一匹配即拒绝
WebFetch
使用 domain: 前缀进行域名匹配:
{
"permissions": {
"allow": [
"WebFetch(domain:example.com)", // 精确匹配
"WebFetch(domain:*.example.com)", // 所有子域(不含根域)
"WebFetch(domain:api.example.com)", // 特定子域
"WebFetch(domain:*)" // 匹配所有域
],
"deny": [
"WebFetch(domain:evil.com)",
"WebFetch(domain:*.internal)"
]
}
}规则:
- 匹配不区分大小写
- 支持
*通配符 - 尾部
.被剥离:example.com.=example.com - 前导
*.通配符匹配任何深度子域 - 其他位置
*只匹配两个点间的文本(防止example.*匹配example.evil.com)
MCP(Model Context Protocol)
匹配 MCP 服务器中的工具:
{
"permissions": {
"allow": [
"mcp__puppeteer", // 来自 puppeteer 服务器的任何工具
"mcp__puppeteer__*", // 所有 puppeteer 工具(通配符形式)
"mcp__puppeteer__puppeteer_navigate", // 特定工具
"mcp__github__get_*" // 来自 github 服务器的 get_ 工具
],
"deny": [
"mcp__*" // 拒绝所有 MCP 工具
]
}
}格式:
mcp__<server>匹配来自该服务器的任何工具mcp__<server>__*通配符语法mcp__<server>__<tool_name>匹配特定工具- 服务器段必须是文字名称,不支持 glob
- Allow 规则仅接受
mcp__<server>__后的工具名称 glob
Agent(Subagents)
控制可用的子代理:
{
"permissions": {
"allow": [
"Agent(Explore)", // Explore 代理
"Agent(Plan)", // Plan 代理
"Agent(my-custom-agent)" // 自定义代理
],
"deny": [
"Agent(Explore)" // 禁用 Explore 代理
]
}
}也可使用参数模式:
{
"permissions": {
"allow": [
"Agent(model:opus)", // 仅允许 Opus 模型的 Agent 调用
"Agent(model:sonnet)", // 仅允许 Sonnet 模型
"Agent(isolation:worktree)", // 仅允许使用 worktree 的调用
"Agent(isolation:*)" // 允许任何隔离类型
]
}
}Cd(目录切换)
控制 /cd 命令可访问的目录:
{
"permissions": {
"allow": [
"Cd(~/code/*)", // 允许 ~/code 的直接子目录
"Cd(~/code/**)", // 允许 ~/code 及其所有子目录
"Cd(**/node_modules)", // 允许任何深度的 node_modules
"Cd(/workspace/**)" // 项目根 workspace 下的所有目录
],
"deny": [
"Cd(~/.ssh/**)", // 拒绝访问 .ssh 目录
"Cd(//etc)**)" // 拒绝访问系统 etc 目录
]
}
}特性:
Cd不是模型可调用的工具,仅在用户运行/cd时适用- 裸
Cddeny 规则完全禁用/cd命令 *匹配恰好一个路径段**匹配跨段- 尾部
/**也匹配其命名的根 - 路径前缀同 Read/Edit(
//、~/、/)
路径匹配示例:
| 规则 | 匹配 | 不匹配 |
|---|---|---|
Cd(~/code/*) |
~/code/app |
~/code/app/src、~/code |
Cd(~/code/**) |
~/code 及其所有下级目录 |
父目录 |
Cd(**/node_modules) |
任何深度的 node_modules | node_modules/pkg |
按参数匹配的通用规则
任何工具都可用 Tool(param:value) 语法:
{
"permissions": {
"allow": [
"Bash(run_in_background:true)", // 仅后台 Bash
"Bash(run_in_background:false)", // 仅前台 Bash
"Bash(timeout:300)" // 特定超时值
]
}
}限制:
- 参数必须是工具输入的直接字段(不支持嵌套)
- 每个规则一个参数
- 支持
*通配符 - 省略的参数不会被匹配