Claude Code hook 在 Windows 上無法運作:原因與解法

同一個 hook 在 Mac 上執行正常,到了 Windows 卻毫無反應,甚至更糟,會擋下每一個指令。原因幾乎都出在 shell。以下說明 Claude Code 在 Windows 上如何執行 hook,以及如何讓你的 hook 穩定可靠。

作者:Aslan,Pet Island 團隊 · 更新於 2026年10月26日 · 閱讀時間 5 分鐘

簡答

在 Windows 上,Claude Code 會用 Git Bash 執行 hook 的 command;若未安裝 Git Bash,則改用 PowerShell。請用 "shell": "powershell" 或 "shell": "bash" 明確指定要用哪一個,讓 stdout 只輸出一個 JSON 物件(不要有設定檔的 echo),用結束代碼 2 來封鎖,並更新 Claude Code(多個 Windows hook 錯誤已在 2.1.310 以前的版本中陸續修正)。用 /hooks 和 claude --debug 來除錯。

哪個 shell 會執行你的 hook

Claude Code 會把 command 字串交給 shell:macOS 和 Linux 上是 sh -c,Windows 上是 Git Bash,若未安裝 Git Bash 則是 PowerShell。hook 參考文件中的這一句話,就能解釋大多數「在我的 Mac 上可以」的回報。為 PowerShell 撰寫的指令在 Git Bash 中會失敗,bash 指令碼在 PowerShell 中會失敗,而你拿到的是哪一個,取決於電腦上剛好有沒有安裝 Git for Windows。

用 shell 欄位消除猜測。它接受 "bash" 或 "powershell":

%USERPROFILE%\.claude\settings.json複製
{
"hooks": {
"Notification": [
{
"matcher": "permission_prompt",
"hooks": [
{
"type": "command",
"shell": "powershell",
"command": "[Console]::Beep(880, 200)"
}
]
}
]
}
}

如果你想用 Git Bash 但 Claude Code 找不到它,請安裝 Git for Windows,或把 CLAUDE_CODE_GIT_BASH_PATH 設為它的位置,然後開啟新的工作階段。

症狀與成因

你看到的現象可能原因解法
hook 似乎從未執行Claude Code 版本過舊、事件或 matcher 錯誤、設定中的 JSON 無效更新;檢查 /hooks;移除註解和結尾逗號
ParserError 或「unexpected token」PowerShell 語法送到了 Git Bash,或反過來明確設定 shell
hook 輸出「does not start with {」JSON 之前印出了其他內容,通常來自 shell 設定檔讓設定檔不要輸出;把記錄寫到 stderr
混用 \ 和 / 的路徑找不到Windows 路徑變數接上了 Unix 風格的後綴使用 exec 形式:程式放在 command,每個引數放在 args
Git Bash 回報 powershell: Permission denied在 2.1.283 和 2.1.304 至 2.1.305 中間歇性出現(#103910,尚未解決)使用 "shell": "powershell",避免中間經過 Git Bash
防護 hook 讓所有東西都通過結束代碼用了 1 而不是 2,或是舊版「失敗即放行」(fail-open)的錯誤用結束代碼 2 封鎖;更新到 2.1.310 或更新版本
hook 立即返回且沒有輸出shell 不會等待的 GUI 子系統程式使用主控台程式,或等待該程序結束

stdout 只能有 JSON

Claude Code 會把 hook 的標準輸出當成它的回應。文件中的規則很簡短:stdout 除了 JSON 物件之外什麼都不要印。在 Windows 上,這條規則會以不易察覺的方式被打破:Git Bash 和某些環境仍會載入你的 shell 設定檔,而設定檔中無條件執行的 echo 會被加在 JSON 前面。結果 hook 在終端機中「正常」,在 Claude Code 裡卻失敗。

請改把記錄寫到檔案或 stderr,並讓設定檔只在互動式 shell 中才輸出。

結束代碼:2 會封鎖,1 不會

結束代碼 0 表示成功。結束代碼 2 是封鎖性錯誤:在可封鎖的事件上,Claude Code 會停止該動作並顯示你的 stderr。結束代碼 1 且沒有有效 JSON 時是非封鎖性錯誤,動作會繼續執行。 如果你的 hook 要強制執行某項政策,請用結束代碼 2。

並非每個事件都能這樣封鎖。Notification hook 的結束代碼會被忽略。以結束代碼 2 結束的 Stop hook 會讓 Claude 繼續工作。PermissionRequest hook 則完全忽略結束代碼 2,而是透過 JSON 中的 decision 物件做決定。

Claude Code 2.1.309 修正了 hook 的程式以代碼 2 結束時,PowerShell hook 不會封鎖的問題。如果你的 PowerShell 防護似乎被忽略,請先檢查版本。

值得為此更新的 Windows 修正

Anthropic 的變更記錄中有一長串 Windows hook 修正。以下是能解釋舊論壇討論串的幾項:

版本修正
2.1.47PreToolUse 和 PostToolUse hook 在 Windows 上靜默失敗;現在改用 Git Bash 而非 cmd.exe 執行
2.1.161明確呼叫 bash 的 hook(/usr/bin/bash script.sh)以「command not found」失敗
2.1.299未設定 shell 的 PreToolUse 和 PermissionRequest hook,在沒有 Git for Windows 時,失敗會直接放行(fail open);現在失敗的防護會封鎖
2.1.309PowerShell hook 遇到結束代碼 2 時不會封鎖;"shell": "powershell" 防護在沒有 Git for Windows 時,失敗會直接放行(fail open)
2.1.310指令只有加引號字串(例如加引號的路徑)的防護,在沒有 Git Bash 時,失敗會直接放行(fail open)

較早的 issue「No hook is working on Windows」(#10450)是在 2.0.27 上回報的;一位留言者追查到原因是 stdin 沒有傳到 hook 指令。如果你的版本這麼舊,請先更新再除錯其他東西。

直接呼叫程式

如果你的 hook 是編譯好的程式,可以用 exec 形式跳過 shell(args 欄位;設定 args 時會忽略 shell)。在 Windows 上,exec 形式要求 command 必須解析為真正的可執行檔,例如 .exe;.cmd 和 .bat 包裝檔(包括 npm 安裝的大多數東西)沒有 shell 就無法啟動。請指向 .exe,或使用 shell 形式。

我們在打造自己的 hook 輔助程式時學到一課:在 Windows 上,shell 啟動為 GUI 子系統建置的程式時不會等待它。shell 立即返回,代理程式讀到空白輸出,hook 看起來就像失效了。hook 程式必須是主控台程式。

外掛 hook 與路徑

建構 ${CLAUDE_PLUGIN_ROOT}/hooks/run.sh 這類路徑的外掛 hook,在 v2.1.2 到 v2.1.12 之間於 Windows 上失效(#18610):變數展開為反斜線路徑,再加上正斜線後綴,就成了 bash 無法解析的混合路徑。目前的文件提供了乾淨的解法:只要 hook 參照路徑預留位置,就使用 exec 形式。把程式放在 command,每個引數放在 args,例如 "command": "node", "args": ["${CLAUDE_PLUGIN_ROOT}/scripts/format.js"]。每個元素都會作為單一引數傳遞,沒有 shell 會把它弄亂。

除錯檢查清單

  1. /hooks 會開啟唯讀清單,列出每個已設定的 hook 及其來源。
  2. claude --debug(或在工作階段中使用 /debug)會顯示每次 hook 執行、其輸出和結束代碼。claude --debug-file <path> 會把這些內容寫入檔案。
  3. 驗證 JSON。 設定檔是嚴格的 JSON;一個結尾逗號就會讓整個檔案失效。
  4. 檢查 matcher。 matcher 區分大小寫;"*"、"" 或不設 matcher 都會符合所有項目。
  5. 自己執行指令,使用 Claude Code 會用的同一個 shell,並以管道送入範例 JSON。
  6. 檢查逾時。 指令 hook 預設為 600 秒;需要等人回應的 hook 需要這樣的餘裕。

調查期間若要關閉所有 hook,請設定 "disableAllHooks": true。

如果你只是想要通知和核准

許多 Windows hook 設定只為了一個目的:知道 Claude Code 何時需要你,並回應它。Pet Island 不需要任何指令碼就能做到。它一鍵連接 Claude Code,替你處理 Windows 的細節,並把每個權限請求、提問和計畫,連同指令或差異內容放到螢幕頂端的一座小島上,讓你在那裡允許或拒絕。Claude Code 在 WSL 中執行時也能使用。

常見問題

在 Windows 上由哪個 shell 執行 Claude Code hook?

Git Bash;若未安裝 Git Bash 則是 PowerShell。在 hook 中設定 "shell": "powershell" 或 "shell": "bash" 即可明確選擇。

為什麼我的 Claude Code hook 在終端機中可以運作,在 Claude Code 中卻不行?

通常是多餘的輸出:會 echo 文字的 shell 設定檔被加到 hook 的 JSON 前面。stdout 只印出 JSON 物件即可。

如何讓 hook 封鎖工具呼叫?

以代碼 2 結束(或在 JSON 中回傳 deny 決定)。結束代碼 1 是非封鎖性錯誤,動作會繼續執行。PermissionRequest hook 會忽略結束代碼 2,改用 decision 物件。

hook 指令可以是 .cmd 或 .bat 檔案嗎?

exec 形式不行。在 Windows 上它必須解析為真正的可執行檔,例如 .exe。要執行 .cmd 或 .bat 檔案,請使用 shell 形式。

如何查看 hook 失敗的原因?

執行 claude --debug 或輸入 /debug,並用 /hooks 查看載入了哪些 hook。

資料來源

本頁所有設定與行為均已於 2026年10月26日 對照下列頁面確認。代理程式更新很快;若內容不再相符,請以官方頁面為準。

延伸閱讀

從螢幕頂端回應每一個代理程式。

Windows 與 Mac · 免費試用 7 天,之後一次付清 $8.99 · 每筆銷售提撥 $1 餵養街頭動物

免費試用 Pet Island