Hooks 與自動化:事件驅動的行為擴充

了解如何透過掛鉤機制,在 Claude Code 的事件節點上附加自訂行為——從 shell 命令到 LLM 驗證——不改核心就能擴展工作流。

90 秒總覽

Hooks 系統讓使用者在 Claude Code 的事件節點上掛載自動化行為:可以是 shell 命令、LLM 提示、HTTP 呼叫,或完整的代理驗證迴圈。所有掛鉤透過 settings.json 配置,以「事件 → 匹配器 → 掛鉤」三層管線運作。匹配器重用權限規則語法,掛鉤支援同步、非同步、一次性等執行模式。掌握這套管線,就能在不修改核心程式碼的前提下擴充任何工作流。

執行路徑(主骨架)

input: 事件觸發(例如 PreToolUse)
載入 settings.json 中對應事件的 matcher 列表
for each matcher:
  if matcher.if 條件匹配當前工具/參數:
    for each hook in matcher.hooks:
      依 hook 類型執行:
        command → 執行 shell 命令(含 timeout)
        prompt  → 送 LLM 提示($ARGUMENTS 展開)
        http    → POST 至指定 URL(含 headers)
        agent   → 啟動完整代理驗證迴圈
      回傳結果供主流程決策
flowchart TD
  A[事件觸發] --> B[載入 Matcher 列表]
  B --> C{條件匹配?}
  C -->|否| D[跳過]
  C -->|是| E[執行 Hook]
  E --> F{Hook 類型}
  F -->|command| G[Shell 命令]
  F -->|prompt| H[LLM 提示]
  F -->|http| I[HTTP POST]
  F -->|agent| J[代理驗證]
  G --> K[回傳結果]
  H --> K
  I --> K
  J --> K
// settings.json 掛鉤配置範例
// "if" 使用權限規則語法:Bash(git *) 表示匹配所有以 git 開頭的 Bash 指令
{
  "hooks": {
    "PreToolUse": [
      {
        "if": "Bash(git *)",
        "hooks": [
          {
            "type": "command",
            "command": "echo '即將執行 git 指令'",
            "timeout": 5000
          }
        ]
      }
    ]
  }
}

三層管線的關鍵:事件決定「何時」、匹配器決定「對誰」、掛鉤決定「做什麼」。

flowchart LR
  subgraph 三層管線
    E[Event
何時觸發] --> M[Matcher
對誰觸發] M --> H[Hook
做什麼] end

路徑判讀重點

  • 事件名稱固定(PreToolUse、PostToolUse、PreMessage、PostMessage 等),不可自訂。
  • 匹配器 if 欄位重用權限規則語法,例如 Bash(git *)
  • 每個匹配器可掛載多個 hook,按陣列順序依次執行。
  • hook 執行結果回傳主流程,可影響後續工具調用決策。

關鍵決策(為什麼這樣設計)

決策 1:事件-匹配器-掛鉤三層架構

原因:將「何時」、「對誰」、「做什麼」三個關注點分離。使用者可以在同一事件上掛載多組匹配器,每組匹配器再各自掛載多個掛鉤,組合彈性極高。

代價:配置結構比扁平陣列深一層,初次接觸需要理解巢狀邏輯。

決策 2:使用權限規則語法做條件匹配

原因:權限系統已有一套成熟的 pattern-matching 語法(如 Bash(git *))。掛鉤匹配器直接重用,降低使用者學習成本,也減少程式碼重複。

代價:匹配器的能力受限於權限語法的表達力;若需要更複雜的條件(如多欄位交叉比對),現有語法不夠用。

決策 3:非同步與一次性模式

原因:async: true 讓耗時掛鉤不阻塞主流程;once: true 讓僅需執行一次的初始化掛鉤自動移除,避免重複觸發。asyncRewake: true 則在背景完成後透過 exit code 2 喚醒模型,兼顧效能與回饋。

代價:非同步掛鉤的執行結果無法同步影響當前決策;一次性掛鉤在配置檔中被自動移除,可能讓不知情的使用者困惑。

替代方案與取捨

方案 優點 缺點 為何未採用/何時可採用
外掛系統(Plugin System) 能力更強,可注入任意邏輯 安全邊界複雜,載入管理成本高 適合需要深度整合的場景;目前掛鉤已覆蓋多數自動化需求
全觸發(Always-fire)無匹配器 配置簡單,不需學習匹配語法 每個事件都觸發所有掛鉤,效能浪費且難以精準控制 掛鉤數量極少時可行,規模增長後匹配器必不可少
純同步執行(Sync-only) 執行順序可預測,除錯容易 耗時掛鉤阻塞主流程,使用體驗變差 所有掛鉤都很快時可行,但實務中常需背景執行
環境變數全開放(無 allowlist) 配置更簡單,不需逐一宣告 HTTP hook 可能洩漏敏感環境變數 安全性考量下不可採用;顯式 allowlist 是必要防護

失敗路徑與防護

Failure 1:Hook 超時阻塞主流程

症狀:同步掛鉤執行時間超過預期,使用者操作卡頓或無回應。

防護:為 command hook 設定合理的 timeout 值;對可能耗時的操作使用 async: true,避免阻塞主線程。利用 statusMessage 顯示自訂 spinner 文字,讓使用者知道系統仍在運作。

Failure 2:HTTP hook 洩漏環境變數

症狀:HTTP hook 在 POST 請求中帶出未預期的環境變數,導致機密外洩。

防護:環境變數插值僅限顯式 allowlist 中列出的變數;HTTP hook 預設受限,不允許存取任意環境變數。配置審查時確認 allowlist 只包含必要項目。

Failure 3:非同步 hook 狀態污染

症狀:背景執行的掛鉤修改了共享狀態(如檔案系統或全域變數),導致後續回合行為不可預測。

防護:非同步掛鉤應設計為無副作用或僅操作隔離的資源。使用 asyncRewake: true 時,透過 exit code 控制是否需要模型介入,避免靜默污染。

實作驗證(你改完要怎麼確認)

  • settings.json 新增一個 PreToolUse command hook:確認對應工具被呼叫時掛鉤確實觸發。
  • 測試匹配器條件:修改 if 條件,確認只有符合 pattern 的工具調用才觸發掛鉤。
  • 驗證 async: true:確認非同步掛鉤不阻塞主流程,主回合正常推進。
  • 驗證 once: true:確認掛鉤第一次觸發後自動從配置中移除,不再重複執行。
  • 測試 HTTP hook allowlist:故意引用未列入 allowlist 的環境變數,確認被拒絕。
  • 模擬 hook 超時:設定極短 timeout,確認超時後主流程仍正常繼續。

這六步涵蓋「觸發、匹配、非同步、一次性、安全、容錯」,是掛鉤配置的最低可接受驗證集。

← 上一頁:提示系統 下一頁:終端 UI →