---
title: "09 - Hooks 自動化"
type: note
specialty: Programming
tags: [claude-code-cli從0開始使用教學, 09-hooks, automation]
created: 2026-08-04
updated: "2026"
modified: 2026-08-04
---

# 09 - Hooks 自動化

← [[08-Subagents與平行工作]] | [[00-Index]] | 下一篇 → [[10-MCP與外部工具]]

---

## Hook 是什麼、為什麼重要

**Hook 是你定義的 shell 指令，Claude Code 在生命週期的特定時點執行它。**

> 🔑 **關鍵價值：確定性。** 某件事一定會發生，而不是靠 LLM 決定要不要做。
>
> 這就是 [[06-CLAUDE-md與記憶系統]] 那句話的解方——CLAUDE.md 是上下文（軟），hook 是執行（硬）。

三種 hook：
- **一般 hook**：跑 shell 指令
- **Prompt-based hook**：用 Claude 模型判斷條件（需要判斷而非死規則時）
- **Agent-based hook**：用一個 agent 評估

---

## 設定位置與格式

寫在 [settings 檔案](https://code.claude.com/docs/en/settings)（`~/.claude/settings.json`、`.claude/settings.json`、`.claude/settings.local.json`）的 `hooks` 區塊。也可以綁在 skill 或 subagent 的 frontmatter 裡。

基本結構：

```json
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "npx prettier --write \"$CLAUDE_FILE_PATHS\""
          }
        ]
      }
    ]
  }
}
```

在 session 裡看目前設定：

```
/hooks
```

---

## 全部 hook 事件

| 事件 | 觸發時機 |
|---|---|
| `SessionStart` | session 開始或 resume 時 |
| `Setup` | `--init-only`，或 `-p` 模式下的 `--init` / `--maintenance`。給 CI / 腳本的一次性準備 |
| `UserPromptSubmit` | 你送出 prompt 後、Claude 處理前 |
| `UserPromptExpansion` | 你打的指令展開成 prompt、送到 Claude 之前。**可以擋下展開** |
| **`PreToolUse`** | **工具呼叫執行前。可以擋下它** ← 最常用 |
| `PermissionRequest` | 工具呼叫需要權限決定時 |
| `PermissionDenied` | 被 auto mode classifier 拒絕時。回傳 `{retry: true}` 可讓模型重試 |
| `PostToolUse` | 工具呼叫成功後 |
| `PostToolUseFailure` | 工具呼叫失敗後 |
| `PostToolBatch` | 一整批平行工具呼叫都結束後、下一次模型呼叫前 |
| `Notification` | Claude Code 送通知時 |
| `MessageDisplay` | 助理訊息文字顯示時 |
| `SubagentStart` / `SubagentStop` | subagent 生成 / 結束 |
| `TaskCreated` / `TaskCompleted` | 任務建立 / 標記完成 |
| `Stop` | Claude 回覆完畢 |
| `StopFailure` | 因 API 錯誤結束該輪（輸出與 exit code 會被忽略）|
| `TeammateIdle` | agent team 的隊友即將 idle |
| **`InstructionsLoaded`** | CLAUDE.md 或 `.claude/rules/*.md` 載入 context 時 ← **除錯神器** |
| `ConfigChange` | session 期間設定檔變更 |
| `CwdChanged` | 工作目錄改變（例如 Claude 執行 `cd`）|
| `DirectoryAdded` | 中途用 `/add-dir` 加目錄 |
| `FileChanged` | 被監看的檔案在磁碟上變更（`matcher` 指定要看哪些檔名）|
| `WorktreeCreate` / `WorktreeRemove` | worktree 建立 / 移除。**會取代預設的 git 行為** |
| `PreCompact` | context 壓縮前 |

`Notification` 事件的細分（用 matcher 比對）：`permission_prompt`、`idle_prompt`、`auth_success`、`elicitation_dialog`、`elicitation_complete`、`elicitation_response`、`agent_needs_input`、`agent_completed`。

---

## 四個對你有用的實例

### 1. 擋下對受保護檔案的編輯 ⭐

**這是你最該裝的一個。** `Obsidian-med-note/CLAUDE.md` §6 說「不要動 `.quartzsite/`」——但那是軟規則。做成 hook 就是硬的：

`.claude/settings.json`：
```json
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Edit|Write|MultiEdit",
        "hooks": [
          {
            "type": "command",
            "command": "case \"$CLAUDE_FILE_PATHS\" in *.quartzsite/*) echo 'BLOCKED: .quartzsite/ 是 Quartz 框架設定，除非任務就是調網站否則不可修改' >&2; exit 2;; esac"
          }
        ]
      }
    ]
  }
}
```

> ⚠️ 這是示意寫法。實際部署前**自己先測一次**（`PreToolUse` 的擋下語義與輸入格式請對照官方 [hooks reference](https://code.claude.com/docs/en/hooks) 的 JSON schema，本教學未逐欄複製）。

### 2. 改完檔案自動更新 `modified` 日期戳

vault 的 `CLAUDE.md` §3 ⓪ 說每次改動筆記都要把 frontmatter 的 `modified` 設成當天。這是**典型的「一定要發生」**：

```json
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          { "type": "command", "command": "python3 .claude/scripts/stamp_modified.py \"$CLAUDE_FILE_PATHS\"" }
        ]
      }
    ]
  }
}
```

寫一支小腳本把日期蓋上去，**就再也不會忘記**——而這正是 `CLAUDE.md` §7 列出的「最常見錯誤」之一。

### 3. Claude 需要你輸入時發桌面通知

```json
{
  "hooks": {
    "Notification": [
      {
        "matcher": "permission_prompt|idle_prompt",
        "hooks": [
          { "type": "command", "command": "notify-send 'Claude Code' '需要你的輸入'" }
        ]
      }
    ]
  }
}
```

（WSL 上可以改成呼叫 `powershell.exe` 發 Windows 通知。）

### 4. 除錯：到底載入了哪些指示

```json
{
  "hooks": {
    "InstructionsLoaded": [
      { "hooks": [ { "type": "command", "command": "echo \"[$(date +%T)] instructions loaded\" >> ~/.claude/instructions.log" } ] }
    ]
  }
}
```

排查 path-scoped rules 或子目錄延遲載入時很有用。

---

## 官方文件裡還有的實例

- 編輯後自動格式化程式碼
- **壓縮後重新注入 context**（`PreCompact`）
- 稽核設定變更
- 目錄或檔案變更時重載環境（搭配 direnv 之類）
- 自動核准特定權限提示

---

## 使用時的注意事項

- **Hook 是以你的身分執行的 shell 指令。** 寫錯 = 真的會壞事。先在安全的地方測。
- **`WorktreeCreate` / `WorktreeRemove` 會取代預設 git 行為**——除非你確定要自訂，否則不要碰。
- Hook 出錯會讓 session 行為異常。**設定改壞了用 `claude --safe-mode` 開起來救**。
- 完整的事件 schema、JSON 輸入 / 輸出格式、async hook、MCP tool hook 見官方 [Hooks reference](https://code.claude.com/docs/en/hooks)。本教學只涵蓋觀念與常用事件。

---

## 什麼時候用 hook、什麼時候用別的

| 需求 | 用什麼 |
|---|---|
| 「一定要在 X 之前 / 之後發生」 | **Hook** |
| 「不准碰某個路徑」 | **權限 deny 規則**（更簡單）或 `PreToolUse` hook（更靈活）|
| 「這個專案的慣例是…」 | **CLAUDE.md** |
| 「這個多步驟流程是這樣跑的」 | **Skill** |
| 「這類任務交給專門的助手」 | **Subagent** |

---

## 🔗 相關筆記

- [[08-Subagents與平行工作]] — 上一步
- [[10-MCP與外部工具]] — 下一步
- [[06-CLAUDE-md與記憶系統]] — 為什麼 CLAUDE.md 不是硬保證
- [[05-權限模式與安全]] — 權限規則 vs hook
- 官方 Hooks reference：<https://code.claude.com/docs/en/hooks>

---

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