iT邦幫忙

2026 iThome 鐵人賽

DAY 9
0
AI Engineering

30 天打造我的 AI 開發工作流:從需求分析到上線系列 第 9

Day 09|Hooks:讓規則從「希望它照做」變成「它做不到」

  • 分享至 

  • xImage
  •  

前言

昨天的 /spec-check 可以告訴我規格哪裡有問題,但它只是「告訴我」。如果我希望某條規則不能被違反,而不是期待 Claude 記得遵守,就得再往下一層。

這就是今天要介紹的 Hooks。


昨天說到

昨天做出第一支自己的 skill,它會逐條檢查規格、輸出缺口報告。

但它有個限制:觸發的方式是我得記得叫它。 而且就算它報出九項必補,也沒有任何東西阻止我直接把規格交出去。

這其實是 D04 就埋下的問題:

CLAUDE.md 是 Context,不是防火牆。

當時只是先提到,今天就把這件事情講完:如果真的想阻止 Claude 做某件事,該怎麼做?


為什麼 CLAUDE.md 擋不住東西

CLAUDE.md 的內容會在每個 session 開始時被讀進 context。它是資訊,不是設定

所以「不要直接改 migration 檔」這句話寫在 CLAUDE.md 裡,效果等於在一段很長的提示詞裡加一句叮嚀。Claude 大部分時候會照做,但不是一道門檻。


hook 是什麼

Hook 就是在 Claude Code 執行某個動作前後,插入一段自己的程式。

https://ithelp.ithome.com.tw/upload/images/20260908/20183588IhTEkZXgen.png

Hook 設定放在:

.claude/settings.json

例如:

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          { "type": "command", "command": "./.claude/guard.sh" }
        ]
      }
    ]
  }
}

這裡有兩個重點:

  • PreToolUse:工具執行之前觸發
  • matcher:指定哪些工具要經過這個 Hook

Claude Code 有很多不同的 Hook Event,和開發流程比較相關的幾個如下:

事件 什麼時候觸發
PreToolUse 工具呼叫執行之前
PostToolUse 工具呼叫成功之後
Stop Claude 準備結束回應時
SessionStart session 開始或恢復
InstructionsLoaded CLAUDE.md 或 rules 被載入時

實作:一支保護憲法的 hook

這次我想做一個很簡單的 Hook:禁止 Claude 修改專案憲法。

Step 1:建立 Hook
我使用 Python 寫一個簡單的檢查:

event = json.load(sys.stdin)

target = event["tool_input"]["file_path"]

if 是憲法:
    sys.stderr.write("constitution.md 不允許由 AI 修改")
    return 2

它只做三件事:

  • 從 stdin 讀取 Claude Code 傳進來的事件
  • 找出 Claude 想修改的檔案
  • 如果是 constitution.md,回傳 exit 2

Step 2:設定 settings.json
設定放專案的 .claude/settings.json

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "python \"$CLAUDE_PROJECT_DIR/.claude/hooks/guard-constitution.py\"",
            "statusMessage": "檢查是否修改受保護檔案"
          }
        ]
      }
    ]
  }
}

踩到的坑:它其實從來沒有生效

第一層:Matcher 沒有攔到

我開一個新的 Session 請 Claude:把憲法第一條從 snake_case 改成 camelCase,結果它真的改成功了。

看執行紀錄才發現:Claude 這次不是使用 Edit 或 Write,而是 Bash → 執行指令 → 修改檔案。我原本的 Matcher 只有 Edit|Write,所以 Hook 根本沒有被觸發。

這件事很容易被忽略:你以為你在保護「檔案」,但 PreToolUse 實際上是在攔「工具」。

第二層:補上 Bash,還是不夠

於是我把 Matcher 改成 Edit|Write|NotebookEdit|Bash,這次真的擋住了,但我又測了幾個情境:

  • 修改 settings.json
  • 修改 Hook 自己
  • 用 Bash 刪除設定檔

結果是全部放行,原因很簡單,我保護的是:constitution.md,這道門會保護憲法,卻不保護自己,所以我又把 Hook 本身和設定檔加入保護範圍。

第三層:Hook 攔的是工具,不是人

Claude 又提醒我一件事:

PreToolUse 只能攔 Claude Code 的工具呼叫,不能攔人直接修改檔案。

如果真的要做到檔案層級的保護,還是要靠:

  • OS 權限
  • Read-only
  • Git branch / protection
  • CI/CD

Hook 比較適合拿來做:流程的門檻,而不是:檔案系統的防火牆。


小結

  • CLAUDE.md 是 Context,不是強制規則。 它可以告訴 Claude 怎麼做,但不能保證 Claude 一定照做。
    Hook 是把規則變成執行時檢查的機制。 可以在工具執行前後介入流程。
  • PreToolUse 可以阻止工具執行,Stop 則可以阻止 Claude 結束回應。
  • Hook 攔的是工具呼叫,不是檔案本身。

明天:hook 讓規則在本機有了執行力,但它擋的都是這台機器上的事。如果規格不只活在 markdown,還存在 Issue、Database Schema、套件文件裡呢?

這時候,就要讓 Claude 連出去:MCP。


上一篇
Day 08|Command 與 Skill:把 SOP 變成自己的一組指令
系列文
30 天打造我的 AI 開發工作流:從需求分析到上線9
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言