---
title: "05 - 權限模式與安全"
type: note
specialty: Programming
tags: [claude-code-cli從0開始使用教學, 05-權限, security, permission-modes]
created: 2026-08-04
updated: "2026"
modified: 2026-08-04
---

# 05 - 權限模式與安全

← [[04-互動介面與快捷鍵]] | [[00-Index]] | 下一篇 → [[06-CLAUDE-md與記憶系統]]

> ⚠️ **這章是全套教學裡最該讀懂的一章。** 你的 vault 會直接 push main 觸發網站重建，刷題網站有 2000 題醫學內容——權限設錯的代價是實質的。

---

## 六種權限模式

當 Claude 要改檔案、跑指令、或發網路請求時，它會停下來問你。**權限模式決定它多常停。**

| 模式 | 不用問就能做的事 | 適合 |
|---|---|---|
| `default`（介面上叫 **Manual**）| **只有讀取** | 剛開始、敏感工作 |
| `acceptEdits` | 讀取、改檔案、常見檔案系統指令（`mkdir` `touch` `mv` `cp` `rm` `rmdir` `sed`）| 你會事後 review 的迭代 |
| `plan` | 讀取（+ auto mode 可用時，classifier 核准的指令）| **改動前先探索** |
| `auto` | 幾乎全部，但有背景安全檢查 | 長任務、減少打斷 |
| `dontAsk` | 只有你事先核准的工具 | 鎖死的 CI / 腳本 |
| `bypassPermissions` | **全部** | **只能在隔離容器 / VM** |

> 📌 `default` 這個值在 CLI 介面上顯示為 **Manual**，`manual` 是可接受的別名（`claude --permission-mode manual` 也行）。設定檔和 hook / SDK 用的值仍然是 `default`。

---

## 怎麼切

**Session 中**：按 `Shift+Tab` 循環 `default` → `acceptEdits` → `plan`。狀態列會顯示：

- `⏸ manual mode on`（灰色）
- `⏵⏵ accept edits on`
- `⏸ plan mode on`
- `⏵⏵ auto mode on`
- `⏵⏵ don't ask on`
- `⏵⏵ bypass permissions on`

⚠️ 不是每個模式都在預設循環裡：
- `auto`：帳號符合條件時才出現
- `bypassPermissions`：要用 `--permission-mode bypassPermissions` / `--dangerously-skip-permissions` / `--allow-dangerously-skip-permissions` 啟動過才會進循環
- `dontAsk`：**永遠不在循環裡**，只能用 `--permission-mode dontAsk` 設

**啟動時**：
```bash
claude --permission-mode plan
```

**設成預設**（`~/.claude/settings.json`）：
```json
{ "permissions": { "defaultMode": "plan" } }
```

---

## Plan mode（你最該養成習慣的那個）

Plan mode 叫 Claude **研究並提出計畫，但不動你的原始碼**。它會讀檔案、跑指令探索、寫出計畫，然後停下來問你。

進入：`Shift+Tab`，或單次 prompt 前綴 `/plan`。

計畫做好後它會問你怎麼繼續：

- **Yes, and use auto mode** — 核准並進 auto mode（auto 不可用時顯示為 "Yes, auto-accept edits"）
- **Yes, manually approve edits** — 核准，但每個編輯都要你點頭
- **No, refine with Ultraplan on Claude Code on the web** — 丟到網頁做瀏覽器版審閱
- **No, keep planning** — 繼續留在 plan mode，告訴它要改什麼

> 💡 `Ctrl+G` 可以**把計畫開在你的文字編輯器裡直接改**，再讓 Claude 照改過的計畫做。這招在「它的計畫 80% 對、但有兩步不能接受」時特別有用。

核准計畫也會**自動用計畫內容幫 session 命名**（除非你已經用 `--name` 或 `/rename` 設過）。

---

## Auto mode（有背景 classifier 把關）

Auto mode 讓 Claude 不用停下來問，但有**另一個 classifier 模型**在每個動作執行前審查，擋掉：超出你要求範圍的、指向不認識的基礎設施的、看起來是被讀到的惡意內容驅動的動作。

**預設會擋的（節選跟你有關的）**：

- 下載並執行程式碼（`curl | bash`）
- 把敏感資料送到外部端點
- 正式環境部署與 migration
- 大規模刪除
- **`git reset --hard`、`git checkout -- .`、`git restore .`、`git clean -fd`、`git stash drop/clear`**（會丟掉未 commit 的變更）
- **force push**
- `git commit --amend` 於「不是這個 session 建立的 commit」或「已經 push 過的 commit」
- 把 secret 送出 repo 的 commit / push
- 印出活的憑證或 token 到 transcript 或檔案
- 對 Claude Code 自己的 transcript（`~/.claude/projects/` 底下的 `.jsonl`）寫入

**預設允許的**：

- 工作目錄內的本機檔案操作
- 安裝 lock file / manifest 裡宣告的相依
- 讀 `.env` 並把憑證送給對應的 API
- 唯讀 HTTP 請求
- **push 到你正在工作的那個 repo 的任何分支（含預設分支）**——但名字看起來像部署目標的分支（`production`、`gh-pages`）會被個別判斷

### 你在對話裡講的界線也算數 ⭐

> classifier 把**你在對話中說出的界線當成阻擋訊號**。你說「不要 push」或「等我 review 再部署」，即使預設規則允許，它也會擋下相符的動作。界線會一直有效直到你在後續訊息裡解除。

⚠️ 但這**不是**硬保證：界線不是存成規則，classifier 每次都從 transcript 重讀。**如果 `/compact` 把那則訊息壓掉了，界線就沒了。** 要硬保證請用 deny rule。

### 什麼時候會退回問你

classifier 連續擋 3 次、或累計擋 20 次，auto mode 就會暫停、恢復詢問。這個閾值不可設定。

---

## `bypassPermissions`：什麼時候都不要在你的機器上用 ⚠️

> 官方警告：**只在隔離環境使用**——容器、VM、沒有網路的 dev container。

它連 [protected paths](#protected-paths受保護路徑) 的寫入都放行。而且：

> `bypassPermissions` 對 prompt injection 或非預期動作**沒有任何保護**。

Linux / macOS 上以 root 或 sudo 執行時，Claude Code 會**拒絕**用這個模式啟動。

👉 **你的機器上有醫學筆記、理財對帳單資料、兩個會自動部署的 repo。這個模式對你沒有正當使用情境。**

---

## Protected paths（受保護路徑）

有一小組路徑的寫入**永遠不會被自動核准**（除了 `bypassPermissions`）：

| 模式 | 對 protected path 的寫入 |
|---|---|
| `default`、`acceptEdits` | 詢問 |
| `plan` | 詢問 |
| `auto` | 交給 classifier |
| `dontAsk` | 拒絕 |
| `bypassPermissions` | 允許 |

**受保護目錄**：`.git`、`.config/git`、`.vscode`、`.idea`、`.husky`、`.cargo`、`.devcontainer`、`.yarn`、`.mvn`、`.claude`（`.claude/worktrees` 除外）

**受保護檔案**：`.gitconfig`、`.gitmodules`、各種 shell rc（`.bashrc`、`.zshrc`、`.profile`、`.envrc`…）、`.npmrc`、`.yarnrc`、`bunfig.toml`、`.bazelrc`、`.pre-commit-config.yaml`、`lefthook.*`、`gradle-wrapper.properties`、`.devcontainer.json`、`.ripgreprc`、`pyrightconfig.json`、**`.mcp.json`、`.claude.json`**

> ⚠️ `settings.json` 裡的 `permissions.allow` 規則**不能**預先核准 protected path 的寫入——安全檢查跑在 allow 規則之前。

---

## 權限規則（allow / ask / deny）

模式設的是基準，**規則疊在上面**。用 `/permissions` 管理，或寫在 `settings.json`：

```json
{
  "permissions": {
    "defaultMode": "plan",
    "allow": [
      "Bash(git status)",
      "Bash(git diff *)",
      "Bash(python3 tools/validate.py)",
      "Read"
    ],
    "ask": [
      "Bash(git push *)"
    ],
    "deny": [
      "Bash(git push --force *)",
      "Bash(rm -rf *)",
      "Edit(.quartzsite/**)"
    ]
  }
}
```

規則語法重點：

- **尾巴的 ` *` 是前綴比對**，而且**空格很重要**：`Bash(git diff *)` 比對任何以 `git diff ` 開頭的指令；`Bash(git diff*)` 會連 `git diff-index` 一起中。
- **deny 規則和明確的 ask 規則在每個模式都生效**，包含 `bypassPermissions`。
- allow 規則在 `bypassPermissions` 下沒意義（反正全都允許了）。
- 進入 auto mode 時，**會授予任意程式碼執行的寬鬆 allow 規則會被丟掉**：`Bash(*)`、`Bash(python*)` 這種、套件管理器 run 指令、`Agent` allow 規則。窄的規則如 `Bash(npm test)` 保留；離開 auto mode 時丟掉的會還原。

### 👉 給你兩個 repo 的建議 deny 規則

`Obsidian-med-note/.claude/settings.json`：
```json
{
  "permissions": {
    "deny": [
      "Edit(.quartzsite/**)",
      "Bash(git push --force *)",
      "Bash(git push -f *)"
    ],
    "ask": [
      "Bash(git push *)"
    ]
  }
}
```

理由直接對應 `CLAUDE.md` §6「不要動 `.quartzsite/`」和 §5「rebase 衝突要停手、絕不覆蓋使用者筆記」。**規則是硬的，CLAUDE.md 是軟的**——把最不能出錯的那兩條做成規則。

---

## 用 hook 做更硬的控制

規則是路徑 / 指令比對。要更複雜的判斷（例如「不准改今天使用者正在編輯的那篇筆記」），用 **`PreToolUse` hook**——它是 shell 指令，可以擋下工具呼叫。見 [[09-Hooks自動化]]。

> 🔑 **記住這個層級**：
> `CLAUDE.md`（軟：上下文）< 權限規則（硬：路徑比對）< hook（硬：任意邏輯）

---

## 實務建議：三段式工作流

```
1. plan mode  →  讓它研究、提計畫（不動檔案）
2. 看計畫，必要時 Ctrl+G 直接改
3. 核准 → acceptEdits 讓它做完
4. git diff 檢查 → 自己 commit（或叫它 commit）
```

**不要一開始就 auto mode。** auto mode 適合「你已經信任這個方向、只是不想一直被打斷」的階段，不適合探索期。

---

## 🔗 相關筆記

- [[04-互動介面與快捷鍵]] — 上一步（`Shift+Tab` 在這裡）
- [[06-CLAUDE-md與記憶系統]] — 下一步
- [[09-Hooks自動化]] — 硬保證的做法
- [[12-設定檔與CLI旗標速查]] — `settings.json` 完整結構
- [[13-實戰-套用在兩個repo]] — 實際該設哪些規則

---

*最後更新：2026-08-04*
