Papyrus.
claude-code / 权限.md

权限

最后更新 2026-07-03

权限模式

权限模式从宏观上来理解是Agent拥有权限的程度,是粗粒度的权限控制。

权限模式 操作权限 最适合场景 特点
default 仅读取 入门、敏感工作 最保守,所有修改操作需询问
acceptEdits 读取 + 文件编辑 + 文件系统命令 代码审查、迭代工作 允许编辑但禁止危险操作
plan 仅读取 修改前的探索阶段 与 default 相同,用于规划阶段
auto 所有操作 + 后台安全检查 长时间任务、减少提示疲劳 自动批准大多数操作,后台验证
dontAsk 仅预先批准的工具 锁定的 CI 和脚本 只允许配置的工具,其他拒绝
bypassPermissions 所有操作 + 后台安全检查 隔离容器和虚拟机 最自由,仅限沙箱环境
操作类型 default acceptEdits plan auto dontAsk bypassPermissions
读取文件
编辑文件
mkdir/touch/mv/cp
Bash 命令
Git 操作
Web 操作
需要权限提示 🟢 频繁 🟡 偶尔 🟢 频繁 🟣 极少 🟢 频繁 🟣 无
后台安全检查

autobypassPermissions 模式下,系统在执行操作前会自动进行的安全验证过程,不需要用户逐一确认

用户请求操作
    ↓
系统后台检查
    ├─ 这个操作是否危险?
    ├─ 是否可能破坏系统?
    ├─ 是否涉及敏感文件?
    └─ 是否违反安全策略?
    ↓
✅ 安全 → 直接执行(无提示)
❌ 危险 → 拦截/警告

例如,会检查如下内容

检查类型 示例 结果
破坏性操作 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-toolsdisallowed-tools(不同的命名)
  • 支持二分法(只有 allow/disallow,没有 ask)

Subagent 配置(agents/*.md)

---
name: fast-searcher
description: 快速搜索
tools: [Read, Bash, WebFetch]
disallowedTools: [Edit, Write, AskUserQuestion]
permissionMode: auto
---
  • 字段名:toolsdisallowedTools(注意驼峰式 camelCase)
  • 支持二分法(tools/disallowedTools
  • 额外字段:permissionMode
维度 JSON CLAUDE.md Skill Subagent
配置格式 JSON YAML YAML YAML
字段名 permissions permissions allowed-tools
disallowed-tools
tools
disallowedTools
命名风格 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 *)"                 // 拒绝危险删除
    ]
  }
}

只读命令(无需权限)

自动允许:lscatechopwdheadtailgrepfindwcwhichdiffstatducdgit(只读形式)


PowerShell

与 Bash 语法相同,但带有额外特性:

{
  "permissions": {
    "allow": [
      "PowerShell(Get-ChildItem *)",
      "PowerShell(git commit *)"
    ],
    "deny": [
      "PowerShell(Remove-Item *)"
    ]
  }
}

特性:

  • 常见别名在匹配前被规范化:PowerShell(Get-ChildItem *) 也匹配 gcilsdir
  • 匹配不区分大小写
  • 识别管道 |、语句分隔符 ;、链运算符 &&||
  • 规则必须匹配每个子命令

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 时适用
  • Cd deny 规则完全禁用 /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)"                 // 特定超时值
    ]
  }
}

限制:

  • 参数必须是工具输入的直接字段(不支持嵌套)
  • 每个规则一个参数
  • 支持 * 通配符
  • 省略的参数不会被匹配