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 檔案~/.claude/settings.json.claude/settings.json.claude/settings.local.json)的 hooks 區塊。也可以綁在 skill 或 subagent 的 frontmatter 裡。

基本結構:

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

在 session 裡看目前設定:

/hooks

全部 hook 事件

事件觸發時機
SessionStartsession 開始或 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一整批平行工具呼叫都結束後、下一次模型呼叫前
NotificationClaude Code 送通知時
MessageDisplay助理訊息文字顯示時
SubagentStart / SubagentStopsubagent 生成 / 結束
TaskCreated / TaskCompleted任務建立 / 標記完成
StopClaude 回覆完畢
StopFailure因 API 錯誤結束該輪(輸出與 exit code 會被忽略)
TeammateIdleagent team 的隊友即將 idle
InstructionsLoadedCLAUDE.md 或 .claude/rules/*.md 載入 context 時 ← 除錯神器
ConfigChangesession 期間設定檔變更
CwdChanged工作目錄改變(例如 Claude 執行 cd
DirectoryAdded中途用 /add-dir 加目錄
FileChanged被監看的檔案在磁碟上變更(matcher 指定要看哪些檔名)
WorktreeCreate / WorktreeRemoveworktree 建立 / 移除。會取代預設的 git 行為
PreCompactcontext 壓縮前

Notification 事件的細分(用 matcher 比對):permission_promptidle_promptauth_successelicitation_dialogelicitation_completeelicitation_responseagent_needs_inputagent_completed


四個對你有用的實例

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

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

.claude/settings.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 的 JSON schema,本教學未逐欄複製)。

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

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

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

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

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

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

(WSL 上可以改成呼叫 powershell.exe 發 Windows 通知。)

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

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

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


官方文件裡還有的實例

  • 編輯後自動格式化程式碼
  • 壓縮後重新注入 contextPreCompact
  • 稽核設定變更
  • 目錄或檔案變更時重載環境(搭配 direnv 之類)
  • 自動核准特定權限提示

使用時的注意事項

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

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

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

🔗 相關筆記


最後更新:2026-08-04