Claude Code Hooks:打造自動化開發工作流程
Claude Code Hooks 新手入門教學。從零開始學習 Hooks,附 10 個以上實用範例、常見錯誤排除與最佳實踐指南。
想讓 Claude Code 自動執行 lint、測試和安全檢查嗎?Hooks 就是你需要的功能。本教學帶你從零開始,掌握 Hooks 的概念與實際應用。
什麼是 Hooks?
簡單來說,Hooks 是攔截 Claude 行動的機制:
你下指令 → [Hook 攔截] → Claude 執行 → [Hook 檢查] → 完成
你可以在以下幾個時間點注入自訂邏輯:
| 時機 | Hook 名稱 | 用途 |
|---|---|---|
| 工具執行前 | PreToolUse | 阻擋危險操作、加入提醒 |
| 工具執行後 | PostToolUse | 自動 lint、執行測試 |
| 任務完成時 | Stop | 確保測試通過後才結束 |
| Session 啟動時 | SessionStart | 載入環境、顯示資訊 |
5 分鐘快速入門
步驟 1:建立設定檔
在你的專案目錄中建立 .claude/settings.json:
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write",
"hooks": [
{
"type": "command",
"command": "echo 'File written!'",
"onFailure": "ignore"
}
]
}
]
}
}
步驟 2:測試 Hook
啟動 Claude Code:
claude
請 Claude 建立任意檔案:
你:建立一個 hello.txt 檔案,內容是 "Hello World"
你會看到 Claude 建立檔案後輸出 File written!。
恭喜!你的第一個 Hook 已經在運作了。
核心概念
Hook 結構
每個 Hook 設定由三個部分組成:
{
"hooks": {
"EventName": [
{
"matcher": "要攔截的工具",
"hooks": [
{
"type": "command 或 prompt",
"command": "要執行的指令",
"onFailure": "失敗處理方式"
}
]
}
]
}
}
Matchers
| Matcher | 說明 |
|---|---|
"Write" | 只攔截 Write 工具 |
"Edit" | 只攔截 Edit 工具 |
"Bash" | 只攔截 Bash 工具 |
"Read" | 只攔截 Read 工具 |
"*" | 攔截所有工具 |
"Write|Edit" | 攔截 Write 或 Edit |
Hook 類型
1. Command Hook(執行指令)
{
"type": "command",
"command": "npm run lint",
"onFailure": "warn"
}
2. Prompt Hook(使用 AI 判斷)
{
"type": "prompt",
"prompt": "檢查這個指令是否安全。如果包含 rm -rf,回傳 'block'。否則回傳 'approve'。"
}
onFailure 選項
| 選項 | 行為 |
|---|---|
"block" | 指令失敗時阻擋操作 |
"warn" | 顯示警告但繼續執行 |
"ignore" | 忽略失敗 |
10 個實用範例
1. 自動格式化(寫入後 Lint)
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{
"type": "command",
"command": "npx prettier --write \"$CLAUDE_FILE_PATHS\"",
"onFailure": "warn"
}
]
}
]
}
}
2. 自動執行測試
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{
"type": "command",
"command": "npm test -- --passWithNoTests",
"onFailure": "warn"
}
]
}
]
}
}
3. 阻擋危險指令
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "prompt",
"prompt": "檢查指令是否包含危險操作(rm -rf、DROP TABLE、git push --force)。如果是,回傳 'block'。否則回傳 'approve'。"
}
]
}
]
}
}
4. 防止讀取機密檔案
{
"hooks": {
"PreToolUse": [
{
"matcher": "Read",
"hooks": [
{
"type": "prompt",
"prompt": "如果檔案路徑包含 .env、secret、credential、password,回傳 'block'。否則回傳 'approve'。"
}
]
}
]
}
}
5. 檢查 API 金鑰洩漏
{
"hooks": {
"PreToolUse": [
{
"matcher": "Write",
"hooks": [
{
"type": "prompt",
"prompt": "掃描內容中是否有 API 金鑰(sk_、api_key、token)。如果找到,回傳 'block' 並說明原因。否則回傳 'approve'。"
}
]
}
]
}
}
6. 強制測試通過才能結束
{
"hooks": {
"Stop": [
{
"matcher": "*",
"hooks": [
{
"type": "command",
"command": "npm test",
"onFailure": "block"
}
]
}
]
}
}
7. 顯示 Session 啟動訊息
{
"hooks": {
"SessionStart": [
{
"matcher": "*",
"hooks": [
{
"type": "command",
"command": "echo 'Claude Code 已啟動 - 專案:'$(basename $(pwd))",
"onFailure": "ignore"
}
]
}
]
}
}
8. TypeScript 型別檢查
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{
"type": "command",
"command": "npx tsc --noEmit",
"onFailure": "warn"
}
]
}
]
}
}
9. Git Commit 前置檢查
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "prompt",
"prompt": "如果指令是 git commit 或 git push,確認測試已通過。如果不確定,回傳 'ask' 詢問使用者。否則回傳 'approve'。"
}
]
}
]
}
}
10. 敏感目錄保護
{
"hooks": {
"PreToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{
"type": "prompt",
"prompt": "如果檔案在 auth/、payment/、admin/ 目錄中,回傳 'ask' 要求確認。否則回傳 'approve'。"
}
]
}
]
}
}
常見錯誤排除
錯誤 1:Hook 沒有觸發
症狀:已設定 Hook 但沒有執行
確認清單:
- JSON 格式是否正確?用
jq . .claude/settings.json驗證 - Matcher 拼寫是否正確?(
Write不是write) - 檔案位置是否正確?(
.claude/settings.json) - 是否重新啟動了 Claude?
解法:
# 驗證 JSON 格式
cat .claude/settings.json | jq .
# 重新啟動 Claude
claude
錯誤 2:Command Hook 執行失敗
症狀:Hook command failed with exit code X
常見原因:
- 找不到指令路徑
- 權限不足
- 指令本身有錯誤
解法:
# 先手動測試指令
npm test
# 確認指令在 PATH 中
which npm
錯誤 3:Prompt Hook 的判斷不如預期
症狀:Hook 做出錯誤判斷或沒有回應
改善方式:
不好的 prompt:
{
"prompt": "檢查這是否安全"
}
好的 prompt:
{
"prompt": "檢查指令是否包含 'rm -rf'。如果是,回傳 'block'。否則回傳 'approve'。只回傳這兩個值之一。"
}
錯誤 4:環境變數問題
症狀:$CLAUDE_FILE_PATHS 是空的
解法:只有特定 Hook 事件才有對應的變數
| 變數 | 可用的 Hook |
|---|---|
$CLAUDE_FILE_PATHS | PostToolUse(Write/Edit 之後) |
$CLAUDE_PROJECT_DIR | 所有 Hook |
錯誤 5:無限迴圈
症狀:Hook 觸發 Hook,陷入迴圈
原因:Hook 執行的指令又觸發了另一個 Hook
解法:使用更精確的 matcher,或避免在指令中觸發其他工具
最佳實踐
1. 從簡單開始
不要一次設定太多 Hook。先從一個開始:
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write",
"hooks": [
{
"type": "command",
"command": "echo 'File written!'",
"onFailure": "ignore"
}
]
}
]
}
}
2. 適當使用 onFailure
| 情境 | 建議設定 |
|---|---|
| 測試必須通過 | "onFailure": "block" |
| Lint 可以有警告 | "onFailure": "warn" |
| 非關鍵性檢查 | "onFailure": "ignore" |
3. 分層設定
PreToolUse → 防止危險操作(安全性)
PostToolUse → 自動化檢查(品質)
Stop → 確認完成標準(交付)
4. 團隊共用
將 .claude/settings.json 加入 Git,讓團隊共享相同的 Hooks:
git add .claude/settings.json
git commit -m "Add Claude Code hooks for team standards"
完整設定範例
以下是適合大多數專案的起始設定:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "prompt",
"prompt": "檢查指令是否包含危險操作(rm -rf、DROP、--force)。如果是,回傳 'block'。否則回傳 'approve'。"
}
]
},
{
"matcher": "Read",
"hooks": [
{
"type": "prompt",
"prompt": "如果路徑包含 .env 或 secret,回傳 'block'。否則回傳 'approve'。"
}
]
}
],
"PostToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{
"type": "command",
"command": "npm run lint -- --quiet 2>/dev/null || true",
"onFailure": "ignore"
}
]
}
],
"Stop": [
{
"matcher": "*",
"hooks": [
{
"type": "command",
"command": "npm test -- --passWithNoTests 2>/dev/null",
"onFailure": "warn"
}
]
}
],
"SessionStart": [
{
"matcher": "*",
"hooks": [
{
"type": "command",
"command": "echo '專案:'$(basename $(pwd))",
"onFailure": "ignore"
}
]
}
]
}
}
下一步
學完 Hooks 基礎後,推薦繼續閱讀:
- Hooks 完整指南 - 進階設定與更多範例
- Hooks 開發手冊 - 腳本開發細節
- TDD 工作流程 - 用 Hooks 實現 TDD
- 安全最佳實踐 - 安全相關的 Hook 設定
總結
| 你想要… | 使用這個 Hook |
|---|---|
| 阻擋危險操作 | PreToolUse + prompt |
| 自動 lint/測試 | PostToolUse + command |
| 確保完成前測試通過 | Stop + command |
| Session 啟動時執行 | SessionStart + command |
記住:Hooks 把「建議」變成「強制執行」。設定一次,永久生效。
最後更新:2026-01-19