你剛讓 Claude 幫你改了一個檔案,結果 ESLint 噴了 30 個錯誤。或者更慘——Claude 下了一個 rm -rf 你來不及攔。
每次都靠自己盯著螢幕按確認,遲早會漏。Claude Code Hooks 讓你寫一段 shell script,AI 每次動手前後自動跑。格式化、lint、安全檢查、通知——你定規則,它照做。
這篇你會學到
- Hooks 是什麼、跟 CLAUDE.md 的差別在哪
- 四種 hook 時機點怎麼選
- 三個實用範例:自動 lint、阻擋危險指令、條件式觸發
- 做不到什麼(先說清楚限制)
你需要什麼
- Claude Code v2.1.85 以上(條件式 hooks 需要這版)
- 基本的 shell scripting 能力
- 一個你想自動化的規則
Hooks 跟 CLAUDE.md 差在哪
CLAUDE.md 是建議——你寫了規則,Claude 盡量遵守,但它可能忘記或判斷不同。
Hooks 是強制——shell script 在 Claude 動手前後自動跑,回傳非零就擋掉。不靠 AI 判斷,靠程式碼執行。
什麼時候用 CLAUDE.md:程式碼風格偏好、命名慣例、架構方向。什麼時候用 Hooks:必須 100% 執行的規則、安全檢查、自動化流程。
四種 Hook 時機
PreToolUse — AI 要用工具之前觸發。拿來阻擋危險指令、驗證參數。
PostToolUse — AI 用完工具之後觸發。拿來自動 lint、格式化、記錄操作。
Notification — AI 需要你注意的時候。拿來做桌面通知、手機推播。
UserPromptSubmit — 你送出 prompt 的時候。拿來自動附加 context、設 session 標題。
存檔後自動跑 ESLint
每次 Claude 寫完檔案,自動跑 lint。發現錯誤就回報給 Claude 讓它自己修。
在 .claude/settings.json 加這段:
{ "hooks": { "PostToolUse": [{ "hooks": [{ "type": "command", "command": "npx eslint --fix $TOOL_INPUT_FILE 2>&1 || true" }] }] } }💡
|| true很重要。如果 hook 回傳非零 exit code,Claude 會把操作當失敗。加|| true讓 lint 結果回報但不阻擋,Claude 看到錯誤會自己���。
阻擋危險的 shell 指令
Claude 要跑 rm -rf、git push --force、DROP TABLE 時,直接擋掉。
{ "hooks": { "PreToolUse": [{ "hooks": [{ "if": "Bash(*)", "type": "command", "command": ".claude/hooks/block-dangerous.sh" }] }] } }
.claude/hooks/block-dangerous.sh 的內容:
#!/bin/bash COMMAND=$(cat | jq -r '.tool_input.command // empty') if echo "$COMMAND" | grep -qE 'rm -rf|--force|DROP TABLE|truncate'; then echo "⛔ 被 hook 攔截了:$COMMAND" exit 2 fi⚠️ exit code 意義不同:exit 0 = 放行,exit 2 = 阻擋並告訴 Claude 原因。其他非零 = hook 本身出錯,Claude 會看到錯誤但不被阻��。
條件式 Hooks:只在 git commit 時檢查
不想每個 bash 指令都觸發 hook?用 if 欄位限定範圍。
{ "hooks": { "PreToolUse": [{ "hooks": [{ "if": "Bash(git commit *)", "type": "command", "command": ".claude/hooks/lint-staged.sh" }] }] } }
這樣 hook 只在 Claude 跑 git commit 時觸發,其他 bash 指令完全不受影響。大幅減少延遲。
讓它更穩的幾個細節
💡 Hooks 支援三種判斷邏輯。除了 shell script,還有 prompt-based hook(用 Claude 模型判斷)和 agent-based hook(用完整 agent 評估)。不是所有規則都適合寫 if/else——有些需要理解 context 的判斷,交給 AI 反而更準。
💡 Hook 的 stdin 是完整的 JSON。包含工具名稱、輸入參數,用jq解析就能做比if欄位更精細的條件判斷。
💡 MCP 工具也能掛 hook。不只 Bash、Read、Write——任何 MCP server 的工具呼叫都會觸發 PreToolUse / PostToolUse。
做不到什麼
❌ Hook 不能改 Claude 的回覆內容。它能攔截工具呼叫、能把結果回報給 Claude,但不能直接修改 Claude 對你說的話。
❌ Hook 跑太慢會拖垮體驗。每個 hook 都是同步執行的。如果你的 lint script 要跑 10 秒,Claude 每次改檔案都要等 10 秒。保持 hook 輕量。
❌ Hook 不會跨 session 記住狀態。每次 session 重新讀 settings.json。需要狀態就自己寫檔案管理。
工具設定
Hooks 是 Claude Code 內建功能,不需要額外安裝。
- 確認 Claude Code 版本 ≥ v2.1.85(
claude --version) - 在專案目錄建
.claude/settings.json - 在
hooks區塊加你的規則 - 重啟 session 讓設定生效
完整的 hook 事件格式、JSON schema、進階用法在 Claude Code Hooks 官方文件。