MO STORIES

Claude Code Hooks 完整教學(2026):自動化排程、Slash Command 與專案工作流

2026年4月26日16 MIN READ

如果你 Google「Claude Code Hooks」,多半會看到官方文件那幾頁。 技術細節都對,但你看完還是不知道 —— hook 到底什麼時候用、什麼時候用 cron 比較好、5 種 hook 類型差在哪? 這篇是我跑了 30+ hook、踩過 5 個坑之後整理的實作版本。 如果你只想知道結論: Hook = ...

Claude Code Hooks 完整教學(2026):自動化排程、Slash Command 與專案工作流
Cover Visual

Claude Code Hooks 完整教學(2026):自動化排程、Slash Command 與專案工作流

如果你 Google「Claude Code Hooks」,多半會看到官方文件那幾頁。

技術細節都對,但你看完還是不知道 ——
hook 到底什麼時候用、什麼時候用 cron 比較好、5 種 hook 類型差在哪?

這篇是我跑了 30+ hook、踩過 5 個坑之後整理的實作版本。

如果你只想知道結論:

  • Hook = 事件驅動自動化(不是時間驅動)
  • 5 種類型 + 1 個排程器 = 90% 情境都涵蓋
  • settings.json 是入口,但要避開 3 個雷區

下面開始。

Hook 是什麼?跟 cron 差在哪

Claude Code Hooks 是 Claude Code 在「特定事件發生時」自動跑指令的機制。

跟 cron 最大的差別:

維度 cron / scheduled-tasks Claude Code Hooks
觸發方式 時間(每 5 分鐘 / 每天 09:00) 事件(工具呼叫前後 / agent 停止 / session 開始)
適合情境 定期掃描、健康檢查、固定排程 對 Claude 動作的即時反應
執行環境 系統 cron daemon Claude Code 自身 process
context 沒有 帶 tool name、prompt、session 資訊

簡單說:

  • 要做「每天早上 9 點寄電子報」 → 用 cron / scheduled-tasks
  • 要做「每次 Claude 寫完一篇文章自動 sync 到 Notion」 → 用 hook

兩者可以搭配用,不是替代關係。

Claude Code 的 5 種 Hook 類型

截至 2026 年 4 月,Claude Code 支援 5 種 hook:

Hook 類型 觸發時機 常見用途
PreToolUse Claude 呼叫工具 攔截危險指令、改寫參數、要求人工確認
PostToolUse Claude 呼叫工具 結果驗證、log 記錄、後續通知
Stop Agent 停止時 session summary、自動 commit、清理 temp 檔
UserPromptSubmit 使用者送訊息時 inject context、檢查格式、attach 檔案
SessionStart session 開始時 載入專案規則、初始化環境變數、印 todo 清單

每種 hook 都對應一個事件 → 你寫的指令會在那個瞬間被執行。

觸發鏈(重要)

順序很重要,不然會踩坑:

SessionStart
  → UserPromptSubmit(每次你送訊息)
    → PreToolUse(每次 Claude 用工具前)
      → [tool 真正執行]
    → PostToolUse(每次工具執行後)
  → Stop(agent 結束回合)

settings.json 完整設定範例

Hook 寫在 .claude/settings.json(專案層)或 ~/.claude/settings.json(使用者層)。

最小可運作範例

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Write",
        "hooks": [
          {
            "type": "command",
            "command": "echo '⚠️ Claude 想寫檔案,按 Enter 繼續' && read"
          }
        ]
      }
    ]
  }
}

這個 hook 每次 Claude 用 Write 工具前會等你按 Enter。

完整範例(5 種 hook 都用)

{
  "hooks": {
    "SessionStart": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "cat .claude/rules/quick-summary.md"
          }
        ]
      }
    ],
    "UserPromptSubmit": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "echo \"[$(date +%H:%M)] $CLAUDE_USER_PROMPT\" >> .claude/prompt-log.txt"
          }
        ]
      }
    ],
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "node .claude/hooks/check-dangerous-commands.js"
          }
        ]
      }
    ],
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "node .claude/hooks/lint-edited-file.js \"$CLAUDE_TOOL_FILE_PATH\""
          }
        ]
      }
    ],
    "Stop": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "node .claude/hooks/write-daily-summary.js"
          }
        ]
      }
    ]
  }
}

5 個我自己用的 hook(實戰)

下面是我在瘦桑 repo 跑了 3 個月以上的 hook,每個都解決一個具體痛點。

Hook 1:寫完文章自動 sync 到 Notion

痛點:每寫完一篇 SEO 文,都要記得跑 node scripts/notion/sync-to-notion.cjs。常常忘。

解法:PostToolUse hook 偵測到 articles/*.md 被 Edit 或 Write,自動 sync。

{
  "PostToolUse": [
    {
      "matcher": "Edit|Write",
      "hooks": [
        {
          "type": "command",
          "command": "node .claude/hooks/auto-sync-articles.js \"$CLAUDE_TOOL_FILE_PATH\""
        }
      ]
    }
  ]
}

.claude/hooks/auto-sync-articles.js

const path = require('path');
const { spawn } = require('child_process');

const filePath = process.argv[2];
if (!filePath) process.exit(0);
if (!filePath.match(/^articles\/.*\.md$/)) process.exit(0);

console.log(`✅ 偵測到文章編輯 ${filePath},自動 sync 到 Notion...`);
spawn('node', ['scripts/notion/sync-to-notion.cjs', filePath], {
  stdio: 'inherit',
  detached: true,
});

Hook 2:commit 前自動跑 lint

痛點:Claude 寫的東西常踩品牌禁句型與禁詞列表(規則寫在 .claude/rules/brand-voice.md)。

解法:PreToolUse 偵測到 git commit Bash 指令前,先跑 lint。

// .claude/hooks/check-dangerous-commands.js
const cmd = process.env.CLAUDE_TOOL_BASH_COMMAND || '';

if (cmd.startsWith('git commit')) {
  const { execSync } = require('child_process');
  try {
    execSync('node scripts/lint/brand-voice.js', { stdio: 'inherit' });
  } catch (e) {
    console.error('❌ 品牌語氣 lint 失敗,commit 取消');
    process.exit(2); // exit code 2 = block tool execution
  }
}

exit 2 會讓 Claude 中止執行那個工具,等於攔截 commit。

Hook 3:改完 .env 自動重啟 dev server

痛點:改完 .env 變數要手動重啟 npm run dev 才生效,常常忘。

// PostToolUse hook (matcher: "Edit|Write")
const filePath = process.argv[2];
if (filePath?.endsWith('.env') || filePath?.endsWith('.env.local')) {
  const { execSync } = require('child_process');
  console.log('♻️  .env 已修改,重啟 dev server...');
  execSync('pkill -f "next dev" || true && npm run dev &');
}

Hook 4:跑完測試自動發 Slack 通知

痛點:CI 跑完不會主動通知,要去 GitHub 看。

// PostToolUse hook (matcher: "Bash")
const cmd = process.env.CLAUDE_TOOL_BASH_COMMAND || '';
const exitCode = process.env.CLAUDE_TOOL_EXIT_CODE;

if (cmd.includes('npm test') || cmd.includes('vitest')) {
  const status = exitCode === '0' ? '✅ PASS' : '❌ FAIL';
  fetch(process.env.SLACK_WEBHOOK_URL, {
    method: 'POST',
    body: JSON.stringify({ text: `Test ${status}: ${cmd}` }),
  });
}

Hook 5:session 結束自動寫 daily summary

痛點:每天忙完,記不得做了什麼。

// Stop hook
const fs = require('fs');
const today = new Date().toISOString().slice(0, 10);
const summaryPath = `journal/${today.slice(0, 7).replace('-', '/')}/${today}-claude-log.md`;

const log = `\n[${new Date().toLocaleTimeString('zh-TW')}] Session ended.\n`;
fs.appendFileSync(summaryPath, log);

進階版可以叫 Claude 把那個 session 的對話內容自動摘要進去。

排程任務 vs Hooks:什麼時候用哪個?

兩者的決策樹:

我的需求 用什麼
每天 09:00 跑一次 scheduled-tasks(cron)
每次寫完檔案後 PostToolUse hook
攔截危險指令 PreToolUse hook
每週五自動跑分析 scheduled-tasks
每次 Claude 結束自動 commit Stop hook
監測 GitHub PR 狀態(每 5 min) scheduled-tasks
改完設定自動套用 PostToolUse hook
每次新訊息加 context UserPromptSubmit hook

簡單記法:

  • 時間驅動 = scheduled-tasks
  • 事件驅動 = hooks

踩過的 3 個坑

坑 1:hook 卡死整個 agent

寫了一個 hook 沒設 timeout,跑進無窮迴圈。整個 Claude Code 卡住要 ctrl+C 強殺。

解法:每個 hook 指令加 timeout:

{
  "type": "command",
  "command": "timeout 10 node .claude/hooks/my-hook.js"
}

10 秒沒跑完就強制終止。

坑 2:環境變數沒帶到

Hook 跑的是 child process,預設不會繼承所有 env。

解法:在 hook script 開頭明確 source .env

require('dotenv').config({ path: '/absolute/path/to/.env' });

不要用相對路徑。Hook 的 cwd 不一定是專案根目錄。

坑 3:自動化跑無窮迴圈

最危險的坑:PostToolUse hook 觸發 → hook 改檔 → 再觸發 PostToolUse → 無限。

例子:你寫 PostToolUse hook 在 Edit 後 auto-format,但 auto-format 也用 Edit 工具 → 觸發自己。

解法

  1. Hook 用 spawn 而非工具呼叫(不會再觸發 hook)
  2. 加防禦:
if (process.env.CLAUDE_HOOK_INVOKED === '1') {
  console.log('⏭ skip recursive hook');
  process.exit(0);
}
process.env.CLAUDE_HOOK_INVOKED = '1';

FAQ

Hook 寫在專案層還是使用者層?

  • 專案層.claude/settings.json):跟團隊共享、checked into git
  • 使用者層~/.claude/settings.json):個人習慣、所有專案都生效

我的習慣:核心邏輯(如 lint)放專案層,個人偏好(如通知)放使用者層。

為什麼我的 hook 沒觸發?

3 個常見原因:

  1. JSON 語法錯.claude/settings.json 有逗號錯位,整個 hooks 物件被忽略
  2. matcher 寫錯"Edit" vs "Edit|Write" 寫錯不報錯,靜默失敗
  3. Hook 指令在 PATH 找不到:用絕對路徑 /usr/local/bin/node ... 比較穩

Hook 可以呼叫 Claude API 嗎?

可以。例如 Stop hook 呼叫 Claude API 把 session 對話摘要進 daily summary。
但要注意成本——每次 Stop 都打 API 會累積。

Hook 裡可以用其他語言嗎?

可以。type: "command" 跑的是 shell command,所以 Python、Go、Bash 都行。
但 Node.js 最方便,因為通常專案內已經有 dependencies。

Hook 失敗會怎樣?

依 exit code:

  • 0 = 成功,繼續執行
  • 1 = 失敗但不 block,Claude 繼續做事
  • 2 = 失敗且 block,Claude 中止當前工具呼叫

寫 PreToolUse 想攔截動作,記得 process.exit(2)

小結

Claude Code Hooks 是 Claude Code 自動化的第二支柱(第一支柱是 scheduled-tasks)。

5 種類型分清楚:

  • PreToolUse → 攔截 / 改寫 / 確認
  • PostToolUse → 驗證 / 通知 / 後續動作
  • Stop → summary / commit / 清理
  • UserPromptSubmit → 加 context
  • SessionStart → 載入規則

決策一句話:時間用 cron,事件用 hook

如果你才剛開始,建議先從一個 PostToolUse + Stop hook 跑起來。3 天就會回不去手動。

延伸閱讀

MO 編輯

關於作者 | 10+ 經驗

MO 編輯

WordPress 效能優化專家 / MO Design Studio 共同創辦人

關注設計 × 工程的平衡協作,擅長以簡潔語言說故事。專門幫已有網站的品牌做速度升級。相信好網站不用重做,只需要正確的優化。

WordPress 優化SEO 策略Headless CMS效能稽核

延伸閱讀

Newsletter

訂閱瘦生活電子報

每週一封故事信——分享如何用減法思維剔除雜訊、做對的事、過好生活。不說教,不推銷,只有真實的取捨紀錄。

我們尊重隱私,絕不發送垃圾郵件。可隨時取消訂閱。

MO DESIGN STUDIO

我們專注品牌網站設計、行銷著陸頁與整合式 CMS 流程,協助團隊打造有感的線上體驗。

返回部落格