← 所有文章
claudeClaude Code

讓 AI 改你的程式碼前,先跑你定的規則

你剛讓 Claude 幫你改了一個檔案,結果 ESLint 噴了 30 個錯誤。或者更慘——Claude 下了一個 rm -rf 你來不及攔。
每次都靠自己盯著螢幕按確認,遲早會漏。Claude Code Hooks 讓你寫一段 shell script,AI 每次動手前後自動跑。格式化、lint、安全檢查、通知——你定規則,它照做。

這篇你會學到

你需要什麼

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 -rfgit push --forceDROP 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 內建功能,不需要額外安裝。

  1. 確認 Claude Code 版本 ≥ v2.1.85(claude --version
  2. 在專案目錄建 .claude/settings.json
  3. hooks 區塊加你的規則
  4. 重啟 session 讓設定生效
    完整的 hook 事件格式、JSON schema、進階用法在 Claude Code Hooks 官方文件
← 所有文章OctoDock 首頁 →