這個單元解決什麼問題Hook 是在工具執行前後、session 起訖、prompt 提交等 30 個生命週期事件點自動跑的確定性腳本:格式化、驗證、攔截、防護網。它把「每次都要記得做」的事從模型軟約束變成系統硬保證。Claude Code v2.1 起 hook 系統大幅擴充:30 個事件、五種 handler 類型(command / http / mcp_tool / prompt / agent)、與 exit code 2 攔截語義。本單元講主要觸發點語義、
settings.json 配置、實戰範本,以及 hook 作為可執行碼所附帶的供應鏈風險與掃描 SOP。學習目標
- 說出 Claude Code hook 的 30 個事件按觸發時機分組,並指出 PreToolUse、PostToolUse、Stop、SessionStart 的語義與典型用途。
- 正確撰寫
settings.json的hooks設定,含matcher與command,並能區分matcher的三種解析規則。 - 用
exit 2攔截 PreToolUse 工具呼叫,以及用additionalContext為 Claude 注入額外 context。 - 辨識 hook 作為外部可執行碼的供應鏈風險,並在引入第三方 hook 前做基本掃描。
- 用 hook 把本庫的
normalize_punctuation.py與validate_kb --hook接成確定性防護網。
1. Hook 是什麼:確定性自動化,補「不一定會記得」的缺口
CLAUDE.md 與 rules 是「請模型遵守」(軟約束、context 層)。Hook 是「系統強制執行」(硬保證、shell 層)。它不在模型的推理鏈內:hook 跑在你 shell 上、讀 stdin 上的工具輸入 JSON、決定要不要放行這次工具呼叫,模型預設不知道 hook 在跑。你用 additionalContext 主動告知時例外。
三個關鍵事實:
- Hook 是確定性的:不靠模型「記得」或「判斷」,shell 該 exit 2 就是 exit 2。每次都一樣。
- Hook 是可執行程式碼:裝 hook 等同於把一段 shell 指令加進你的工作流,這是供應鏈面的入口。
- Hook 的觸發點遠比一般認得多:截至 2026-06 共 30 個事件,按觸發節奏分四組 [1]。
2. 30 個觸發事件分組
Claude Code v2.1 起 hook 系統涵蓋 30 個事件([1]),按觸發節奏分四組。2.1 每次 session 一次
2.2 每次對話輪次一次
2.3 每個工具呼叫一次(agentic loop 內)
2.4 Subagent / task 事件
2.5 異步 / side-channel
3. 配置:settings.json 結構
Hook 設定在 settings.json 的 hooks 區塊,三層巢狀:事件 → matcher group → hook handlers([1])。
3.1 五種 handler 類型
type 欄位決定 handler 怎麼跑([1]):
預設
type 為 command,省略 type 等同顯式指定 command。
3.2 設定位置與 scope
3.3 matcher 語法
matcher 解析規則按字元自動選擇([1]):
每個事件 match 不同欄位:
- 工具事件(PreToolUse / PostToolUse 等)match
tool_name SessionStartmatch 來源(startup/resume/clear/compact)Notificationmatch 類型FileChanged是字面檔名(非 regex / 非 exact-list)- 沒有 matcher 機制的事件(UserPromptSubmit、PostToolBatch、Stop、TeammateIdle、TaskCreated、TaskCompleted、WorktreeCreate、WorktreeRemove、MessageDisplay、CwdChanged):always fire 或 always ignored if matcher set
3.4 第二層篩選:if
if 欄位是 permission-rule 語法,提供更細的條件過濾([1]):
"Bash(rm *)"、"Edit(*.ts)"。不支援 && / || / 清單組合,要多條件時拆成多個 handler。
4. 輸入:stdin 上的 JSON
所有command hook 從 stdin 收到統一格式的 JSON([1]);http hook 收到 POST body。
基本 shape:
--agent 或 Subagent 內執行時,會附加 agent_id 與 agent_type。只有 SessionStart 會收到 model 欄位 [1]。
4.1 路徑佔位符
用args exec 形式避免 quoting 問題([1]):
${CLAUDE_PROJECT_DIR}:專案根${CLAUDE_PLUGIN_ROOT}:plugin 安裝目錄${CLAUDE_PLUGIN_DATA}:plugin 持久資料${user_config.*}:plugin 使用者設定
5. Exit code 與決策
command hook 透過 exit code 表態([1]):
5.1 exit 2 阻擋效果一覽
不是所有事件都把 exit 2 視為阻擋。真正會擋下的事件([1]):
PreToolUse→ 阻擋工具呼叫UserPromptSubmit→ reject 並清除 promptUserPromptExpansion→ 阻擋 expansionStop/SubagentStop/TeammateIdle→ 防止停止PreCompact→ 阻擋 compactPostToolBatch→ 在下個 model call 前停止 agentic loopWorktreeCreate→ 任何非零 exit 都 fail creation
exit 2 對 PostToolUse / PostToolUseFailure / Notification 等無阻擋效果,只顯示 stderr。多數 Unix 直覺是「exit 1 是錯誤」,但 Claude Code hook 系統把 exit 1 當非阻斷錯誤。要強制擋下請用 exit 2。
5.2 為 Claude 注入額外 context
回傳 JSON 帶hookSpecificOutput.additionalContext 給 Claude 看(需有對應的 hookEventName)([1]):
SessionStart/Setup/SubagentStart→ 對話開頭UserPromptSubmit/UserPromptExpansion→ 跟著 promptPreToolUse/PostToolUse*/PostToolBatch→ 跟著工具結果
5.3 通用 JSON 輸出欄位
5.4 決策控制模式(不同事件用不同欄位)
6. 五個實戰範本
6.1 PreToolUse 攔截危險 Bash
settings.json:
6.2 PostToolUse 自動格式化(本庫用法)
路徑從 stdin 取,不靠帶路徑的環境變數上例的腳本自行掃描待處理檔案。若要對「剛編輯的單檔」處理,從 stdin 的 hook 輸入 JSON 解出
.tool_input.file_path(見第 4 節的 jq 範例)。Claude Code 不提供 $CLAUDE_TOOL_INPUT_FILE_PATH 這類帶路徑的環境變數(截至 2026-06);可在 command 字串內展開的是 ${CLAUDE_PROJECT_DIR}、${CLAUDE_PLUGIN_ROOT}、${CLAUDE_PLUGIN_DATA} 等定址變數 [1]。6.3 Stop 跑收尾驗證(本庫用法)
validate_kb.py --hook 是 Stop hook 模式:有 CRITICAL/HIGH 才擋下、工具錯誤 fail-open 不誤傷正常流程。它在本庫作為確定性防護網,即使自然語言驅動的自主檢核漏跑,回合結束時仍會擋下。
6.4 SessionStart 注入環境變數
SessionStart hook 可透過$CLAUDE_ENV_FILE 環境變數(指向 session 專屬暫存檔)持久化環境變數 [1]:
SessionStart / Setup / CwdChanged / FileChanged 可用)。
6.5 工具呼叫 log(PostToolUse)
7. Skill / Subagent frontmatter 內的 hook
不只是settings.json,Skill 與 Subagent 的 frontmatter 內可宣告 hook,只在該 Skill / Subagent 生命週期內生效([1]):
8. 進階:HTTP / MCP / prompt handler
8.1 HTTP handler 範本
allowedEnvVars 是白名單:只暴露列出的環境變數給 hook。不要在 headers 直接寫值(會進 plugin 設定檔),用 $VAR 引用環境變數 [1]。
8.2 MCP tool handler 範本
8.3 prompt handler 範本
9. 安全:hook 是可執行碼,外部來源即供應鏈面
Hook 的command 欄位直接由 shell 執行。安裝來路不明的 hook 等同於把第三方程式碼的執行權交出去。
9.1 已知威脅
- CVE-2025-59536(CVSS 8.7):
.claude/內的程式碼在使用者核准信任對話前已執行。已於 Claude Code v1.0.111+ 修復 [2]。未更新版本有被預置惡意指令的風險。 - CVE-2026-21852:攻擊者控制的 app 改寫
ANTHROPIC_BASE_URL,把 API 流量導向他處並在 trust 前外洩 API key。修於 v2.0.65+ [2]。 - Snyk ToxicSkills(2026-02):公開 skill 中 36% 含 prompt injection。Hook 與 skill 同屬供應鏈面,引入前先掃描。
9.2 引入外部 hook 前必跑的掃描
9.3 最小權限原則
Hook 的command 只授予完成任務所需的最小存取:
- 不要在 hook 內讀
~/.ssh、~/.aws、**/.env*。這些路徑都該在permissions.deny阻擋。 - 不要讓 hook 寫到 repo 外,用
${CLAUDE_PROJECT_DIR}限定在專案內。 - 用
allowedEnvVars白名單環境變數(HTTP handler),不要把整個 process env 暴露。
9.4 版本與 managed 政策
disableAllHooks: true在 settings 可暫時關掉所有 hook(managed 級 hook 只能由 managed 級設定關掉)[1]。- 組織可用
allowManagedHooksOnly: true擋下使用者 / 專案 / plugin 層 hook(plugin 透過enabledPlugins強制啟用者除外)。 - 保持 Claude Code >= v2.0.65(CVE-2026-21852 修復版)+ >= v2.1.139(hook 改用
systemMessage/terminalSequence而非直接寫/dev/tty)[1, 2]。
10. 工具對照
各家工具對 hook 機制的支援差異極大(截至 2026-06):命名澄清與邊界
- Claude Code 的 hook 系統截至 2026-06 是 30 個事件的完整生命週期鉤子([1]);其他 CLI 工具的「hook」多指 command hook 一類,事件數遠少。
- OpenAI Codex、Antigravity、GitHub Copilot CLI 的 hook 機制演進快,使用前以各家當前官方文件為準。
- Cursor 截至 2026-06 未在 CLI / IDE 提供一等公民的 hook 機制;本 Playbook 短提一欄。
- 本庫的
validate_kb --hook(Stop 模式)以本表主範本(Claude Code)的語意設計。
11. 自我檢核動手做
30 分鐘練習
- PostToolUse 自動格式化:照本庫的
PostToolUse範本,在.claude/settings.json接上normalize_punctuation.py,編輯任一.md觀察自動正規化。 - PreToolUse 攔截危險 Bash:寫
block-rm.sh與對應設定;嘗試讓 Claude 跑rm -rf /tmp/xxx觀察permissionDecision: deny與給 Claude 的 reason。 - Stop 收尾驗證:接上
validate_kb.py --hook,故意製造一個 frontmatter 缺updated欄的單元,觀察 Stop hook 擋下並回報。 - 供應鏈掃描:在
~/.claude/與.claude/跑本節的rg掃描,確認沒有可疑外連、沒有隱藏 Unicode。 - SessionStart 注入 env:寫一個 SessionStart hook 透過
CLAUDE_ENV_FILE設MY_FLAG=1,在新 session 跑echo $MY_FLAG驗證生效。
12. 常見誤區
自我檢核
通過本單元的標準
- 你能說出 hook 與
CLAUDE.md/ rules 的根本差別嗎?(shell 確定性 vs. context 軟約束) - 你能在 5 分鐘內寫出一個
PreToolUse攔截git commit含.env的 hook 嗎? - 你能說出
exit 0/exit 2/ 其他 exit code 在不同事件的語義嗎? - 你能說出 hook 作為可執行程式碼的三條供應鏈防護 SOP 嗎?
- 在你目前的工作流中,有哪一件「每次應該做但不一定記得做」的事,可以改用 PostToolUse 或 Stop hook 來保證?說出觸發事件、要跑的指令、以及選 PostToolUse 還是 Stop 的理由。
來源與延伸閱讀
事實主張依官方文件,快變動項標註截至 2026-05。-
[1] Anthropic, “Hooks,” code.claude.com, 2026. [Online]. Available: https://code.claude.com/docs/en/hooks (截至 2026-06;含 30 個事件、五種 handler 類型、matcher 三模式解析、
exit 2阻擋語義、additionalContext注入、v2.1.139+改用terminalSequence) - [2] Anthropic, “Claude Code release notes,” code.claude.com, 2026. [Online]. Available: https://code.claude.com/docs/en/changelog (截至 2026-06;CVE-2025-59536 與 CVE-2026-21852 修復版本)
-
[3] Anthropic, “Extend Claude with skills,” code.claude.com, 2026. [Online]. Available: https://code.claude.com/docs/en/skills (截至 2026-06;Skill frontmatter 內
hooks設定) -
[4] Anthropic, “Create custom subagents,” code.claude.com, 2026. [Online]. Available: https://code.claude.com/docs/en/subagents (截至 2026-06;Subagent frontmatter 內
hooks與Stop→SubagentStop自動轉換)
- 設定層級模型見 02-1 設定的層級模型。
CLAUDE.md軟約束與 hook 硬保證的分工見 04-1 CLAUDE.md 與記憶檔。- rules path-scoped 機制見 04-2 rules。
- Skill frontmatter 內 hook 見 04-4 Skill。
- Subagent 生命週期 hook 見 04-5 Subagent。
- 供應鏈風險見 03-3 安全、隱私與供應鏈風險。