回到頂部

Claude Code Hooks 25 個觸發點實戰指南 2026:5 大類範例 + 組合模式 + 反模式

Claude Code Hooks 完整實戰:25 個 ready-to-copy 範例(品質 / 安全 / Git / 通知 / 一致性)、5 個 hook 組合模式、企業真實案例、5 個反模式避坑。

Hooks 60 秒理解

Hooks 是 Claude Code 的「事件驅動自動化機制——在 Claude 做特定動作前 / 後 / 出錯時自動執行你的 shell 腳本

為什麼重要:Hooks 是 Claude 的護欄——沒護欄你不敢讓它跑 production

對應 pocketos 9 秒刪庫事件——那次事件就是因為沒設 hook 攔截 rm -rf

Hooks vs CLAUDE.md vs Skills vs Slash Commands

機制解決什麼觸發
CLAUDE.md這個專案的全局規矩每次 session 自動讀
Skills特定任務的 SOPClaude 自動判斷該用
Slash Commands一鍵啟動的指令使用者輸入 /xxx
Hooks事件發生時的自動腳本特定事件被觸發
MCP外部工具的橋樑明確的 tool call

Hooks 的獨特定位:事件驅動 + 安全護欄——其他 3 個都不能做這件事

Hooks 三節奏

14 個官方事件分布在三個生命週期:

SessionStart → UserPromptSubmit

    [每輪對話]
   PreToolUse → ToolExecution → PostToolUse

    Stop / StopFailure

    SessionEnd

14 個官方事件速查表

事件觸發時機可阻擋?常見用途
SessionStart新 session 開始載入專案狀態、開 audit log
SessionEndsession 結束寫日誌、上傳 log
UserPromptSubmit使用者送出訊息掃 PII、攔截危險 prompt
PreToolUseClaude 將呼叫 tool 前攔截 rm / sudo / 危險指令
PostToolUsetool 執行完後跑 lint / format / 自動 commit
Stop任務完成發 Slack 通知、寫摘要
StopFailure任務失敗發警報、寫錯誤 log
Notification需要使用者輸入切到第二螢幕、Slack 通知
PreCompact壓縮 context 前備份原 context
PostCompact壓縮後寫摘要、驗證 context

注意:事件清單會隨 Claude Code 更新——官方文件 為準

安裝與第一個 hook(5 分鐘)

settings.json 結構

位置:~/.claude/settings.json(全域)或 <repo>/.claude/settings.json(專案)

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit",
        "command": "npx prettier --write ${tool.args.file_path}"
      }
    ]
  }
}

這個 hook 的意思:每次 Claude 用 Edit 工具改檔後,自動跑 prettier 格式化

驗證 hook 跑起來

# 在 Claude Code 內
> 改一個 .ts 檔的 import 順序
# 改完後檢查是否自動 prettier

Mason 註:第一次設 hook 建議用「顯眼的副作用(例如 echo 到 log file)——確認真的被觸發後再加複雜邏輯**。

🎯 25 個 ready-to-copy 觸發點(按任務分類)

這節是這篇文章對 SERP 最有殺傷力的章節——對手都按事件分類,Mason 按「你想做什麼分類

🅰️ 類別 A:程式品質與格式化(5 個)

1. Edit 後跑 prettier / black / gofmt

{
  "hooks": {
    "PostToolUse": [{
      "matcher": "Edit",
      "command": "npx prettier --write ${tool.args.file_path}"
    }]
  }
}

Python:black ${tool.args.file_path} Go:gofmt -w ${tool.args.file_path}

2. Edit 後跑 ESLint 並反饋給 Claude

{
  "hooks": {
    "PostToolUse": [{
      "matcher": "Edit",
      "command": "npx eslint ${tool.args.file_path} --fix; echo 'Lint check complete' >&2"
    }]
  }
}

stderr 輸出會傳回給 Claude——Claude 看到 lint 失敗會自己修

3. Edit 前確認檔案不在保護清單

{
  "hooks": {
    "PreToolUse": [{
      "matcher": "Edit",
      "command": "if grep -q '${tool.args.file_path}' .claude/protected-files.txt; then echo 'BLOCKED: protected file' >&2; exit 1; fi"
    }]
  }
}

.claude/protected-files.txt 列出絕不能改的檔案(資料庫 migration、production config 等)。

4. 寫 test 後自動跑 test suite

{
  "hooks": {
    "PostToolUse": [{
      "matcher": "Write",
      "command": "if [[ '${tool.args.file_path}' == *.test.* ]]; then npm test; fi"
    }]
  }
}

5. 寫 markdown 後跑 vale / textlint

{
  "hooks": {
    "PostToolUse": [{
      "matcher": "Edit|Write",
      "command": "if [[ '${tool.args.file_path}' == *.md ]]; then vale ${tool.args.file_path}; fi"
    }]
  }
}

Mason 站台用 vale 檢查中文標點 + 用詞一致性

🔴 類別 B:安全與危險指令攔截(5 個)

6. 攔 rm -rf / sudo / pkill

# .claude/hooks/pre-tool-use-block-dangerous.sh
#!/bin/bash
ARGS=$1
if [[ "$ARGS" == *"rm -rf"* ]] || [[ "$ARGS" == *"sudo"* ]] || [[ "$ARGS" == *"pkill"* ]]; then
  echo "BLOCKED: dangerous command detected" >&2
  exit 1
fi
{
  "hooks": {
    "PreToolUse": [{
      "matcher": "Bash",
      "command": "./.claude/hooks/pre-tool-use-block-dangerous.sh '${tool.args.command}'"
    }]
  }
}

這個 hook 是 pocketos 事件 的直接解藥

7. 攔對 production 環境的 deploy 指令

# .claude/hooks/pre-tool-use-block-prod-deploy.sh
#!/bin/bash
CMD=$1
if [[ "$CMD" == *"deploy"* ]] && [[ "$CMD" == *"prod"* ]]; then
  echo "BLOCKED: production deploy requires manual approval" >&2
  exit 1
fi

8. 攔接觸 .env / credentials.json

# .claude/hooks/pre-tool-use-block-secrets.sh
#!/bin/bash
FILE=$1
if [[ "$FILE" == *".env"* ]] || [[ "$FILE" == *"credentials"* ]] || [[ "$FILE" == *"secret"* ]]; then
  echo "BLOCKED: secret files cannot be read by Claude" >&2
  exit 1
fi

9. 強制 git status clean 才能跑 destructive 指令

#!/bin/bash
if [[ "$1" == *"git reset --hard"* ]] || [[ "$1" == *"git clean -fd"* ]]; then
  if ! git diff --quiet || ! git diff --cached --quiet; then
    echo "BLOCKED: uncommitted changes detected. Commit first." >&2
    exit 1
  fi
fi

10. UserPromptSubmit 掃 PII 自動 redact

#!/bin/bash
PROMPT=$1
# 掃信箱 / 手機 / 身分證
REDACTED=$(echo "$PROMPT" | sed 's/[a-zA-Z0-9._%+-]*@[a-zA-Z0-9.-]*\.[a-zA-Z]\{2,\}/[REDACTED_EMAIL]/g')
REDACTED=$(echo "$REDACTED" | sed 's/09[0-9]\{8\}/[REDACTED_PHONE]/g')
REDACTED=$(echo "$REDACTED" | sed 's/[A-Z][12][0-9]\{8\}/[REDACTED_ID]/g')
echo "$REDACTED"

這個 hook 讓員工不會無意中把客戶個資丟給 Claude

🔄 類別 C:Git 與 CI/CD 整合(5 個)

11. commit 後自動推給 GitHub Actions

{
  "hooks": {
    "PostToolUse": [{
      "matcher": "Bash",
      "command": "if [[ '${tool.args.command}' == *'git commit'* ]]; then gh workflow run ci.yml; fi"
    }]
  }
}

12. Stop 後寫 daily log

#!/bin/bash
# .claude/hooks/stop-write-daily-log.sh
DATE=$(date +%Y-%m-%d)
SUMMARY=$1
echo "[$DATE $(date +%H:%M)] $SUMMARY" >> ~/.claude/logs/daily-$DATE.log

13. PreToolUse 攔 git push --force 到 main

#!/bin/bash
CMD=$1
if [[ "$CMD" == *"git push --force"* ]] || [[ "$CMD" == *"git push -f"* ]]; then
  BRANCH=$(git branch --show-current)
  if [[ "$BRANCH" == "main" ]] || [[ "$BRANCH" == "master" ]]; then
    echo "BLOCKED: force push to main/master is forbidden" >&2
    exit 1
  fi
fi

14. PostToolUse Edit 後自動產 PR description 草稿

#!/bin/bash
# 每次改檔後追加到 .claude/pr-draft.md
CHANGES=$(git diff --stat)
echo "## 改動摘要 ($(date +%H:%M))" >> .claude/pr-draft.md
echo "$CHANGES" >> .claude/pr-draft.md

15. Edit 後自動 update 測試覆蓋率

{
  "hooks": {
    "PostToolUse": [{
      "matcher": "Edit",
      "command": "if [[ '${tool.args.file_path}' == src/* ]]; then npm run coverage:update; fi"
    }]
  }
}

📢 類別 D:通知與監控(5 個)

16. Stop 後發 Slack

#!/bin/bash
SUMMARY=$1
curl -X POST -H 'Content-type: application/json' \
  --data "{\"text\":\"Claude 完成任務:$SUMMARY\"}" \
  $SLACK_WEBHOOK_URL

17. StopFailure 發 Discord + DataDog

#!/bin/bash
ERROR=$1
# Discord 通知
curl -H "Content-Type: application/json" \
  -d "{\"content\":\"⚠️ Claude 任務失敗:$ERROR\"}" \
  $DISCORD_WEBHOOK
# DataDog 事件
curl -X POST "https://api.datadoghq.com/api/v1/events" \
  -H "DD-API-KEY: $DD_API_KEY" \
  -d "{\"title\":\"Claude failure\",\"text\":\"$ERROR\",\"alert_type\":\"error\"}"

18. SessionStart 寫 audit log

#!/bin/bash
SESSION_ID=$1
echo "[$(date +%Y-%m-%d_%H:%M)] Session $SESSION_ID started by $USER" >> /var/log/claude/audit.log

19. PreToolUse Bash 指令超過 30 秒前發通知

#!/bin/bash
CMD=$1
# 預估超過 30 秒的指令(可自訂規則)
LONG_PATTERNS=("npm run build" "docker build" "pytest" "terraform apply")
for p in "${LONG_PATTERNS[@]}"; do
  if [[ "$CMD" == *"$p"* ]]; then
    curl -X POST -d "{\"text\":\"Claude 開始長任務:$p\"}" $SLACK_WEBHOOK
    break
  fi
done

20. PostToolUse 每次 Edit 寫 file change log

#!/bin/bash
FILE=$1
echo "[$(date)] $USER edited $FILE via Claude" >> ~/.claude/file-changes.log

🤝 類別 E:跨工具 / 跨倉庫一致性(5 個)

21. SessionStart 讀最新 CLAUDE.md

#!/bin/bash
# 從 main 拉最新 CLAUDE.md
git fetch origin main -- CLAUDE.md
git checkout origin/main -- CLAUDE.md
echo "📋 CLAUDE.md 已更新到最新版"

22. PreToolUse Edit 套用團隊 style guide

{
  "hooks": {
    "PreToolUse": [{
      "matcher": "Edit",
      "command": "cat .claude/style-guide.md >&2"
    }]
  }
}

>&2 讓 style guide 直接塞進 Claude 的 context——每次改檔前都會「看到規則**。

23. PostToolUse 寫文件後同步 Notion

#!/bin/bash
FILE=$1
if [[ "$FILE" == docs/*.md ]]; then
  python3 .claude/scripts/sync-to-notion.py "$FILE"
fi

24. SessionEnd 寫摘要到 Linear / Jira

#!/bin/bash
SUMMARY=$1
TICKET=$(git branch --show-current | grep -oE '[A-Z]+-[0-9]+')
if [[ -n "$TICKET" ]]; then
  # 寫到對應 ticket
  curl -X POST "https://api.linear.app/graphql" \
    -H "Authorization: $LINEAR_TOKEN" \
    -d "{\"query\":\"mutation { commentCreate(input: {issueId: \\\"$TICKET\\\", body: \\\"Claude session 摘要:$SUMMARY\\\"}) { success } }\"}"
fi

25. PreCompact 備份原 context

#!/bin/bash
SESSION_ID=$1
mkdir -p ~/.claude/context-backups
cat ~/.claude/sessions/$SESSION_ID.json > ~/.claude/context-backups/$SESSION_ID-pre-compact.json
echo "✅ Context 備份到 ~/.claude/context-backups/"

🧩 5 個 Hook 組合模式

單一 hook 解決單一問題——組合 hook 解決工作流問題

1. 「安全三段式」**:Pre 攔截 + Post 記錄 + StopFailure 警報

{
  "hooks": {
    "PreToolUse": [{
      "matcher": "Bash",
      "command": "./.claude/hooks/pre-block-dangerous.sh '${tool.args.command}'"
    }],
    "PostToolUse": [{
      "matcher": "Bash",
      "command": "./.claude/hooks/post-log-command.sh '${tool.args.command}'"
    }],
    "StopFailure": [{
      "command": "./.claude/hooks/notify-team-failure.sh '${error}'"
    }]
  }
}

用途:production 環境的最低防線——攔截 + 留 audit + 即時警報

2. 「品質閉環」**:Post lint + 失敗自動回饋

{
  "hooks": {
    "PostToolUse": [{
      "matcher": "Edit",
      "command": "npx eslint ${tool.args.file_path} 2>&1 || echo 'Lint failed: please fix' >&2"
    }]
  }
}

用途:Claude 改錯 → 自動看到 lint 報錯 → 自己修——完全 self-healing

3. 「Audit Trail」**:SessionStart 開 log + 每 PostToolUse 寫入 + SessionEnd 上傳

{
  "hooks": {
    "SessionStart": [{
      "command": "echo \"[$(date)] Session start\" > /var/log/claude/$SESSION_ID.log"
    }],
    "PostToolUse": [{
      "command": "echo \"[$(date)] ${tool.name} ${tool.args}\" >> /var/log/claude/$SESSION_ID.log"
    }],
    "SessionEnd": [{
      "command": "aws s3 cp /var/log/claude/$SESSION_ID.log s3://my-bucket/claude-audit/"
    }]
  }
}

用途:金融 / 醫療 / 政府客戶的合規必備——完整 audit trail

4. 「Prod 保護」**:多層 PreToolUse 攔截

#!/bin/bash
# .claude/hooks/multi-layer-prod-guard.sh
CMD=$1

# Layer 1: 分支檢查
BRANCH=$(git branch --show-current)
if [[ "$BRANCH" == "main" ]] && [[ "$CMD" == *"deploy"* ]]; then
  echo "BLOCKED: cannot deploy from main directly" >&2
  exit 1
fi

# Layer 2: 環境檢查
if [[ "$CMD" == *"--env=prod"* ]]; then
  echo "BLOCKED: prod deploy requires manual approval" >&2
  exit 1
fi

# Layer 3: 確認檔
if [[ "$CMD" == *"terraform apply"* ]] && ! [[ -f ".prod-deploy-approved" ]]; then
  echo "BLOCKED: terraform apply requires .prod-deploy-approved file" >&2
  exit 1
fi

5. 「團隊一致性」**:SessionStart 讀規範 + PreToolUse 強制 + StopFailure 回報

{
  "hooks": {
    "SessionStart": [{
      "command": "git pull origin main -- .claude/team-rules.md"
    }],
    "PreToolUse": [{
      "matcher": "Edit",
      "command": "cat .claude/team-rules.md >&2"
    }],
    "StopFailure": [{
      "command": "curl -X POST $SLACK_WEBHOOK -d '{\"text\":\"Claude 違反團隊規範:'${error}'\"}'"
    }]
  }
}

🏢 企業 / 團隊級真實案例(3 個)

案例 1:金融業 — PII redaction + audit log + 跨 region 限制

需求:台灣金融業 + 合規要求:

  • 個資不能丟外部 AI(PII redaction)
  • 完整 audit trail(誰用 Claude 做了什麼)
  • 資料不能跨境(限定 Anthropic 美國 / 歐洲 region)

Hook 組合:

  • UserPromptSubmit 掃 PII(範例 10)
  • Audit Trail 三段式(模式 3)
  • PreToolUse 確認 API endpoint 限定 region(自訂 hook)

案例 2:SaaS 團隊 — 強制 conventional commits + 自動 changelog

需求:敏捷 SaaS 團隊:

  • 強制 Conventional Commits(feat: / fix: / chore:)
  • 每次 commit 自動 update CHANGELOG.md
  • PR 自動產生 description 草稿

Hook 組合:

  • PostToolUse Bash(git commit)驗證 commit 格式 + update CHANGELOG
  • PostToolUse Edit追加到 .claude/pr-draft.md(範例 14)

案例 3:Mason 內容站台 — 中文標點全形 + 不准動 jingyun-spa

需求:Mason 自己用 Claude Code 維護 1,600+ 篇站台:

  • 中文標點必全形(站台 SEO 一致性)
  • migration/old-content/jingyun-spa 專案不准動(私案)
  • 每篇文章 description 必須 < 160 字(schema 規範)

Hook 組合:

{
  "hooks": {
    "PreToolUse": [{
      "matcher": "Edit|Write",
      "command": "if [[ '${tool.args.file_path}' == *migration/old-content/* ]] || [[ '${tool.args.file_path}' == *jingyun-spa* ]]; then echo 'BLOCKED: protected dir' >&2; exit 1; fi"
    }],
    "PostToolUse": [{
      "matcher": "Edit|Write",
      "command": "if [[ '${tool.args.file_path}' == *.md ]]; then node scripts/normalize-cjk-punctuation.mjs '${tool.args.file_path}'; fi"
    }],
    "PostToolUse": [{
      "matcher": "Edit|Write",
      "command": "if [[ '${tool.args.file_path}' == *.md ]]; then node scripts/check-description-length.mjs '${tool.args.file_path}'; fi"
    }]
  }
}

這就是 Mason 真實在用的 hook 配置——對應 Claude Code workflow 完整實戰

⚠️ 5 個反模式(避坑)

反模式 1:Hook 自己又呼叫 Claude

症狀:PostToolUse 裡跑 claude --some-task無限迴圈

為什麼:Claude 改檔 → hook 觸發 → hook 呼叫 Claude → 又改檔 → 又觸發

解法:Hook 內絕對不能呼叫 Claude Code 本身。如果需要 AI 處理,用 API 直接呼叫:

# 錯誤
claude "請審視這個檔案"

# 正確
curl https://api.anthropic.com/v1/messages \
  -H "x-api-key: $ANTHROPIC_API_KEY" \
  -d '{"model":"claude-sonnet-4-6","messages":[...]}'

反模式 2:PreToolUse 太嚴 → Claude 卡住

症狀:Claude 想做事,每個動作都被攔——無法完成任務**

為什麼:Allow list 寫太嚴 / Deny 太多

解法:從寬到嚴疊代——先給 Claude 充分權限,碰到風險點再加 hook 攔不要一開始就鎖死**。

反模式 3:PostToolUse 跑太慢拖死 session

症狀:每次 Edit 後 hook 跑 30 秒——Claude session 變極慢

為什麼:hook 內跑慢任務(全專案 lint、跑整套 test、上傳到外部 API)

解法:Hook 內只跑「快任務——慢任務改成「寫到 queue,背景 process 處理:

# 錯誤:同步跑 5 分鐘 test
npm test

# 正確:背景跑 + 快速回應
nohup npm test > /tmp/test.log 2>&1 &
echo "Test queued, results will be in /tmp/test.log"

反模式 4:Hook script 寫死絕對路徑

症狀:自己電腦能跑,換台機器就壞了**

為什麼:寫了 /Users/mason/.claude/hooks/xxx.sh 這種絕對路徑

解法:全用相對路徑或環境變數:

# 錯誤
/Users/mason/.claude/hooks/check.sh

# 正確
$CLAUDE_PROJECT_DIR/.claude/hooks/check.sh

# 或在 hook script 內
SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)

反模式 5:Hook 出錯但沒 fallback

症狀:Hook 內某個指令失敗,整個 Claude session 直接掛**

為什麼:hook script 沒處理 error,exit 1 直接 propagate 給 Claude**

解法:Hook 內所有可能失敗的指令都加 fallback:

# 錯誤
npx prettier --write file.ts

# 正確
npx prettier --write file.ts 2>/dev/null || echo "Warning: prettier failed, skipping" >&2

Hooks 跟 Skills、MCP 該怎麼搭配?

你想做什麼該用哪個
這類任務都用這個流程SkillClaude Skills 完整指南
需要連外部系統(DB / API)MCPMCP 協議入門
事件發生時自動做某事Hook ← 本文
一鍵啟動的固定流程Slash Command

典型搭配:Skill 提供 SOP + MCP 連外部系統 + Hook 提供護欄 + Slash Command 一鍵啟動——4 個機制各司其職

❓ FAQ

Hooks 寫在哪個檔案?全域跟專案優先誰?

3 個位置:

  1. ~/.claude/settings.json(全域)——所有 session 都生效
  2. <repo>/.claude/settings.json(專案)——只在這個專案生效
  3. <repo>/.claude/settings.local.json(個人專案 override)——個人在此專案的覆寫,不 commit

優先順序:local > 專案 > 全域——local 會 override 專案,專案 override 全域

典型用法:

  • 全域:所有專案的安全規則(rm -rf 攔截、PII 掃描)
  • 專案:團隊共用的規則(lint / format / commit 格式)
  • local:個人偏好(額外的 Slack 通知、log 路徑)
PreToolUse 跟 PostToolUse 該選哪個?

核心差別:Pre 可阻擋,Post 不能阻擋**。

用 PreToolUse:安全攔截——「我要阻止 Claude 做這件事」**

用 PostToolUse:自動化後續——「Claude 做完後我要再做什麼」**

典型搭配:

  • PreToolUse:攔截 rm / push —force / 接觸 .env
  • PostToolUse:lint / format / 寫 log / 發通知

注意:Post 不能阻擋 = 即使 hook 出錯也擋不住 Claude 的動作——所以重要的安全規則用 Pre

Hook 出錯會不會把整個 Claude Code 弄壞?

Pre 會 / Post 不會:

PreToolUse:hook 失敗(exit 1) → Claude 整個 tool call 取消——這是它的功能

PostToolUse:hook 失敗記錄錯誤但 Claude session 繼續——不會弄壞

避免「hook 把 session 弄壞3 個原則**:

  1. 所有可能失敗的指令加 fallbackcommand || true2>/dev/null
  2. 快任務 Pre / 慢任務 PostPre 必須在 < 2 秒回應
  3. 完整測試——新 hook 加上去後先在獨立專案測試 1-2 天
25 個範例都要裝嗎?從哪 5 個開始?

第一次安裝建議 5 個(對應 pocketos 9 秒刪庫事件):

  1. 範例 6:攔 rm -rf / sudo / pkill
  2. 範例 13:攔 git push —force 到 main
  3. 範例 8:攔接觸 .env / credentials
  4. 範例 18:SessionStart 寫 audit log
  5. 範例 1 或 2:PostToolUse lint / prettier

這 5 個 = 80% 的「保命設定——裝完後再依需求加其他

進階階段(用 1-2 個月後):

  • 範例 10:PII redaction(若處理客戶資料)
  • 範例 16:Stop Slack 通知(團隊協作)
  • 範例 22:PreToolUse 套用 style guide
Hooks 跟 Skills 該怎麼分工?

核心區別:

Skill 是「怎麼做的 SOP**:Claude 看到某個任務,用這套 SOP 處理**

Hook 是「事件發生時的自動腳本:Claude 做某個動作前 / 後,強制執行**

典型分工:

  • Skill:「幫使用者寫健康新聞 → 套用編譯方法論」**
  • Hook:「改完 .md 檔 → 自動跑全形標點 normalize」**

搭配:Skill 在「對話層指導 Claude,Hook 在「工具層強制執行**。

Mason 站台:Skills 處理寫作 SOP,Hooks 處理「改完後一定要做的事——兩者互補**。

⚠️ 警語

  • 本文 25 個範例是 ready-to-copy 但非 production-ready——請依你的環境調整
  • Hooks 內呼叫外部 API(Slack / Datadog / Linear)會增加 latency——請評估接受度
  • 企業環境設 hooks必須跟 IT / 法務確認合規——audit log、PII redaction 都涉及法規

權威來源:


深入閱讀:➜ Claude Code 完全 Pillar | Claude Code 工作流 | Claude Skills 完整指南 | MCP 協議入門

№ · further reading

延伸閱讀