Claude Code Hooks 實戰:從架構原理到5個可複製的安全配方
整理版優先睇
Claude Code Hooks 利用 PreToolUse 嘅 exit 2 硬攔截,實現敏感文件、危險命令同 PII 嘅安全防護,係唯一提供完整 Hook 事件同 exit code 攔截嘅 AI 編程工具。
呢篇文章係陸徐洲寫嘅,佢係一家 LIMS 公司嘅 AI 算法負責人,正在寫《駕馭AI》呢本書。佢想解決嘅問題係:AI Agent 處理客戶數據、分析業務表格嗰陣,會唔小心輸出敏感信息,例如身份證號、手機號,甚至執行危險命令。整體結論係:要用 Claude Code 嘅 Hook 系統建立硬防護,尤其係 PreToolUse 嘅 exit 2 攔截,先至係真正可靠。
文章首先解釋咗 Hook 系統嘅設計原理。Claude Code 有 20 幾種事件,最常用係 PreToolUse 同 PostToolUse。PreToolUse 可以硬攔截,exit 2 就直接取消操作,AI 繞唔過;PostToolUse 係注入建議,但模型可以無視。作者強調「攔截寧可誤殺,過濾寧可漏過」,呢個係 fail-safe 原則。
然後作者分享咗 5 個安全配方:敏感文件守衞(.env 等)、危險命令攔截(rm -rf)、PII 文件攔截(身份證號自動脱敏)、寫入後自動格式化、提交前自動測試。佢仲做咗對比實驗,證實 PreToolUse 係硬防護。最後提醒,目前只有 Claude Code 提供完整 Hook 系統,其他工具都未有。
- PreToolUse 嘅 exit 2 係唯一真正硬攔截,PostToolUse 只係建議,模型有機會無視。
- 5 個安全配方包括敏感文件守衞、危險命令攔截、PII 文件攔截、寫入後格式化、提交前測試,可直接複製。
- PreToolUse 同 PostToolUse 能力不對稱,攔截寧可誤殺,過濾寧可漏過。
- CLAUDE.md 同 PostToolUse 係軟約束,面對不可逆操作必須用硬約束。
- 從第一天就將 Hook 當作工程紀律,喺 settings.json 配置配方,防止事故。
設計原理:PreToolUse 先係硬防護
Claude Code 嘅 Hook 事件有 20 幾種,但安全防護最常用嘅係 PreToolUse 同 PostToolUse。一個喺 AI 執行工具之前觸發,一個喺之後觸發。佢哋嘅能力係唔對稱嘅。
PreToolUse 能硬攔截,exit 2 直接取消操作,AI 繞唔過,就算開咗 bypass 模式都冇用。
PostToolUse 可以做嘅係往 Claude 嘅上下文注入信息,但只係「建議」,唔係「命令」。作者喺書嘅框架裏面將呢個唔對稱性做得更徹底:pre_tool 異常默認拒絕操作,post_tool 異常默認放行。控制工程叫 fail-safe 原則,傳感器故障時默認切斷進料,唔係默認繼續。
5 個安全配方:從敏感文件到自動測試
配置放喺 .claude/settings.json(團隊共享)或 .claude/settings.local.json(個人)。Hook 腳本從 stdin 接收 JSON,exit 0 放行,exit 2 攔截。以下係五個可以直接複製嘅配方。
- 1 敏感文件守衞:攔截 AI 讀取 .env、.pem、.key 等敏感檔案,直接 exit 2 阻止。
- 2 危險命令攔截:偵測 rm -rf、DROP TABLE、git push --force 等不可逆操作,硬攔截。
- 3 PII 文件攔截:Read 工具執行前掃描檔案內容,發現身份證號就 exit 2,逼 AI 用 sed 脱敏。
- 4 寫入後自動格式化:PostToolUse 觸發,AI 改完檔案後自動跑 prettier,唔會攔截。
- 5 提交前自動測試:PostToolUse 配合 if 字段,只喺 git commit 時執行 npm test。
# 配方一:敏感文件守衞
case "$(basename "$FILE_PATH")" in
.env*) echo "禁止訪問環境變量文件" >&2; exit 2 ;;
esac
# 配方二:危險命令攔截
if echo "$COMMAND" | grep -qE 'rm[[:space:]]+-rf'; then
echo "Hook攔截:危險命令 rm -rf" >&2; exit 2
fi
# 配方三:PII 文件攔截
if [ "$TOOL_NAME" = "Read" ] && [ -f "$FILE_PATH" ]; then
ID_COUNT=$(grep -cE '[1-9][0-9]{5}(19|20)[0-9]{2}...' "$FILE_PATH")
if [ "$ID_COUNT" -gt 0 ]; then
echo "包含PII,禁止直接讀取,請用sed脱敏後輸出" >&2; exit 2
fi
fi
# 配方四:寫入後自動格式化(PostToolUse)
{"matcher": "Edit|Write", "hooks": [{"type": "command", "command": "jq -r '.tool_input.file_path' | xargs npx prettier --write"}]}
# 配方五:提交前自動測試(PostToolUse)
{"matcher": "Bash", "hooks": [{"type": "command", "if": "Bash(git commit*)", "command": "cd $CLAUDE_PROJECT_DIR && npm test"}]}
實驗結果:PreToolUse 硬攔截有效
作者用書裏嘅企業級框架 harness_py_pro 做咗對比實驗:10 條患者數據,三輪遞進。第一輪冇 Hook,身份證號同手機號完整裸露;第二輪加 PreToolUse,.env 被攔截;第三輪 PreToolUse + PostToolUse 雙重防護,身份證號自動脱敏。
結論:PreToolUse 嘅 exit 2 係真正嘅硬防護,PostToolUse 只係軟約束。
目前 Codex CLI、Gemini CLI、Cursor 都冇 Hook 系統,Claude Code 係唯一提供完整 Hook 事件同 exit code 攔截嘅 AI 編程工具。作者提醒:CLAUDE.md 同 PostToolUse 嘅 stdout 都依賴模型理解,係「軟約束」;PreToolUse 嘅 exit 2 係代碼強制執行嘅「硬約束」——擋唔小心用軟約束夠,擋不可逆嘅必須用硬約束。
大家好,我係陸徐洲。
第一篇 Harness實戰文章嘅結尾,我寫咗一句話:「目前最成熟嘅 Harness 系統係 Claude Code 本身,佢嘅 hooks、skills、settings.json 組成咗一套完整嘅控制架構。」
今日就詳細講嚇呢句話。唔止係教你點樣配,我會從正在寫嘅書《駕馭AI》度拎出設計原理,講清楚點解要咁設計,然後畀你 5 個可以直接複製嘅安全配方。
先睇嚇以下場景。10 條患者數據,身份證號碼、手機號碼全部裸露喺 CSV 裏面。叫 AI Agent 去讀呢個檔案,佢會原樣輸出每一個字符。
130191419371218041X,13812345678。
你喺公司內部有冇跑過類似場景?叫 AI 幫手處理客戶數據、分析業務表格、睇配置文件。佢做嘢又快又好,但佢唔知啲乜嘢唔應該講出嚟。
先睇一眼唔加任何防護嘅結果。

身份證號碼、手機號碼,一字不差咁輸出咗。
再睇加咗 Hook 防護之後嘅同一份數據:

1301914********041X,138****5678同樣嘅數據,身份證中間 8 位變咗做星號,手機號中間 4 位被遮咗。
呢個就係 Claude Code Hooks 做嘅嘢。
先講一個關鍵嘅設計決策。
Claude Code 嘅 Hook 事件有 20 多種,覆蓋會話生命週期、配置變更、多 Agent 協作等場景。安全防護最常用嘅係兩種:PreToolUse 同 PostToolUse。一個喺 AI 執行工具之前觸發,一個喺執行之後觸發。
佢哋嘅能力係唔對稱嘅PreToolUse 可以硬攔截,腳本返回 exit 2,操作直接俾人取消,AI 繞唔過,就算開咗 bypass 模式都冇用。PostToolUse 可以做嘅係向 Claude 嘅上下文度注入信息,但佢係「建議」,唔係「命令」。
我喺本書嘅框架 harness_py_pro 度將呢個唔對稱性做得更加徹底:pre_tool 嘅異常默認拒絕操作,post_tool 嘅異常默認放行。控制工程裏面叫 fail-safe 原則,傳感器故障時默認切斷進料,唔係默認繼續。
一句講曬:攔截寧可誤殺,過濾寧可漏過。
實驗驗證過咗。我先用 PostToolUse 注入一段 PII 脱敏警告,結果 Opus 4.6 直接無視,用戶明確要求「包括身份證號碼同手機號碼」,模型認為用戶意圖優先。所以最終方案係將 PII 檢測放喺 PreToolUse 度,exit 2 硬攔截。
唔係所有 Hook 事件都一樣可靠,揀錯位置,防護形同虛設。
講完原理,上配方。先睇 Claude Code 嘅 Hooks 配置係點樣:

配置在 .claude/settings.json 裏面。團隊共享用 .claude/settings.json,個人用 .claude/settings.local.json。Hook 腳本從 stdin 接收 JSON,exit 0 放行,exit 2 攔截。
配方一:敏感文件守衞。 攔截 AI 讀取 .env、.pem、.key。
case "$(basename "$FILE_PATH")" in
.env*) echo "禁止訪問環境變量文件" >&2; exit 2 ;;
esac實際效果:

Claude 回覆話「呢個係項目安全防護嘅預期行為,.env 檔案唔應該俾 AI 直接訪問」。佢明白點解被攔。
配方二:危險命令攔截。 rm -rf、DROP TABLE、git push --force一旦執行冇後悔藥。
if echo "$COMMAND" | grep -qE 'rm[[:space:]]+-rf'; then
echo "Hook攔截:危險命令 rm -rf" >&2; exit 2
fi實際效果:

紅色報錯,硬攔截。
配方三:PII 檔案攔截。 嚟自書裏面第 9 章嘅醫療合規案例。讀取前先掃描檔案內容,發現身份證號碼就攔截,話畀 AI 用脱敏方式處理。
if [ "$TOOL_NAME" = "Read" ] && [ -f "$FILE_PATH" ]; then
ID_COUNT=$(grep -cE '[1-9][0-9]{5}(19|20)[0-9]{2}...' "$FILE_PATH")
if [ "$ID_COUNT" -gt 0 ]; then
echo "包含PII,禁止直接讀取,請用sed脱敏後輸出" >&2; exit 2
fi
fi關鍵點:唔係話畀 AI「請注意脱敏」,而係直接攔截讀取,逼佢行脱敏流程。話畀佢聽同攔截係兩回事。
實際效果:

Hook 攔截後,Claude 自動改用 sed 命令做脱敏,身份證號碼中間全部係星號。
配方四:寫入後自動格式化。 PostToolUse,唔攔截,AI 改完檔案後自動跑 prettier。
{"matcher": "Edit|Write", "hooks": [{"type": "command",
"command": "jq -r '.tool_input.file_path' | xargs npx prettier --write"}]}配方五:提交前自動測試。 git commit 之前先跑測試。
{"matcher": "Bash", "hooks": [{"type": "command",
"if": "Bash(git commit*)",
"command": "cd $CLAUDE_PROJECT_DIR && npm test"}]}if 字段做參數過濾,淨係喺 git commit 嗰陣觸發,唔會每條 bash 命令都跑測試。
五個配方之外,我仲用書裏面嘅企業級框架 harness_py_pro 跑咗一組對比實驗。同一套設計哲學,Python 版嘅 HookExecutor 實現。三輪遞進,10 條患者數據。
第一輪冇 Hook,身份證號碼同手機號碼完整裸露。第二輪加 PreToolUse,.env 被攔截。

第三輪 PreToolUse + PostToolUse 雙重防護,身份證號碼自動脱敏:

三輪彙總一張表講清楚:

兩組實驗,同一個結論。PreToolUse 嘅 exit 2 係真正嘅硬防護。
有一件事值得講多句。CLAUDE.md 同 PostToolUse 嘅 stdout 都依賴模型理解同遵守,係「軟約束」。PreToolUse 嘅 exit 2 係代碼強制執行嘅「硬約束」。擋「唔小心」用軟約束夠啦,擋「不可逆嘅」就一定要用硬約束。
目前 Codex CLI、Gemini CLI、Cursor 都冇 Hook 系統。Claude Code 係唯一提供完整 Hook 事件同 exit code 攔截嘅 AI 編程工具。呢個都係我喺書度揀佢做參考實現嘅原因。
今日嘅 5 個配方同實驗代碼都開源喺書嘅代碼倉庫度。企業級用 Python 嘅 HookExecutor,個人用 Claude Code 嘅 settings.json,設計哲學一樣,揀適合自己嘅就得。
能力越強嘅系統就越需要精密嘅控制,呢個道理唔會過時。分別只在於,你係喺事故之後先至諗起加防護,定係由第一日就將佢當做工程紀律。
我係陸徐洲,一間 LIMS 公司嘅 AI 算法負責人。關注我,等我哋一齊喺 AI 落地實踐嘅路上,行得更遠。
多謝你睇我嘅文章。有任何關於 AI 提效或者工程落地實踐方面嘅問題都可以加我微信,交個朋友,一齊探討,共同進步。

大家好,我是陸徐洲。
第一篇 Harness實戰文章的結尾,我寫了一句話:"目前最成熟的 Harness 系統是 Claude Code 本身,它的 hooks、skills、settings.json 組成了一套完整的控制架構。"
今天展開這句話。不只是教你配,我會從正在寫的書《駕馭AI》裏拿出設計原理,講清楚為什麼這麼設計,然後給你 5 個可以直接複製的安全配方。
先看看以下場景。10 條患者數據,身份證號、手機號全裸露在 CSV 裏。讓 AI Agent 去讀這個文件,它會原樣輸出每一個字符。
130191419371218041X,13812345678。
你在公司內部跑過類似場景嗎?讓 AI 幫忙處理客戶數據、分析業務表格、查看配置文件。它幹活又快又好,但它不知道哪些東西不該說出來。
先看一眼不加任何防護的結果。

身份證號、手機號,一字不差地輸出了。
再看加了 Hook 防護之後的同一份數據:

1301914********041X,138****5678。同樣的數據,身份證中間 8 位變成了星號,手機號中間 4 位被遮掉了。
這就是 Claude Code Hooks 乾的事。
先說一個關鍵的設計決策。
Claude Code 的 Hook 事件有 20 多種,覆蓋會話生命週期、配置變更、多 Agent 協作等場景。安全防護最常用的是兩種:PreToolUse 和 PostToolUse。一個在 AI 執行工具之前觸發,一個在執行之後觸發。
它們的能力是不對稱的。PreToolUse 能硬攔截,腳本返回 exit 2,操作直接被取消,AI 繞不過去,哪怕開了 bypass 模式也沒用。PostToolUse 能做的是往 Claude 的上下文裏注入信息,但它是"建議",不是"命令"。
我在書的框架 harness_py_pro 裏把這個不對稱性做得更徹底:pre_tool 的異常默認拒絕操作,post_tool 的異常默認放行。控制工程裏叫 fail-safe 原則,傳感器故障時默認切斷進料,不是默認繼續。
一句話:攔截寧可誤殺,過濾寧可漏過。
實驗驗證過了。我先用 PostToolUse 注入一段 PII 脱敏警告,結果 Opus 4.6 直接無視,用戶明確要求"包括身份證號和手機號",模型認為用戶意圖優先。所以最終方案是把 PII 檢測放到 PreToolUse 裏,exit 2 硬攔截。
不是所有 Hook 事件都一樣可靠,選錯位置,防護形同虛設。
說完原理,上配方。先看 Claude Code 的 Hooks 配置長什麼樣:

配置在 .claude/settings.json 裏。團隊共享用 .claude/settings.json,個人用 .claude/settings.local.json。Hook 腳本從 stdin 接收 JSON,exit 0 放行,exit 2 攔截。
配方一:敏感文件守衞。 攔截 AI 讀取 .env、.pem、.key。
case "$(basename "$FILE_PATH")" in
.env*) echo "禁止訪問環境變量文件" >&2; exit 2 ;;
esac實際效果:

Claude 回覆說"這是項目安全防護的預期行為,.env 文件不應被 AI 直接訪問"。它理解了為什麼被攔。
配方二:危險命令攔截。 rm -rf、DROP TABLE、git push --force,一旦執行沒有後悔藥。
if echo "$COMMAND" | grep -qE 'rm[[:space:]]+-rf'; then
echo "Hook攔截:危險命令 rm -rf" >&2; exit 2
fi實際效果:

紅色報錯,硬攔截。
配方三:PII 文件攔截。 來自書裏第 9 章的醫療合規案例。讀取前先掃描文件內容,發現身份證號就攔截,告訴 AI 用脱敏方式處理。
if [ "$TOOL_NAME" = "Read" ] && [ -f "$FILE_PATH" ]; then
ID_COUNT=$(grep -cE '[1-9][0-9]{5}(19|20)[0-9]{2}...' "$FILE_PATH")
if [ "$ID_COUNT" -gt 0 ]; then
echo "包含PII,禁止直接讀取,請用sed脱敏後輸出" >&2; exit 2
fi
fi關鍵點:不是告訴 AI"請注意脱敏",而是直接攔截讀取,逼它走脱敏流程。告訴和攔截是兩回事。
實際效果:

Hook 攔截後,Claude 自動改用 sed 命令做脱敏,身份證號中間全是星號。
配方四:寫入後自動格式化。 PostToolUse,不攔截,AI 改完文件後自動跑 prettier。
{"matcher": "Edit|Write", "hooks": [{"type": "command",
"command": "jq -r '.tool_input.file_path' | xargs npx prettier --write"}]}配方五:提交前自動測試。 git commit 之前先跑測試。
{"matcher": "Bash", "hooks": [{"type": "command",
"if": "Bash(git commit*)",
"command": "cd $CLAUDE_PROJECT_DIR && npm test"}]}if 字段做參數過濾,只在 git commit 時觸發,不會每條 bash 命令都跑測試。
五個配方之外,我還用書裏的企業級框架 harness_py_pro 跑了一組對比實驗。同一套設計哲學,Python 版的 HookExecutor 實現。三輪遞進,10 條患者數據。
第一輪無 Hook,身份證號和手機號完整裸露。第二輪加 PreToolUse,.env 被攔截。

第三輪 PreToolUse + PostToolUse 雙重防護,身份證號自動脱敏:

三輪彙總一張表說清楚:

兩組實驗,同一個結論。PreToolUse 的 exit 2 是真正的硬防護。
有一件事值得多說一句。CLAUDE.md 和 PostToolUse 的 stdout 都依賴模型理解和遵守,是"軟約束"。PreToolUse 的 exit 2 是代碼強制執行的"硬約束"。擋"不小心"用軟約束夠了,擋"不可逆的"必須用硬約束。
目前 Codex CLI、Gemini CLI、Cursor 都沒有 Hook 系統。Claude Code 是唯一提供完整 Hook 事件和 exit code 攔截的 AI 編程工具。這也是我在書裏選它當參考實現的原因。
今天的 5 個配方和實驗代碼都開源在書的代碼倉庫裏。企業級用 Python 的 HookExecutor,個人用 Claude Code 的 settings.json,設計哲學一樣,選適合自己的就行。
能力越強的系統越需要精密的控制,這個道理不會過時。區別只在於,你是在事故之後才想起來加防護,還是從第一天就把它當作工程紀律。
我是陸徐洲,一家 LIMS 公司的 AI 算法負責人。關注我,讓我們一起在 AI 落地實踐的路上,走得更遠。
感謝您閲讀我的文章。有任何關於AI提效或者工程落地實踐方面的問題都可以加我微信,交個朋友,一起探討,共同進步。
