本文根據 Claude Code 官方文檔《Automate actions with hooks》和 Hooks 參考整理,核對日期 2026-10-07。示例配置改寫自官方示例;事件名和字段以官方 Hooks reference 為準。
適用於誰
- 想讓 Claude Code 每次改完文件自動格式化、等我確認時彈通知的人;
- 想在團隊項目裏強制禁止改
.env、禁止跑drop table之類命令的人——寫在 CLAUDE.md 裏只是「建議」,Hook 是「必須」; - 搜「claude code hooks 怎麼用」「hooks 通知 windows」的人。
結論先說
- Hook = 用戶自己定義的命令,在 Claude Code 生命週期的固定時機自動運行(改文件前後、需要你輸入時、會話開始時……),結果是確定的,不依賴模型「記得去做」。
- 配置寫在
settings.json的hooks字段裏:~/.claude/settings.json對你所有項目生效,項目裏的.claude/settings.json可以提交給團隊共用。寫完在會話裏輸入/hooks確認已加載。 - 最常用的 4 個事件:
PreToolUse(工具執行前,可以攔截)、PostToolUse(執行成功後)、Notification(需要你輸入或確認時)、Stop(Claude 回覆完畢時)。 - 腳本的退出碼決定結果:
0表示不反對(照常走權限流程),2表示攔截,並把 stderr 裏的原因反饋給 Claude。 - Hook 以你的帳戶權限執行任意命令,來自別人的 Hook 配置要先讀懂再用。
第一個 Hook:Claude 等你時彈桌面通知
打開(沒有就新建)~/.claude/settings.json,按你的系統選一段加進去。
macOS:
json
{
"hooks": {
"Notification": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "osascript -e 'display notification \"Claude Code 需要你處理\" with title \"Claude Code\"'"
}
]
}
]
}
}
如果沒有彈窗:官方說明 osascript 借用的是系統自帶的「腳本編輯器」發通知,先在終端執行一次 osascript -e 'display notification "test"',再到「系統設定 → 通知」裏給「腳本編輯器」打開允許通知。
Linux:把 command 換成:
text
notify-send 'Claude Code' 'Claude Code 需要你處理'
沒有這個命令就裝 libnotify-bin(Debian / Ubuntu)。注意伺服器、SSH、容器裏通常沒有桌面通知服務。
Windows(PowerShell):官方給的是彈一個對話框的寫法:
json
{
"hooks": {
"Notification": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "powershell.exe -Command \"[System.Reflection.Assembly]::LoadWithPartialName('System.Windows.Forms'); [System.Windows.Forms.MessageBox]::Show('Claude Code needs your attention', 'Claude Code')\""
}
]
}
]
}
}
它彈的是對話框而不是右下角通知,可能被終端窗口擋住;在 WSL 裏使用需要 powershell.exe 在 PATH 裏。
驗證:會話裏輸入 /hooks,能在 Notification 下看到它。然後按 Shift+Tab 切到 manual mode on,讓 Claude 做一件需要確認的事,切到別的窗口等通知。
只在某些情況通知:matcher 留空表示所有通知類型都觸發;也可以填:
| matcher | 觸發時機 |
|---|---|
permission_prompt | 需要你批准某個操作,且已經等了約 6 秒 |
idle_prompt | Claude 回覆完約 60 秒你還沒輸入 |
auth_success | 登入認證完成 |
agent_completed | 後台會話完成或失敗(agent view 打開時) |
想在「Claude 每次回覆完」都提醒,可以把同樣的命令掛在 Stop 事件上。
常用示例
1. 改完文件自動格式化(PostToolUse)
放在項目的 .claude/settings.json:
json
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "jq -r '.tool_input.file_path' | xargs npx prettier --write"
}
]
}
]
}
}
matcher: "Edit|Write" 表示只在 Claude 用改文件工具之後運行。命令從 stdin 收到的 JSON 裏取出文件路徑交給 Prettier。需要先裝好 jq(macOS brew install jq,Ubuntu apt-get install jq)。成功時對話裏不會有任何提示,打開文件看格式有沒有變即可。
2. 禁止修改敏感文件(PreToolUse + 退出碼 2)
新建 .claude/hooks/protect-files.sh:
bash
#!/bin/bash
INPUT=$(cat)
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty')
# 把 Windows 的反斜槓統一成 /,下面的匹配才可靠
FILE_PATH="${FILE_PATH//\\//}"
PROTECTED_PATTERNS=(".env" "package-lock.json" ".git/")
for pattern in "${PROTECTED_PATTERNS[@]}"; do
if [[ "$FILE_PATH" == *"$pattern"* ]]; then
echo "已攔截:$FILE_PATH 屬於受保護文件($pattern)" >&2
exit 2
fi
done
exit 0
macOS / Linux 上要先 chmod +x .claude/hooks/protect-files.sh,然後註冊:
json
{
"hooks": {
"PreToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/protect-files.sh"
}
]
}
]
}
}
讓 Claude 去改 .env 試試:操作會在執行前被攔下,攔截原因會作為反饋發給 Claude,它會換別的辦法。
3. 攔截危險命令
同樣的思路掛在 Bash 上,檢查 tool_input.command:
bash
#!/bin/bash
INPUT=$(cat)
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command')
if echo "$COMMAND" | grep -q "drop table"; then
echo "已攔截:不允許刪除數據表" >&2
exit 2
fi
exit 0
官方特別說明:PreToolUse Hook 在任何權限模式之前執行,返回拒絕時連 bypass 模式也攔得住,所以適合做團隊強制規範。反過來,Hook 返回「允許」並不能繞過設定裏的 deny 規則。
4. 上下文壓縮後重新提醒(SessionStart + compact)
對話太長被壓縮後,可能丟掉一些細節。用 SessionStart 加 compact matcher,在每次壓縮後把關鍵資訊再塞回去:
json
{
"hooks": {
"SessionStart": [
{
"matcher": "compact",
"hooks": [
{
"type": "command",
"command": "echo '提醒:本項目用 pnpm,不用 npm;提交前先跑 pnpm test。'"
}
]
}
]
}
}
echo 可以換成任何有輸出的命令,比如 git log --oneline -5。每次會話都要加載的規矩,寫進 CLAUDE.md 更合適。
Hook 是怎麼工作的
輸入:事件觸發時,Claude Code 把一段 JSON 通過 stdin 交給你的命令,裏面有 session_id、cwd、hook_event_name,工具類事件還有 tool_name 和 tool_input(Bash 的命令在 tool_input.command,改文件的路徑在 tool_input.file_path)。
輸出:
- 退出碼
0:不反對。對PreToolUse來說這不等於批准,正常的權限確認照樣會出現;UserPromptSubmit、SessionStart這類事件的 stdout 文字會加進 Claude 的上下文。 - 退出碼
2:攔截,把 stderr 的內容作為原因。少數事件(如SessionStart)不能被攔截,只會把資訊顯示給你。 - 其他退出碼:通常算「非阻塞錯誤」,操作繼續,對話裏顯示
hook error。 - 想要更細的控制,可以退出碼 0 並打印 JSON,例如
PreToolUse返回permissionDecision: "deny"和原因。注意這些字段要放在hookSpecificOutput裏面,放錯層級會被靜默忽略。
常用事件:
| 事件 | 時機 |
|---|---|
SessionStart / SessionEnd | 會話開始(含恢復、壓縮後)/ 結束 |
UserPromptSubmit | 你提交消息後、Claude 處理前 |
PreToolUse | 工具執行前,可攔截 |
PermissionRequest | 需要權限決定時,可代你批准(要把 matcher 寫窄) |
PostToolUse / PostToolUseFailure | 工具執行成功 / 失敗後 |
Notification | Claude Code 發通知時 |
Stop | Claude 回覆完畢 |
SubagentStart / SubagentStop | 子代理啟動 / 結束 |
PreCompact / PostCompact | 上下文壓縮前 / 後 |
FileChanged / CwdChanged | 被監視的文件變化 / 工作目錄變化 |
完整事件列表有三十多個,見官方 Hooks reference。除了執行命令(type: "command"),還可以把事件 POST 到一個網址(http)、調用 MCP 工具(mcp_tool),或者交給模型判斷(prompt / agent)。
配置位置與作用範圍:
| 位置 | 範圍 |
|---|---|
~/.claude/settings.json | 你所有的項目,僅本機 |
.claude/settings.json | 當前項目,可提交到倉庫 |
.claude/settings.local.json | 當前項目,僅自己 |
插件的 hooks/hooks.json | 啟用該插件時 |
| 技能 / 子代理的 frontmatter | 技能被調用後 / 子代理運行期間 |
想臨時全部關掉,在設定裏寫 "disableAllHooks": true。
常見問題
Q:配置了卻不觸發?
先 /hooks 看有沒有出現在正確的事件下;matcher 區分大小寫,要和工具名完全一致(Edit 不是 edit);再確認事件選對了,PreToolUse 在執行前、PostToolUse 在執行後。
Q:對話裏出現「PreToolUse hook error」?
腳本意外以非 0 退出。手動喂一段樣例 JSON 測試:echo '{"tool_name":"Bash","tool_input":{"command":"ls"}}' | ./my-hook.sh; echo $?。提示 command not found 就用絕對路徑或 $CLAUDE_PROJECT_DIR;提示 jq: command not found 就裝 jq 或改用 Python / Node 解析。
Q:Hook 打印了 JSON 但沒生效?
常見原因是你的 shell 配置文件(~/.bashrc、~/.zshrc)裏有無條件的 echo,輸出跑到了 JSON 前面。把這些 echo 包在 if [[ $- == i ]]; then ... fi 裏,只在交互式終端執行。
Q:Claude 用 shell 命令改文件,Edit|Write 的 Hook 能捕獲嗎?
不能。官方建議:必須覆蓋所有改動時,加一個 Stop Hook 每輪掃描一次工作區,或者用 FileChanged 監視具體文件。
Q:怎麼看 Hook 的詳細執行記錄?
按 Ctrl+O 打開記錄視圖看結果;更詳細的用 claude --debug-file /tmp/claude.log 啟動,或會話中輸入 /debug 開啟調試日誌。
參考資料
- Automate actions with hooks(官方):https://code.claude.com/docs/en/hooks-guide
- Hooks reference(官方):https://code.claude.com/docs/en/hooks
- Settings files and precedence(官方):https://code.claude.com/docs/en/settings
- Configure permissions(官方):https://code.claude.com/docs/en/permissions
0 條評論
還沒有評論,來搶沙發~