Hook 看起來簡單,但它的威力來自於「在正確的時刻介入」。本篇深入 Hook 的生命週期,展示 6 個不同的 Hook 觸發點(lifecycle points),提供 12+ 個實戰場景範例,以及具體的配置和部署步驟。
🔄 Hook 的完整生命週期
Claude Code 在執行工作時,會經過多個檢查點。Hook 就是在這些檢查點上「攔截」執行流程,進行驗證、轉換或防禦。
用戶輸入
↓
[PreRequest Hook] ← Hook 1:攔截請求前
↓
驗證認證和權限
↓
[PreToolUse Hook] ← Hook 2:在工具執行前
↓
執行工具(bash、read、edit 等)
↓
獲取工具結果
↓
[PostToolUse Hook] ← Hook 3:在工具執行後
↓
結果驗證和轉換
↓
[Stop Hook] ← Hook 4:決定是否需要暫停和修正
↓
返回結果給用戶
↓
[PostResponse Hook] ← Hook 5:響應後的清理
↓
異常處理
↓
[OnError Hook] ← Hook 6:異常發生時的恢復
↓
完成
📍 6 個 Hook 觸發點詳解
1️⃣ PreRequest Hook(最上游的防禦)
觸發時機:用戶提交請求時,在任何工具執行前
使用場景:
- 🔴 防禦場景 1:檢查用戶是否試圖讀取敏感檔案(.env, .ssh, .config)
- 🟠 檢查場景 2:驗證請求是否包含危險關鍵字(git reset –hard, rm -rf)
- 🟡 轉向場景 3:根據時間或上下文自動拒絕某些類型的請求
# 配置位置:~/.claude/settings.json 或 settings.local.json
{
"hooks": {
"pre_request": {
"enabled": true,
"rules": [
{
"name": "block_sensitive_files",
"pattern": "(read|cat).*(\\.env|\\.key|\\.ssh|credentials)",
"action": "block",
"message": "⚠️ Cannot access sensitive files"
},
{
"name": "warn_destructive",
"pattern": "git (reset --hard|push --force)|rm -rf",
"action": "confirm",
"message": "⚠️ This command is destructive. Continue?"
}
]
}
}
}
2️⃣ PreToolUse Hook(工具執行前的最後檢查)
觸發時機:具體工具(bash、read、edit 等)即將執行時
使用場景:
- 🔴 防禦場景 1:攔截特定工具(禁止 rm、禁止 git push 到 main)
- 🟠 檢查場景 2:驗證檔案路徑存在性(避免編輯不存在的檔案)
- 🟡 轉換場景 3:修改命令參數(將 rm 改為 mv to trash)
- 🟢 記錄場景 4:記錄所有敏感操作的日誌
# 例子:PreToolUse Hook - 禁止直接刪除
{
"hooks": {
"pre_tool_use": {
"enabled": true,
"rules": [
{
"name": "prevent_direct_deletion",
"tool": "bash",
"pattern": "^rm ",
"action": "transform",
"transform": "echo 'Using rm is disabled. Use: mv $file ~/.trash' && false"
},
{
"name": "verify_branch_safety",
"tool": "bash",
"pattern": "git push.*main",
"action": "confirm",
"message": "Push to main? This is permanent."
},
{
"name": "auto_backup_on_edit",
"tool": "edit",
"action": "pre_action",
"command": "cp {file} {file}.backup"
}
]
}
}
}
3️⃣ PostToolUse Hook(工具執行後的驗證和轉換)
觸發時機:工具執行完畢,獲得結果後
使用場景:
- 🟡 驗證場景 1:檢查 bash 命令是否成功(exit code = 0)
- 🟠 轉換場景 2:格式化輸出(JSON 格式化、表格美化)
- 🟢 記錄場景 3:自動保存重要操作結果
- 🔵 優化場景 4:清理大型輸出(截斷日誌)
# 例子:PostToolUse Hook - 自動格式化和驗證
{
"hooks": {
"post_tool_use": {
"enabled": true,
"rules": [
{
"name": "validate_bash_success",
"tool": "bash",
"action": "validate",
"check": "exit_code == 0",
"on_fail": "log_error"
},
{
"name": "auto_format_json",
"tool": "bash",
"pattern": "jq|json",
"action": "transform",
"transform": "jq '.' (automatically format JSON output)"
},
{
"name": "save_large_results",
"tool": "bash",
"pattern": "curl|wget",
"action": "post_action",
"command": "save_to_file ~/.cache/last_result.json"
},
{
"name": "truncate_verbose_output",
"tool": "bash",
"action": "transform",
"condition": "output_size > 10000",
"transform": "head -100 + '... (truncated {remaining} lines)'"
}
]
}
}
}
4️⃣ Stop Hook(驗證器決策點)
觸發時機:結果返回給用戶前,決定是否需要暫停和修正
使用場景:
- 🔴 驗證場景 1:JSON 格式驗證(無效 JSON 需要修正)
- 🟠 邏輯場景 2:檢查結果合理性(SQL 查詢應該有行,否則可能是錯誤)
- 🟡 決策場景 3:判斷結果是否完整(檔案大小是否符合預期)
# 例子:Stop Hook with Validator - JSON 驗證和自動修復
{
"hooks": {
"stop_hook": {
"enabled": true,
"validator": {
"name": "json_validator",
"rules": [
{
"id": "valid_json",
"check": "is_valid_json(result)",
"on_fail": "stop_and_request_fix",
"message": "JSON is malformed. Please fix and retry.",
"auto_attempt": 3
},
{
"id": "non_empty_result",
"check": "len(result) > 10",
"on_fail": "warn",
"message": "Result might be incomplete (too short)"
},
{
"id": "api_error_check",
"check": "'error' not in result.lower()",
"on_fail": "stop_and_request_fix",
"message": "API returned an error. Review and retry."
}
]
}
}
}
}
5️⃣ PostResponse Hook(執行後的清理和通知)
觸發時機:結果已返回給用戶,工作完成後
使用場景:
- 🟢 清理場景 1:刪除臨時檔案(/tmp 下的中間結果)
- 🔵 通知場景 2:記錄到監控系統(重要操作記錄)
- 🟣 統計場景 3:更新執行統計(執行次數、成功率)
# 例子:PostResponse Hook - 清理和通知
{
"hooks": {
"post_response": {
"enabled": true,
"rules": [
{
"name": "cleanup_temp_files",
"action": "cleanup",
"targets": ["/tmp/*.temp", "/tmp/claude-*"],
"condition": "age > 1h"
},
{
"name": "log_sensitive_operations",
"action": "log",
"condition": "tool in ['bash', 'edit'] AND (git|deploy|delete) in command",
"log_file": "~/.claude/audit.log"
},
{
"name": "notify_on_error",
"action": "notify",
"condition": "exit_code != 0",
"channels": ["stderr", "log_file"]
}
]
}
}
}
6️⃣ OnError Hook(異常情況處理)
觸發時機:工具執行失敗或發生異常時
使用場景:
- 🔴 恢復場景 1:自動回滾(某個命令失敗,執行恢復操作)
- 🟠 重試場景 2:自動重試(網絡超時自動重試)
- 🟡 降級場景 3:使用備選方案(API 1 失敗,嘗試 API 2)
# 例子:OnError Hook - 自動恢復和重試
{
"hooks": {
"on_error": {
"enabled": true,
"rules": [
{
"name": "auto_retry_network_errors",
"error_pattern": "(timeout|connection refused|ECONNREFUSED)",
"action": "retry",
"max_attempts": 3,
"backoff": "exponential"
},
{
"name": "rollback_on_git_error",
"error_pattern": "git (push|merge|rebase)",
"action": "execute",
"command": "git reset --hard HEAD"
},
{
"name": "fallback_api_endpoint",
"error_pattern": "api1\\.example\\.com",
"action": "retry_with",
"new_command": "replace(api1, api2)"
}
]
}
}
}
🛠️ 如何正確配置和部署 Hook
步驟 1:選擇配置位置
- 全局配置:
~/.claude/settings.json(所有項目適用) - 項目級配置:
{project}/.claude/settings.local.json(單個項目) - 團隊配置:
{team}/.claude/team-settings.json(團隊共享)
🔵 最佳實踐
敏感規則(.env 保護、刪除防禦)→ 全局 settings.json
項目特定規則(特定分支政策、特定工具限制)→ settings.local.json
步驟 2:編寫 Hook 規則
Hook 規則的通用結構:
{
"hook_type": "pre_tool_use", // 觸發點
"name": "rule_name", // 規則名稱
"tool": "bash", // 適用工具(可選)
"pattern": "regex_pattern", // 匹配模式(可選)
"action": "block|confirm|transform|validate", // 動作類型
"condition": "expression", // 執行條件(可選)
"message": "User-facing message", // 給用戶的提示
"auto_attempt": 3, // 自動重試次數(可選)
"transform": "transformation", // 轉換規則(如果 action=transform)
"on_fail": "action_on_failure" // 失敗時的行動
}
步驟 3:驗證 Hook 配置
# 1. 檢查 JSON 語法
jq '.' ~/.claude/settings.json
# 2. 列出所有啟用的 Hook
claude config list-hooks --enabled
# 3. 測試特定 Hook(乾跑)
claude hook test --name rule_name --dry-run
# 4. 查看 Hook 日誌
tail -f ~/.claude/hooks.log
步驟 4:分層部署(由簡到複雜)
- 第 1 周:安全防禦
- PreRequest Hook:阻止敏感檔案讀取
- PostToolUse Hook:驗證 bash 執行成功
- 第 2 周:工作流驗證
- Stop Hook:JSON 驗證
- PostToolUse Hook:自動格式化
- 第 3 周:錯誤恢復
- OnError Hook:自動重試
- PostResponse Hook:清理臨時檔案
📋 12+ 個實戰範例速查表
| 範例 | Hook 類型 | 動作 | 效果 |
|---|---|---|---|
| 保護 .env 檔案 | PreRequest | Block | 永不讀取敏感檔案 |
| 防止 git reset –hard | PreToolUse | Confirm | 需要確認才能執行 |
| 禁止直接 rm | PreToolUse | Transform | 改為移到回收站 |
| 自動格式化 JSON | PostToolUse | Transform | 自動美化輸出 |
| 驗證 JSON 有效性 | Stop | Validate | 無效 JSON 拒絕返回 |
| 自動備份編輯檔案 | PreToolUse | Pre-action | 編輯前自動備份 |
| 日誌敏感操作 | PostResponse | Log | 所有敏感操作記錄 |
| 網絡超時自動重試 | OnError | Retry | 最多重試 3 次 |
| 清理臨時檔案 | PostResponse | Cleanup | 自動刪除 /tmp |
| 驗證 bash 成功 | PostToolUse | Validate | exit code ≠ 0 時警告 |
| 截斷大型輸出 | PostToolUse | Transform | > 10KB 自動截斷 |
| API 故障轉移 | OnError | Fallback | 用備選 API 重試 |
⚠️ Hook 配置的常見陷阱
陷阱 1:規則太寬鬆,誤傷正常操作
❌ 錯誤:
"pattern": "read" // 任何包含 "read" 的命令都會觸發
✅ 正確:
"pattern": "read (.*\\.env|\\.key|\\.credentials)" // 只針對特定檔案
陷阱 2:Hook 順序錯誤導致邏輯失效
❌ 錯誤順序:
1. PostToolUse(驗證)
2. PreToolUse(保護) ← 太晚了,工具已經執行了
✅ 正確順序:
1. PreToolUse(攔截和保護)
2. PostToolUse(驗證結果)
3. Stop(決定是否修正)
陷阱 3:Transform 規則語法錯誤
❌ 錯誤:
"transform": "cmd.replace('old', 'new')" // Python 語法,但 Hook 是 shell
✅ 正確:
"transform": "sed 's/old/new/g'" // Shell 語法
或
"transform": "replace(cmd, old, new)" // Hook 提供的函數
✅ Hook 部署檢查清單
- ☐ 配置檔案 JSON 語法正確(jq 驗證通過)
- ☐ Hook 規則的 pattern 足夠明確(不會誤傷)
- ☐ PreToolUse 規則在最關鍵的地方(防禦第一)
- ☐ Stop Hook 驗證邏輯清晰(什麼時候拒絕)
- ☐ OnError Hook 有適當的重試邏輯
- ☐ 測試了至少一個完整工作流
- ☐ 查看日誌確認 Hook 被正確觸發
- ☐ 團隊成員知道有這些 Hook(溝通重要)
🔗 與其他文章的連結
📚 延伸閱讀
- ← 文章 2:Hook 基礎指南(從這裡開始)
- 文章 3:Skill 自動化 →(5+ 步工作流)
- 系列總覽(完整導航)
總結:Hook 的 6 個層次
- 🎯 L1:PreRequest(最上游,全局防禦)
- 🎯 L2:PreToolUse(工具前,細粒度保護)
- 🎯 L3:PostToolUse(結果驗證和轉換)
- 🎯 L4:Stop(決策點,是否修正)
- 🎯 L5:PostResponse(清理和通知)
- 🎯 L6:OnError(異常恢復)
掌握這 6 個層次,你就能在任何地方「攔截」執行流程,實現你想要的保護和自動化。
發佈留言