> ## Documentation Index
> Fetch the complete documentation index at: https://docs.qoder.com/llms.txt
> Use this file to discover all available pages before exploring further.

# 权限

> 了解 Qoder CLI 的权限模式、规则配置和工具调用审批流程。

## 权限模式

权限模式决定了 Qoder 如何处理工具调用——每种模式在"自动化程度"和"安全宽松度"两个维度上定位不同。

| 模式                          | 适用场景               | 行为                                         |
| :-------------------------- | :----------------- | :----------------------------------------- |
| `default`                   | 常规交互式使用            | 安全读取和内部动作可自动执行；敏感操作请求确认。                   |
| `accept_edits`              | 日常编码任务             | 自动批准工作目录内的安全文件编辑。Shell 命令、外部动作和敏感路径仍走正常检查。 |
| `auto`                      | 自动化运行、Goal 执行      | 零弹窗。安全读取和工作区内编辑自动批准；风险动作被拒绝或交给 AI 分类器判断。   |
| `bypass_permissions` (YOLO) | 仅用于可信本地实验          | 跳过所有批准提示。所有工具调用自动放行。                       |
| `dont_ask`                  | 必须不弹窗的 headless 流程 | 从不询问。任何原本需要询问的动作都会被拒绝。                     |

### Plan 模式

Plan 是独立的**工作状态**（非权限策略），可与上述任意权限模式共存。通过 `/plan` 命令进入/退出（toggle）。进入后 Qoder 只读探索代码并输出方案，写入受限于计划文件。退出时可选择后续权限模式或直接进入 Goal 执行。

### Goal 模式

Goal 是自主执行状态。通过 `/goal set <目标>` 进入——自动切换到 `auto` 模式并锁定 Shift+Tab 切换，确保执行过程零打扰。Goal 可与 Plan 共存（先规划再执行）。使用 `/goal clear` 或 `/goal pause` 退出。

### 模式循环切换

在交互式会话中，按 **Shift+Tab** 在所有权限模式间循环切换。按 **Ctrl+Y** 可直达 YOLO 模式。

### 启动参数

使用 `--permission-mode` 选择当前会话的默认行为：

```shell theme={null}
qodercli --permission-mode default
qodercli --permission-mode accept_edits
qodercli --permission-mode plan           # 兼容旧版本，实际转译为 default + 进入 Plan 工作状态
qodercli --permission-mode auto
qodercli --permission-mode bypass_permissions
qodercli --permission-mode yolo           # 等价于 bypass_permissions
qodercli --permission-mode dont_ask

# 快捷方式
qodercli --yolo                         # 等价于 --permission-mode bypass_permissions
qodercli --dangerously-skip-permissions # 同上
```

在交互式会话中，还可以通过 **Ctrl+Y** 快速切换到 YOLO 模式。

支持多种命名格式（大小写不敏感）：

| 标准值 (snake\_case)    | camelCase           | 别名             |
| :------------------- | :------------------ | :------------- |
| `accept_edits`       | `acceptEdits`       | —              |
| `bypass_permissions` | `bypassPermissions` | `yolo`, `YOLO` |
| `dont_ask`           | `dontAsk`           | —              |

示例：

```shell theme={null}
# 以下写法等价
qodercli --permission-mode bypass_permissions
qodercli --permission-mode bypassPermissions
qodercli --permission-mode yolo
qodercli --yolo
qodercli --dangerously-skip-permissions
```

非默认模式只会在可信目录中生效。如果当前目录未被信任，Qoder 会回退到 `default`。

## 权限如何决策

Qoder 在每次工具调用前做权限检查。权限结果只有三种：

* **`allow`**：立即执行工具。
* **`ask`**：需要外部确认后才能执行。
* **`deny`**：阻止这次工具调用。

权限适用于文件读取和编辑、Bash 命令、Web 抓取、MCP 工具、Subagent 以及其他内置工具。

### 决策顺序

Qoder 按固定顺序评估权限：

1. 先检查 `deny` 规则——命中即拒绝。
2. 工具自身的安全检查（如危险命令检测、敏感路径检测）。
3. `ask` 规则——命中则标记为需要确认。
4. 工具级 `allow` 规则和模式带来的自动允许行为。
5. 如果最终结果仍是 `ask`，由运行环境决定如何消费。

宽泛 allow 规则并不等于所有动作都会静默执行——安全检查和 ask 规则优先级更高。

### 不同运行环境下 `ask` 的消费方式

| 运行环境                          | `ask` 的归宿                        | 说明                    |
| :---------------------------- | :------------------------------- | :-------------------- |
| **TUI**（交互式终端）                | 弹窗确认                             | 用户在终端中选择允许/拒绝。        |
| **Headless**（`-p`/`--prompt`） | 自动拒绝                             | 无人交互，`ask` 转为 `deny`。 |
| **SDK**（stdio 协议）             | 发送 `canUseTool` 回调给宿主            | 宿主程序决定 allow/deny。    |
| **ACP**（IDE 集成）               | 发送 `requestPermission` RPC 给 IDE | IDE 弹窗或自动决策。          |

Headless 模式（`-p`/`--prompt`）下，可以搭配权限模式使用：

```shell theme={null}
# Headless + accept_edits：文件编辑自动通过，Bash 被拒绝
qodercli -p "refactor the utils module" --permission-mode accept_edits

# Headless + bypass_permissions：全部放行（仅限可信场景）
qodercli -p "run the migration" --yolo

# Headless + 精确 allow 规则：只放行特定工具
qodercli -p "check status" --allowed-tools 'Read,Bash(git status)'
```

## 权限配置

### 配置来源（8 层优先级）

规则从多个来源合并，按优先级从低到高：

| 层级 | 来源                | 说明                                                           |
| :- | :---------------- | :----------------------------------------------------------- |
| 1  | `userSettings`    | `~/.qoder/settings.json`（用户全局）                               |
| 2  | `projectSettings` | `<project>/.qoder/settings.json`（项目级，团队共享）                   |
| 3  | `localSettings`   | `<project>/.qoder/settings.local.json`（本机个人，加入 `.gitignore`） |
| 4  | `flagSettings`    | `--settings <path>` CLI 参数指定的文件                              |
| 5  | `cliArg`          | `--allowed-tools` / `--disallowed-tools` 命令行参数               |
| 6  | `command`         | `/allow`、`/deny` 会话中命令                                       |
| 7  | `session`         | 运行时临时规则（弹窗中“本次会话允许”）                                         |

高优先级来源的规则覆盖低优先级。如果组织策略开启了 `allowManagedPermissionRulesOnly`，则只使用策略托管的规则。

**各来源的配置方式：**

* **层级 1-3（settings 文件）**：在对应路径的 JSON 文件中写入 `permissions.allow` / `permissions.deny` / `permissions.ask` 数组。`settings.local.json` 适合存放本机个人审批规则，建议加入 `.gitignore`。
* **层级 4（flagSettings）**：`qodercli --settings ./custom-settings.json`，指定额外的 settings 文件路径。该文件格式与标准 settings.json 相同。
* **层级 5（cliArg）**：通过 `--permission-mode`、`--allowed-tools`、`--disallowed-tools`、`--tools` 等命令行参数配置，仅作用于当前会话。
* **层级 6（command）**：会话中输入 `/allow Bash(npm test)` 或 `/deny WebFetch`，持久化到 `settings.local.json`。
* **层级 7（session）**：弹窗中选择“本次会话允许”产生的临时规则，进程退出后失效。

### 模式配置

**设置默认模式**——在 settings 中配置 `general.defaultPermissionMode`：

```json theme={null}
{
  "general": {
    "defaultPermissionMode": "accept_edits"
  }
}
```

支持的值：

| 值                    | 行为                                  | 别名                         |
| -------------------- | ----------------------------------- | -------------------------- |
| `default`            | 每次操作都提示确认                           | —                          |
| `accept_edits`       | 自动批准文件编辑，Shell 命令仍需确认               | `acceptEdits`              |
| `plan`               | 只读模式（兼容旧版，实际转为 default + Plan 工作状态） | —                          |
| `auto`               | AI 分类器评估操作安全性                       | —                          |
| `bypass_permissions` | 跳过所有权限检查（YOLO）                      | `yolo`、`bypassPermissions` |
| `dont_ask`           | 非交互模式，需要确认的操作直接拒绝                   | `dontAsk`                  |

大小写不敏感，所有别名均可使用。

**禁用 YOLO 模式**——组织管理员可通过以下配置阻止用户进入 bypass\_permissions 模式：

```json theme={null}
{
  "security": {
    "disableYoloMode": true
  }
}
```

设置后，`--yolo`、`--permission-mode bypass_permissions` 和 Ctrl+Y 均不可用，Shift+Tab 循环也会跳过该模式。子 agent 声明 bypass 时也会被降级为 acceptEdits。

**禁用 Plan 模式**——如果不需要 Plan 工作流，可以关闭：

```json theme={null}
{
  "general": {
    "plan": {
      "enabled": false
    }
  }
}
```

设置后，`/plan` 命令不可用，`--permission-mode plan` 回退为 default，EnterPlanMode/ExitPlanMode 工具不注册。

**Auto 模式分类器配置**——可以通过自然语言规则引导 AI 分类器的判断倾向：

```json theme={null}
{
  "autoMode": {
    "allow": [
      "running npm/yarn/pnpm scripts defined in package.json",
      "creating or editing test files"
    ],
    "soft_deny": [
      "deleting files outside the test directory",
      "modifying CI/CD configuration"
    ],
    "environment": [
      "This is a Node.js monorepo with pnpm workspaces",
      "The project uses Vitest for testing"
    ]
  }
}
```

| 字段            | 作用              |
| :------------ | :-------------- |
| `allow`       | 分类器倾向于自动批准的操作描述 |
| `soft_deny`   | 分类器倾向于拒绝的操作描述   |
| `environment` | 提供给分类器的环境上下文信息  |

这些规则是**软引导**——注入到分类器 prompt 作为参考，最终决策仍由 AI 分类器做出。出于安全考虑，`autoMode` 配置只从可信来源（用户全局 settings 和 localSettings）读取，项目 settings 被排除以防止恶意权限提升。

### 权限规则配置

规则按 `allow`、`ask` 和 `deny` 分组：

```json theme={null}
{
  "permissions": {
    "allow": [
      "Read(/src/**)",
      "Edit(/src/**)",
      "Bash(npm run test:*)"
    ],
    "ask": [
      "Bash(npm publish:*)",
      "WebFetch"
    ],
    "deny": [
      "Read(*.pem)",
      "Bash(rm -rf:*)"
    ]
  }
}
```

### 规则语法

| 形式                  | 含义                                |
| :------------------ | :-------------------------------- |
| `ToolName`          | 作用于整个工具。                          |
| `ToolName(content)` | 作用于某个路径、命令、agent 类型，或工具支持的其他特定内容。 |
| `*`                 | 匹配所有工具。                           |

使用规范工具名：`Read`、`Edit`、`Write`、`Bash`、`Grep`、`Glob`、`WebFetch`、`WebSearch`、`Agent`，以及 `mcp__github__create_issue` 这类 MCP 工具名。

如果内容中包含括号，需要转义：

```json theme={null}
{
  "permissions": {
    "allow": [
      "Bash(python -c \"print\\(1\\)\")"
    ]
  }
}
```

`ToolName(*)` 等同于 `ToolName`（工具级规则）。

### 命令行覆盖

```shell theme={null}
qodercli --allowed-tools 'Read,Grep,Bash(git status)'
qodercli --disallowed-tools 'Bash(rm -rf:*),mcp__github__delete_repo'
qodercli --tools 'Read,Grep,Edit'
```

`--allowed-tools` 和 `--disallowed-tools` 使用与 settings 相同的规则语法。`--tools` 限制本次运行可用的内置工具集（未列出的工具会被拒绝）。

## 信任目录

Qoder 将启动时的当前工作目录（CWD）视为**主信任目录**。在信任目录内：

* 文件读取默认 allow
* 文件写入在 `accept_edits` 和 `auto` 模式下可自动批准
* 非默认权限模式（auto、bypass 等）才能生效

如果当前目录不被信任，Qoder 会强制回退到 `default` 模式。

### 扩展信任范围

通过 `--add-dir`、`/add-dir` 命令或 `permissions.additionalDirectories` 增加额外可信工作目录：

```shell theme={null}
qodercli --add-dir ../shared
```

```json theme={null}
{
  "permissions": {
    "additionalDirectories": ["../shared"]
  }
}
```

也可以在全局 settings 中配置 `permissions.trustDirectories` 将常用目录永久信任。

### 受保护路径

部分路径受到保护，因为编辑它们可能改变执行行为、凭据或工具行为。例如 `.git`、`.vscode`、`.idea`、`.husky`、大多数 `.qoder` 配置文件、`.bashrc`/`.zshrc` 等 shell 启动文件、Git 配置、`.mcp.json`、`.ripgreprc`。在常规交互式模式下，这些路径需要明确批准；在 `auto` 模式下会被拒绝。

## 文件访问规则

带路径范围的读取规则使用 `Read(...)`。带路径范围的写入规则使用 `Edit(...)`；它覆盖 `Edit`、`Write` 和 `NotebookEdit` 的文件写入检查。某个路径上的 `Edit(...)` allow 规则也会隐含允许读取同一路径。

文件规则使用 gitignore 风格匹配。

| 模式               | 含义                                                                            |
| :--------------- | :---------------------------------------------------------------------------- |
| `/src/**`        | 基于规则来源根目录的路径。在 project/local settings 中相对于项目根目录；在 user settings 中相对于 home 目录。 |
| `~/Documents/**` | 基于 home 目录的路径。                                                                |
| `//tmp/data/**`  | 从系统 `/` 开始的绝对路径。绝对路径需要使用双斜杠。                                                  |
| `*.secret`       | 不带根目录的文件名模式，可在任意位置匹配。                                                         |

示例：

```json theme={null}
{
  "permissions": {
    "allow": [
      "Read(/src/**)",
      "Edit(/src/**)",
      "Read(~/Documents/specs/**)"
    ],
    "ask": [
      "Edit(/package.json)",
      "Read(~/Downloads/**)"
    ],
    "deny": [
      "Read(*.pem)",
      "Edit(/.git/**)",
      "Edit(//etc/**)"
    ]
  }
}
```

## Bash 规则

`Bash(...)` 规则可以匹配精确命令、命令前缀或通配模式。

| 规则                     | 匹配内容                                         |
| :--------------------- | :------------------------------------------- |
| `Bash(npm run build)`  | 精确匹配 `npm run build`。                        |
| `Bash(npm run test:*)` | 匹配 `npm run test` 以及以 `npm run test ` 开头的命令。 |
| `Bash(git log *)`      | 使用 glob 风格通配匹配。                              |
| `Bash(git status)`     | 精确匹配 `git status`。                           |

示例：

```json theme={null}
{
  "permissions": {
    "allow": [
      "Bash(git status)",
      "Bash(git log:*)",
      "Bash(npm run test:*)"
    ],
    "ask": [
      "Bash(npm publish:*)",
      "Bash(git push:*)"
    ],
    "deny": [
      "Bash(rm -rf:*)",
      "Bash(sudo:*)"
    ]
  }
}
```

Shell 匹配是保守的：

* `deny` 和 `ask` 规则会穿透常见 wrapper 和环境变量前缀，因此 `Bash(rm -rf:*)` 仍能拦截被包装过的破坏性命令。
* 前缀和通配 `allow` 规则不会静默批准复合命令，除非每个顶层命令片段都能独立被允许。
* 部分可证明只读的 shell 命令，在 deny、ask 和路径检查之后可以被自动允许。
* 危险命令（如破坏性删除或 force push），即使存在宽泛 allow 规则，也可能强制确认。在 `auto` 模式下，危险 Shell 命令会被拒绝。

除非你完全信任当前会话，否则避免使用 `Bash` 或 `Bash(*)` 这类宽泛规则。

## Web 和 MCP 规则

Web 工具可以用工具级规则控制。若所有 web fetch 都需要确认，用 `ask`；若某个会话或项目应禁用网络访问，用 `deny`。

```json theme={null}
{
  "permissions": {
    "ask": [
      "WebFetch"
    ],
    "deny": [
      "WebSearch"
    ]
  }
}
```

MCP 工具使用完整限定名：

```text theme={null}
mcp__<server>__<tool>
```

支持的 MCP 模式包括：

| 规则                          | 含义                          |
| :-------------------------- | :-------------------------- |
| `mcp__github__create_issue` | 单个 MCP 工具。                  |
| `mcp__github__*`            | `github` MCP server 下的所有工具。 |
| `mcp__github`               | `github` MCP server 下的所有工具。 |
| `mcp__*`                    | 所有 MCP 工具。                  |

示例：

```json theme={null}
{
  "permissions": {
    "allow": [
      "mcp__context7__*"
    ],
    "ask": [
      "mcp__github__create_issue"
    ]
  }
}
```

MCP server 配置也可以通过 `alwaysAllow` 为该 server 的工具设置自动允许。如果一次运行只想启用指定 MCP server，可以使用 `--allowed-mcp-server-names`。

```shell theme={null}
qodercli --allowed-mcp-server-names context7,github
```

## Hook 与权限

Qoder 的 Hook 系统在权限决策链路中有两个注入点，可以通过自定义脚本影响工具的允许/拒绝行为。

### 影响权限的 Hook 事件

| Hook 事件             | 触发时机               | 可产生的权限影响                                          |        |                    |
| :------------------ | :----------------- | :------------------------------------------------ | ------ | ------------------ |
| `PreToolUse`        | 工具执行前（权限检查阶段）      | 可返回 \`permissionDecision: "allow"                 | "deny" | "ask"\` 直接覆盖权限管道结果 |
| `PermissionRequest` | 权限管道产出 `ask` 后、弹窗前 | 可返回 `decision.behavior` 为 `allow` 或 `deny`，代替用户交互 |        |                    |

其他 Hook 事件（`PostToolUse`、`SessionStart`、`Stop` 等）不参与权限决策。

### PreToolUse Hook

在工具执行前触发。Hook 脚本可以检查工具名和参数，返回权限决策：

```json theme={null}
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "python ./scripts/check-bash-command.py"
          }
        ]
      }
    ]
  }
}
```

Hook 脚本通过 stdin 接收 JSON 输入（含 `tool_name`、`tool_input`、`session_id` 等），通过 stdout 输出 JSON 结果：

```json theme={null}
{
  "hookSpecificOutput": {
    "hookEventName": "PreToolUse",
    "permissionDecision": "deny",
    "permissionDecisionReason": "Command blocked by security policy"
  }
}
```

`permissionDecision` 可选值：

* `"allow"`：跳过权限管道，直接批准
* `"deny"`：跳过权限管道，直接拒绝
* `"ask"`：继续走正常权限管道（默认行为）

### PermissionRequest Hook

在权限管道产出 `ask` 之后、弹窗/回调之前触发。适合用于自动化审批系统或外部通知（如 Slack/邮件提醒）：

```json theme={null}
{
  "hooks": {
    "PermissionRequest": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "node ./scripts/auto-approve-safe-ops.js"
          }
        ]
      }
    ]
  }
}
```

输出格式：

```json theme={null}
{
  "hookSpecificOutput": {
    "hookEventName": "PermissionRequest",
    "decision": {
      "behavior": "allow",
      "updatedInput": {},
      "updatedPermissions": []
    }
  }
}
```

### Hook 与权限模式的优先级

Hook 的权限决策优先级**高于**权限模式——即使在 `bypass_permissions` 模式下，PreToolUse Hook 返回 `deny` 仍然会阻止执行。这为组织级安全策略提供了不可绕过的拦截能力。

执行顺序：

1. Hook `PreToolUse` → 如果返回 allow/deny，短路
2. 权限管道（规则 + 模式 + 安全检查）
3. 如果结果是 `ask` → Hook `PermissionRequest` → 如果返回 allow/deny，短路
4. 最终由运行环境消费 `ask`（弹窗/deny/回调）
