Anthropic
寫第一個 hook
settings.json 三層放 hook 的差別,從零寫一個 formatter hook。
TL;DR
- Hook 配置寫在
settings.json的hooks區塊——三層 settings 都可以放,依誰要用選層級 - 推薦用
/hooksinteractive 命令新增,比手寫 JSON 不容易出格式錯誤 - Hook command 是任何能執行的 binary / script,從 stdin 拿 tool call payload,用 exit code 回應
一個情境:改完 .ts 自動跑 prettier
你不想再手動 format。你希望——Claude 每次 Edit 或 Write 動到 .ts 檔,自動幫你跑一次 prettier。
不用記得提醒它、不用 review 時抓格式 issue、不用為了這件事寫一條 CLAUDE.md rule(rule 不一定每次都被遵守)。
這就是 PostToolUse hook 的場景:tool 執行之後觸發一個你定義的 command。
hook 長什麼樣
最小可動的配置就三件事——何時觸發、配對哪個 tool、跑什麼 command:
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{
"type": "command",
"command": "prettier --write \"$CLAUDE_FILE_PATHS\""
}
]
}
]
}
}
PostToolUse:tool 跑完才觸發(PreToolUse 是執行前,可以擋下來)matcher:regex 比對 tool name,這裡同時抓Write跟Editcommand:什麼都行——shell one-liner、CLI、Node script 都可以
stdin 拿到什麼
Hook command 啟動時,Claude Code 會把這次 tool call 的資料用 JSON 從 stdin 餵進來:
{
"session_id": "2d6a1e4d-6...",
"hook_event_name": "PostToolUse",
"tool_name": "Edit",
"tool_input": { "file_path": "/code/app.ts" }
}
你的 script 讀進來、parse、決定要做什麼。tool_input 的 shape 每個 tool 不一樣(Read / Edit 有 file_path、Bash 有 command、Grep 有 pattern)。
exit code 在講什麼
Hook 用 exit code 跟 Claude 對話:
| exit code | 意思 |
|---|---|
0 | OK,繼續 |
2 | Block 這次 tool call(只在 PreToolUse 有效),stderr 內容會丟給 Claude 看 |
| 其他 non-zero | 視為 error,記 log 但不擋 |
對 formatter 來說 exit 0 就好——你只是順手 format,沒打算擋什麼。
三層 settings 怎麼選
跟 Lesson 03 那三層一樣,hook 也是放在這三個地方:
| 層級 | 路徑 | 適合放 |
|---|---|---|
| User | ~/.claude/settings.json | 個人習慣(自動 format、log) |
| Project shared | <repo>/.claude/settings.json | 團隊規範(commit 前跑 lint),會 commit |
| Project local | <repo>/.claude/settings.local.json | 個人偏好 / 機密路徑,不 commit |
判斷很簡單——這個 hook 誰會想用? 只有你 → user;整個團隊 → project shared;只有你 + 不想推上 git → project local。
接下來
下一篇 → 實用 hook 範例集:format、log、擋讀 .env、commit message 檢查——挑一個直接抄來改。

