Claude Code Hooks 完整指南 — 讓 AI 自動化不再靠運氣
你有沒有遇過這種狀況:叫 Claude Code 改完檔案,結果忘了跑 formatter,code review 被打回來的全是 style issue?
或者更痛的——Claude 很盡責地幫你改了五個檔案,你說「好了可以了」,它就真的停了。然後你才發現 test 沒跑、lint 沒過、有一個 .env 被改到。
Hooks 就是拿來解決這類問題的。它不是什麼 AI 魔法,反而是整套 Claude Code 裡面最不 AI 的部分——純粹的 shell 腳本,在特定時間點被觸發,做你設定好的事情。確定性的行為,不靠 LLM 判斷。
概念:Hook 是什麼?
一句話講完:在 Claude Code 生命週期的特定節點,自動執行你寫的腳本。
跟 Git hooks 很像。pre-commit hook 在 commit 前跑 lint,Claude Code 的 PreToolUse hook 在工具執行前跑你的檢查。概念相通,只是觸發的時機不一樣。
目前支援的 hook 事件超過 20 個,常用的幾個:
| 事件 | 觸發時機 |
|---|---|
PreToolUse |
工具執行前,可以攔截 |
PostToolUse |
工具執行後,適合做後處理 |
Notification |
Claude 等待你輸入時 |
Stop |
Claude 回應完畢時 |
SessionStart |
Session 開始或恢復時 |
ConfigChange |
設定檔被修改時 |
PermissionRequest |
權限對話框彈出時 |
每個 hook 都有一個 matcher 可以過濾條件。比方 PostToolUse 配上 matcher: "Edit|Write",就只在檔案被編輯時觸發,Bash 指令不會被影響。
實戰一:檔案一改完就自動 format
這大概是最多人需要的場景。Claude 改完 code,Prettier 立刻跑過去。不用每次提醒它「記得 format」。
在專案根目錄的 .claude/settings.json 加入:
1 | { |
PostToolUse 代表工具執行成功後觸發。matcher: "Edit|Write" 限制只在檔案編輯工具上生效。腳本從 stdin 拿到 JSON,用 jq 抽出檔案路徑,丟給 Prettier。
一氣呵成,Claude 完全不需要知道 Prettier 的存在。
實戰二:桌面通知 — 不用盯著 terminal
Claude 在跑長任務的時候,你切去看 Slack、看文件,回來才發現它早就問你問題了,空等了十分鐘。
Notification hook 解決這個痛點:
1 | { |
macOS 用 osascript,Linux 用 notify-send。matcher 留空表示所有通知類型都觸發。裝好之後就不用一直盯著 terminal 了。
實戰三:保護敏感檔案不被修改
.env 被 Claude 改到是真的會出事的那種。package-lock.json 被動到也很頭痛。
用 PreToolUse hook 加一層保護:
1 |
|
註冊方式:
1 | { |
重點是 exit code。exit 2 代表攔截,Claude 會收到 stderr 的訊息然後自動調整策略,不會硬幹。exit 0 代表放行。
實戰四:Compaction 後重新注入上下文
Claude Code 的 context window 滿了會觸發 compaction(壓縮),把對話摘要化。問題是壓縮之後某些重要指令可能被吃掉——比方說「這個專案用 Bun 不用 npm」。
SessionStart hook 配合 compact matcher 可以在壓縮後重新注入記憶:
1 | { |
stdout 的內容會直接注入 Claude 的 context。你也可以把 echo 換成 git log --oneline -5,讓 Claude 壓縮後自動知道最近改了什麼。
進階:三種 Hook 類型
除了最基本的 command 類型,Hooks 還有三種進階玩法:
Prompt-based Hook:叫一個輕量模型(預設 Haiku)做判斷。不跑腳本,直接問 LLM「這個動作 OK 嗎?」適合需要語義理解的場景。
1 | { |
Agent-based Hook:比 prompt hook 更強,會起一個 subagent 去實際跑測試、讀檔案。適合「先跑 test 確認全過才能停」的場景。
1 | { |
HTTP Hook:把事件資料 POST 到一個 endpoint。適合團隊級的 audit logging 或串接外部服務。
三種類型的共通點:都用同一套 JSON 格式溝通,只是執行邏輯不同。
設定檔放哪裡?
| 位置 | 作用範圍 | 可以 commit 嗎 |
|---|---|---|
~/.claude/settings.json |
全域,所有專案 | 不行 |
.claude/settings.json |
單一專案 | 可以 |
.claude/settings.local.json |
單一專案(gitignore) | 不行 |
Plugin hooks/hooks.json |
Plugin 啟用時生效 | 跟著 Plugin 走 |
想看目前所有 hook 的狀態,在 Claude Code 裡打 /hooks 就會列出來。
除錯技巧
Hook 沒觸發?先檢查這幾件事:
/hooks選單裡有沒有看到你的 hook- matcher 是不是 case-sensitive 的問題(
bash≠Bash) - 腳本有沒有執行權限(
chmod +x) jq有沒有裝
想看更多執行細節,按 Ctrl+O 開 verbose mode,或用 claude --debug 啟動。所有 hook 的 stdout/stderr 都會印出來。
有個常見的坑:如果你的 .zshrc 裡有不帶條件的 echo,hook 跑的時候那個 echo 會混進 JSON 輸出,導致 parse 失敗。解法是把 echo 包在 interactive shell 判斷裡:
1 | if [[ $- == *i* ]]; then |
小結
Hooks 讓 Claude Code 從「有時候記得做」變成「每次一定做」。format、lint、protect、notify——這些不需要 AI 判斷的事情,就不應該交給 AI 判斷。
腳本寫一次,之後每個 session 自動生效。這種確定性,在跟 AI 協作的時候格外珍貴。
原文來源:Automate workflows with hooks - Claude Code Docs
參考來源:Claude Code in Action - Anthropic Academy






