827 827
828您的 hook 的退出碼會告訴 Claude Code 是否繼續執行觸發該 hook 的操作,例如工具呼叫或提示詞。完成的執行有以下三種結果之一:828您的 hook 的退出碼會告訴 Claude Code 是否繼續執行觸發該 hook 的操作,例如工具呼叫或提示詞。完成的執行有以下三種結果之一:
829 829
830* **成功**:您的 hook 以 0 退出。Claude Code 套用您的 hook 列印的任何 [JSON 輸出](#json-output) 欄位,除非這些欄位阻止或拒絕該操作,否則操作會繼續進行。830* **成功**:您的 hook 以 0 退出。Claude Code 套用您的 hook 列印的任何 [JSON 輸出](#json-output) 欄位,除非這些欄位阻止或拒絕該操作,否則操作會繼續進行。[啟動背景程序的 hook](#hooks-that-start-a-background-process) 說明了例外情況。
831* **阻止性錯誤**:您的 hook 以 2 退出。在 [可以阻止的事件](#exit-code-2-behavior-per-event) 上,Claude Code 會停止該操作。831* **阻止性錯誤**:您的 hook 以 2 退出。在 [可以阻止的事件](#exit-code-2-behavior-per-event) 上,Claude Code 會停止該操作。
832* **非阻止性錯誤**:您的 hook 以任何其他代碼退出,或以其他方式失敗,例如無法啟動或列印無效的 JSON。操作會繼續進行,且在 `PreToolUse` 等事件上,您會在逐字稿中看到 `<hook name> hook error` 通知。如果您希望失敗的 hook 阻止操作,請設定 [`onFailure: "block"`](#block-the-action-when-a-hook-fails)。832* **非阻止性錯誤**:您的 hook 以任何其他代碼退出,或以其他方式失敗,例如無法啟動或列印無效的 JSON。操作會繼續進行,且在 `PreToolUse` 等事件上,您會在逐字稿中看到 `<hook name> hook error` 通知。如果您希望失敗的 hook 阻止操作,請設定 [`onFailure: "block"`](#block-the-action-when-a-hook-fails)。
833 833
932* 逾時的 `command`、`http` 或 `mcp_tool` hook 不阻止工具呼叫。呼叫透過正常 [權限流程](/docs/zh-TW/permissions) 繼續,因此不要指望停滯的 hook 充當閘門。要在 `command` 或 `http` hook 逾時時阻止呼叫,請設定 [`onFailure: "block"`](#block-the-action-when-a-hook-fails)。932* 逾時的 `command`、`http` 或 `mcp_tool` hook 不阻止工具呼叫。呼叫透過正常 [權限流程](/docs/zh-TW/permissions) 繼續,因此不要指望停滯的 hook 充當閘門。要在 `command` 或 `http` hook 逾時時阻止呼叫,請設定 [`onFailure: "block"`](#block-the-action-when-a-hook-fails)。
933* 超過其逾時的 [Agent SDK 回呼 hook](/docs/zh-TW/agent-sdk/hooks) [阻止工具呼叫](#pretooluse)。933* 超過其逾時的 [Agent SDK 回呼 hook](/docs/zh-TW/agent-sdk/hooks) [阻止工具呼叫](#pretooluse)。
934 934
935<h4 id="hooks-that-start-a-background-process">
936 啟動背景程序的 hook
937</h4>
938
939如果您的命令 hook 在背景程序中做出決定後就退出,該程序在 Claude Code 停止讀取之後才列印的拒絕不會阻止工具呼叫。對於非 [async](#run-hooks-in-the-background) 的 hook,Claude Code 會在 hook 本身的程序退出後不久完成讀取 hook 的輸出。
940
941請在啟動背景程序之前列印決定,並重新導向該程序的 stdout 和 stderr。如果您的指令碼列印允許決定,然後啟動背景程序而未重新導向該程序的 stdout 和 stderr,Claude Code 會阻止工具呼叫。hook 錯誤包含 `refusing to honor the suspect capture`。
942
943此 `PreToolUse` hook 指令碼使用 `policy-check.sh` 列印決定,然後在背景上傳指標:
944
945```bash theme={null}
946#!/bin/bash
947"$CLAUDE_PROJECT_DIR"/.claude/hooks/policy-check.sh || exit $?
948"$CLAUDE_PROJECT_DIR"/.claude/hooks/upload-metrics.sh >/dev/null 2>&1 &
949```
950
951指令碼的其餘部分執行以下操作:
952
953* **`|| exit $?`**:讓檢查的退出碼成為 hook 本身的退出碼,因此以 2 退出以拒絕的檢查仍會阻止。否則 hook 會以最後一行的代碼退出,也就是 0。
954* **`>/dev/null 2>&1 &`**:在背景執行 `upload-metrics.sh` 並重新導向其輸出,使其不會讓 hook 的輸出保持開啟。
955
956要測試此指令碼,請讓 `policy-check.sh` 以 2 退出,然後觸發該 hook 所匹配的工具呼叫。工具呼叫會被阻止。
957
935<h4 id="block-the-action-when-a-hook-fails">958<h4 id="block-the-action-when-a-hook-fails">
936 在 hook 失敗時阻止操作959 在 hook 失敗時阻止操作
937</h4>960</h4>
1245 Hook 事件1268 Hook 事件
1246</h2>1269</h2>
1247 1270
1248每個事件都對應到 Claude Code 生命週期中可以執行 hook 的一個時間點。以下各節依照生命週期的順序排列:從工作階段設定、經過代理式迴圈,到工作階段結束。每一節都說明事件何時觸發、支援哪些 matcher、接收的 JSON 輸入,以及如何透過輸出來控制行為。1271每個事件都對應 Claude Code 生命週期中可執行 hook 的一個時間點。以下各節依照生命週期的順序排列:從工作階段設定、經過代理式迴圈,到工作階段結束。每一節說明事件何時觸發、支援哪些 matcher、接收的 JSON 輸入,以及如何透過輸出控制行為。
1249 1272
1250<h3 id="sessionstart">1273<h3 id="sessionstart">
1251 SessionStart1274 SessionStart
1252</h3>1275</h3>
1253 1276
1254在 Claude Code 啟動新工作階段或恢復既有工作階段時執行。適合用來載入開發上下文,例如既有的 issue 或程式碼庫的近期變更,或是設定環境變數。若是不需要指令碼的靜態上下文,請改用 [CLAUDE.md](/docs/zh-TW/memory)。1277在 Claude Code 開始新工作階段或恢復現有工作階段時執行。適合用來載入開發情境,例如現有的 issue 或程式碼庫的近期變更,或是設定環境變數。若是不需要指令碼的靜態情境,請改用 [CLAUDE.md](/docs/zh-TW/memory)。
1255 1278
1256SessionStart 會在每個工作階段執行,因此請讓這些 hook 保持快速。僅支援 `type: "command"` 和 `type: "mcp_tool"` hook。關於 `mcp_tool` hook 何時執行,請參閱 [MCP 工具 hook 欄位](#mcp-tool-hook-fields)。1279SessionStart 會在每個工作階段執行,因此請讓這些 hook 保持快速。僅支援 `type: "command"` 和 `type: "mcp_tool"` hook。關於 `mcp_tool` hook 何時執行,請參閱 [MCP tool hook 欄位](#mcp-tool-hook-fields)。
1257 1280
1258matcher 值對應工作階段的啟動方式:1281matcher 值對應工作階段的啟動方式:
1259 1282
1263| `resume` | `--resume`、`--continue` 或 `/resume` |1286| `resume` | `--resume`、`--continue` 或 `/resume` |
1264| `clear` | `/clear` |1287| `clear` | `/clear` |
1265| `compact` | 自動或手動壓縮 |1288| `compact` | 自動或手動壓縮 |
1266| `fork` | 從既有工作階段分岔出的新工作階段:搭配 `--resume` 或 `--continue` 的 `--fork-session`、`/fork` 背景副本、`/branch`,或是您[移至背景](/docs/zh-TW/agent-view#from-inside-a-session)的對話 |1289| `fork` | 從現有工作階段分岔出的新工作階段:搭配 `--resume` 或 `--continue` 的 `--fork-session`、`/fork` 背景副本、`/branch`,或您[移至背景](/docs/zh-TW/agent-view#from-inside-a-session)的對話 |
1267 1290
1268在 v2.1.214 之前,分岔的工作階段回報的 source 為 `"resume"`。1291在 v2.1.214 之前,分岔出的工作階段回報的 source 為 `"resume"`。
1269 1292
1270當您啟動互動式工作階段、在啟動時使用 `--continue` 或 `--resume` 恢復對話,或執行 `/clear` 時,SessionStart hook 會在背景執行。您可以立即輸入,而您恢復的對話也會直接出現,無須等待 hook。Claude 的第一個回應仍會等待 hook 完成,讓其上下文能傳達給 Claude。1293當您啟動互動式工作階段、在啟動時以 `--continue` 或 `--resume` 恢復對話,或執行 `/clear` 時,SessionStart hook 會在背景執行。您可以立即開始輸入,恢復的對話也會直接顯示,無需等待 hook。Claude 的第一個回應仍會等待 hook 完成,以便其情境能傳達給 Claude。
1271 1294
1272當您在工作階段內使用 `/resume` 切換對話時,切換動作則會等待 hook 完成。如果您在背景 hook 仍在執行時執行 `/clear` 或切換到另一個對話,它們傳回的任何內容都不會套用到該工作階段。1295當您在工作階段內以 `/resume` 切換對話時,切換會改為等待 hook 完成。若您在背景 hook 仍在執行時執行 `/clear` 或切換到另一個對話,它們回傳的任何內容都不會套用到工作階段。
1273 1296
1274啟動時(包括恢復的工作階段)也適用同樣的等待:在 SessionStart hook 仍在執行時送出的提示詞,會等到它們完成後才傳達給 Claude。1297啟動時也有相同的等待,包括恢復的工作階段:在 SessionStart hook 仍在執行時送出的提示詞,要等到 hook 完成後才會傳達給 Claude。
1275 1298
1276在上述任一等待期間,按下 `Esc` 可將提示詞取回輸入框而不送出。hook 會繼續執行。1299在任一種等待期間,按下 `Esc` 可將提示詞取回輸入框而不送出。hook 會繼續執行。
1277 1300
1278<h4 id="sessionstart-input">1301<h4 id="sessionstart-input">
1279 SessionStart 輸入1302 SessionStart 輸入
1283 1306
1284| 欄位 | 說明 |1307| 欄位 | 說明 |
1285| :- | :- |1308| :- | :- |
1286| `source` | 工作階段的啟動方式:新工作階段為 `"startup"`、恢復的工作階段為 `"resume"`、`/clear` 之後為 `"clear"`、壓縮之後為 `"compact"`,或從既有工作階段分岔出的新工作階段為 `"fork"` |1309| `source` | 工作階段的啟動方式:新工作階段為 `"startup"`、恢復的工作階段為 `"resume"`、`/clear` 之後為 `"clear"`、壓縮之後為 `"compact"`,從現有工作階段分岔出的新工作階段則為 `"fork"` |
1287| `model` | 目前使用中的模型識別碼。此欄位可能被省略,例如在 `/clear` 之後,或工作階段透過對話復原而還原時,因此讀取前請先檢查欄位是否存在 |1310| `model` | 目前使用的模型識別碼。此欄位可能被省略,例如在 `/clear` 之後,或工作階段透過對話復原還原時,因此讀取前請先檢查欄位是否存在 |
1288| `agent_type` | agent 名稱,在您以 `claude --agent <name>` 啟動 Claude Code 時出現 |1311| `agent_type` | agent 名稱,當您以 `claude --agent <name>` 啟動 Claude Code 時才會出現 |
1289| `session_title` | 工作階段的自訂標題,在已設定時出現,例如透過 `--name`、`/rename`、hook 的 `sessionTitle` 輸出,或 Agent SDK 的 `renameSession()` 設定。會輸出 `sessionTitle` 的 hook 可以先檢查此欄位,以避免覆寫既有的自訂標題 |1312| `session_title` | 工作階段的自訂標題,在已設定時出現,例如透過 `--name`、`/rename`、hook 的 `sessionTitle` 輸出,或 Agent SDK 的 `renameSession()`。輸出 `sessionTitle` 的 hook 可以先檢查此欄位,以避免覆寫既有的自訂標題 |
1290 1313
1291您尚未命名的工作階段仍可能有[自動產生的標題](/docs/zh-TW/sessions#name-your-sessions)。該標題不是自訂標題,也不會出現在 `session_title` 中。1314您尚未命名的工作階段仍可能有[自動產生的標題](/docs/zh-TW/sessions#name-your-sessions)。該標題不是自訂標題,也不會出現在 `session_title` 中。
1292 1315
1293當 `source` 為 `"resume"` 或 `"fork"`,且逐字稿中至少包含一則 Claude 的回應時,SessionStart hook 也會接收下列四個欄位。您的 hook 可以使用它們,在第一個請求之前回報恢復一個過時對話的成本,例如透過 [`systemMessage`](#json-output)。這些欄位需要 Claude Code v2.1.251 或更新版本。1316當 `source` 為 `"resume"` 或 `"fork"`,且逐字稿中至少包含一則 Claude 的回應時,SessionStart hook 還會接收下列四個欄位。您的 hook 可以用它們在第一個請求之前回報恢復一段閒置已久的對話所需的成本,例如透過 [`systemMessage`](#json-output)。這些欄位需要 Claude Code v2.1.251 或更新版本。
1294 1317
1295| 欄位 | 說明 |1318| 欄位 | 說明 |
1296| :- | :- |1319| :- | :- |
1297| `seconds_since_last_response` | 自恢復之逐字稿中最後一則回應以來經過的實際秒數 |1320| `seconds_since_last_response` | 自恢復的逐字稿中最後一則回應以來經過的實際秒數 |
1298| `context_tokens` | 恢復之工作階段的第一個請求重新傳送作為提示詞的 token 數 |1321| `context_tokens` | 恢復的工作階段的第一個請求作為提示詞重新傳送的 token 數 |
1299| `prompt_cache_likely_expired` | 當最後一則回應早於工作階段的[提示快取存留時間](/docs/zh-TW/prompt-caching#cache-lifetime),或之後的壓縮取代了已快取的對話時為 `true` |1322| `prompt_cache_likely_expired` | 當最後一則回應早於工作階段的[提示快取存留期](/docs/zh-TW/prompt-caching#cache-lifetime),或之後的壓縮取代了已快取的對話時為 `true` |
1300| `estimated_cache_write_usd` | 在工作階段的模型上將 `context_tokens` 寫入提示快取的預估成本(美元),不含回應 |1323| `estimated_cache_write_usd` | 以工作階段的模型將 `context_tokens` 寫入提示快取的估計成本(美元),不含回應 |
1301 1324
1302此範例顯示在最後一則回應 90 分鐘後恢復的工作階段的輸入:1325此範例顯示一個在最後一則回應 90 分鐘後恢復的工作階段的輸入:
1303 1326
1304```json theme={null}1327```json theme={null}
1305{1328{
1320 SessionStart 決策控制1343 SessionStart 決策控制
1321</h4>1344</h4>
1322 1345
1323SessionStart hook 可以為 Claude 新增上下文、提供第一則使用者訊息、設定工作階段標題、監看檔案,以及重新載入 skill。除了所有 hook 皆可使用的 [JSON 輸出欄位](#json-output)之外,請針對每項功能傳回對應的欄位:1346SessionStart hook 可以為 Claude 新增情境、提供第一則使用者訊息、設定工作階段標題、監看檔案,以及重新載入 skill。除了所有 hook 都可使用的 [JSON 輸出欄位](#json-output)之外,請為每一項回傳對應的欄位:
1324 1347
1325| 欄位 | 說明 |1348| 欄位 | 說明 |
1326| :- | :- |1349| :- | :- |
1327| `additionalContext` | 在對話開始時、第一個提示詞之前加入 Claude 上下文的字串。關於文字如何傳遞以及應放入什麼內容,請參閱[為 Claude 加入上下文](#add-context-for-claude) |1350| `additionalContext` | 在對話開始時、第一個提示詞之前加入 Claude 情境的字串。關於文字如何傳遞以及應放入什麼內容,請參閱[為 Claude 新增情境](#add-context-for-claude) |
1328| `initialUserMessage` | 在使用 `-p` 旗標的[非互動模式](/docs/zh-TW/headless)中,作為工作階段第一則使用者訊息的字串。即使您未傳入提示詞,它也會成為第一個回合。您傳入的提示詞則會作為下一個回合 |1351| `initialUserMessage` | 在使用 `-p` 旗標的[非互動模式](/docs/zh-TW/headless)中,作為工作階段第一則使用者訊息的字串。即使您未傳入提示詞,它也會成為第一個回合。您傳入的提示詞會作為下一個回合 |
1329| `sessionTitle` | 設定工作階段標題,效果與 `/rename` 相同。當 `source` 為 `"startup"`、`"resume"` 或 `"fork"` 時適用 |1352| `sessionTitle` | 設定工作階段標題,效果與 `/rename` 相同。在 `source` 為 `"startup"`、`"resume"` 或 `"fork"` 時套用 |
1330| `watchPaths` | 在此工作階段期間要監看 [FileChanged](#filechanged) 事件的絕對路徑陣列 |1353| `watchPaths` | 在此工作階段期間要監看 [FileChanged](#filechanged) 事件的絕對路徑陣列 |
1331| `reloadSkills` | 布林值。為 `true` 時,Claude Code 會在 SessionStart hook 完成後重新掃描 [skill](/docs/zh-TW/skills) 和命令目錄。請參閱[重新載入 hook 安裝的 skill](#reload-skills-that-a-hook-installs) |1354| `reloadSkills` | 布林值。為 `true` 時,Claude Code 會在 SessionStart hook 完成後重新掃描 [skill](/docs/zh-TW/skills) 和命令目錄。請參閱[重新載入 hook 安裝的 skill](#reload-skills-that-a-hook-installs) |
1332 1355
1333此輸出會新增上下文並為工作階段命名:1356此輸出會新增情境並為工作階段命名:
1334 1357
1335```json theme={null}1358```json theme={null}
1336{1359{
1342}1365}
1343```1366```
1344 1367
1345只新增上下文的 hook 可以直接輸出內容而不必建構 JSON,因為 Claude Code 會將 SessionStart hook 的[純文字 stdout](#exit-code-0) 加入 Claude 的上下文。1368只新增情境的 hook 可以直接印出內容而不必建構 JSON,因為 Claude Code 會將 SessionStart hook 的[純文字 stdout](#exit-code-0) 加入 Claude 的情境。
1346 1369
1347如果您外掛的 SessionStart hook 提供 `initialUserMessage` 或 `sessionTitle`,請在工作階段開始前安裝該外掛。對於在 SessionStart hook 執行後才完成安裝的外掛,Claude Code 會忽略這兩個欄位。1370若您外掛的 SessionStart hook 提供 `initialUserMessage` 或 `sessionTitle`,請在工作階段開始前安裝該外掛。對於在 SessionStart hook 執行完畢後才完成安裝的外掛,Claude Code 會忽略這兩個欄位。
1348 1371
1349<h4 id="reload-skills-that-a-hook-installs">1372<h4 id="reload-skills-that-a-hook-installs">
1350 重新載入 hook 安裝的 skill1373 重新載入 hook 安裝的 skill
1351</h4>1374</h4>
1352 1375
1353若要讓 SessionStart hook 安裝的 skill 在同一個工作階段中可用,請傳回 `reloadSkills`。skill 探索通常會在 SessionStart hook 完成之前執行,因此若沒有此欄位,hook 寫入 `~/.claude/skills/` 或 `.claude/skills/` 的檔案可能在第一個提示詞執行時尚不存在。1376若要讓 SessionStart hook 安裝的 skill 在同一個工作階段中可用,請回傳 `reloadSkills`。skill 探索通常在 SessionStart hook 完成之前就會執行,因此若沒有此欄位,hook 寫入 `~/.claude/skills/` 或 `.claude/skills/` 的檔案可能在第一個提示詞執行時尚未被載入。
1354 1377
1355此範例會同步共用的 skill 儲存庫並請求重新掃描:1378此範例會同步共用的 skill 儲存庫並要求重新掃描:
1356 1379
1357```bash theme={null}1380```bash theme={null}
1358#!/bin/bash1381#!/bin/bash
1363echo '{"hookSpecificOutput": {"hookEventName": "SessionStart", "reloadSkills": true}}'1386echo '{"hookSpecificOutput": {"hookEventName": "SessionStart", "reloadSkills": true}}'
1364```1387```
1365 1388
1366儲存庫 URL 僅為預留位置。請替換為您自己的 skill 儲存庫。1389儲存庫 URL 僅為預留位置。請將其替換為您自己的 skill 儲存庫。
1367 1390
1368<h4 id="persist-environment-variables">1391<h4 id="persist-environment-variables">
1369 保存環境變數1392 保存環境變數
1370</h4>1393</h4>
1371 1394
1372SessionStart hook 可以存取 `CLAUDE_ENV_FILE` 環境變數,它提供一個檔案路徑,讓您為 Claude 在工作階段稍後執行的 shell 命令保存環境變數。1395SessionStart hook 可以存取 `CLAUDE_ENV_FILE` 環境變數,它提供一個檔案路徑,讓您可以為 Claude 在工作階段稍後執行的 shell 命令保存環境變數。
1373 1396
1374若要設定個別環境變數,請將 `export` 陳述式寫入 `CLAUDE_ENV_FILE`。請使用附加(`>>`)以保留其他 hook 設定的變數:1397若要設定個別的環境變數,請將 `export` 陳述式寫入 `CLAUDE_ENV_FILE`。請使用附加(`>>`)以保留其他 hook 設定的變數:
1375 1398
1376```bash theme={null}1399```bash theme={null}
1377#!/bin/bash1400#!/bin/bash
1385exit 01408exit 0
1386```1409```
1387 1410
1388若要擷取設定命令造成的所有環境變更,請比較前後匯出的變數:1411若要擷取設定命令所造成的所有環境變更,請比較前後匯出的變數:
1389 1412
1390```bash theme={null}1413```bash theme={null}
1391#!/bin/bash1414#!/bin/bash
1404exit 01427exit 0
1405```1428```
1406 1429
1407每個 Bash 命令都會在命令本身之前,將該檔案的內容作為 shell 程式碼執行,因此其中的一行可以使用 Bash 會求值的任何內容,例如 `export PATH="$PATH:./node_modules/.bin"` 中的 `$PATH` 參照。1430每個 Bash 命令都會在命令本身之前將該檔案的內容作為 shell 程式碼執行,因此其中的一行可以使用 Bash 能求值的任何內容,例如 `export PATH="$PATH:./node_modules/.bin"` 中的 `$PATH` 參照。
1408 1431
1409<a id="persisted-variables-in-powershell-commands" />1432<a id="persisted-variables-in-powershell-commands" />
1410 1433
1411<h5 id="persisted-variables-in-powershell-commands">1434<h5 id="persisted-variables-in-powershell-commands">
1412 PowerShell 命令中的保存變數1435 PowerShell 命令中保存的變數
1413</h5>1436</h5>
1414 1437
1415在 Claude Code v2.1.296 或更新版本中,[PowerShell](/docs/zh-TW/tools-reference#powershell-tool) 命令也會接收來自 `CLAUDE_ENV_FILE` 的變數,但 PowerShell 從不執行該檔案。Claude Code 會改為從中讀出指派內容,並將它們複製到 PowerShell 命令的環境中。只有在每一行都屬於以下其中一種時才會這麼做,範圍涵蓋此工作階段中每個 hook 寫入的內容,以及您在啟動前[將 `CLAUDE_ENV_FILE` 設為](/docs/zh-TW/env-vars)的任何腳本:1438在 Claude Code v2.1.296 或更新版本中,[PowerShell](/docs/zh-TW/tools-reference#powershell-tool) 命令也會接收 `CLAUDE_ENV_FILE` 中的變數,但 PowerShell 從不執行該檔案。Claude Code 會從中讀出賦值,並改為複製到 PowerShell 命令的環境中。只有當本工作階段中每個 hook 所寫入的內容,以及您在啟動前[將 `CLAUDE_ENV_FILE` 設為](/docs/zh-TW/env-vars)的任何指令碼中,每一行都屬於下列其中一種時,才會這麼做:
1416 1439
1417* 空白行或 `#` 註解1440* 空白行或 `#` 註解
1418* 位於行首的單一指派,寫成 `export NAME=value`、`declare -x NAME=value` 或 `NAME=value`,且其值會被 Bash 完全依原樣使用,由以下部分任意組合而成:只使用字母、數字與 `_ @ % + = : , . / -` 字元的未加引號文字、單引號內的文字,以及其中任何 `$`、反引號或 `"` 皆以反斜線跳脫的雙引號內文字1441* 位於行首的單一賦值,寫法為 `export NAME=value`、`declare -x NAME=value` 或 `NAME=value`,且其值是 Bash 會按原樣使用的值,可由下列部分任意組合而成:僅使用字母、數字及字元 `_ @ % + = : , . / -` 的未加引號文字、單引號內的文字,以及其中任何 `$`、反引號或 `"` 都已用反斜線跳脫的雙引號內文字
1419 1442
1420如果有任何一行屬於其他類型,例如帶有未跳脫 `$PATH` 的 `export PATH="$PATH:./node_modules/.bin"`、`source` 命令,或 `direnv export bash` 印出的 `$'...'` 字串,PowerShell 命令將不會接收任何變數,且 `claude --debug` 會記錄 `Session environment is not all plain assignments`。Bash 命令仍會接收全部變數。在 Windows 上,PowerShell 命令也不會接收值中包含 `/` 或 `\` 的變數,因為 Git Bash 與 Windows 撰寫路徑的方式不同。[沙箱化](/docs/zh-TW/sandboxing)的 PowerShell 命令不會接收任何變數。1443若有任何一行屬於其他類型,例如帶有未跳脫 `$PATH` 的 `export PATH="$PATH:./node_modules/.bin"`、`source` 命令,或 `direnv export bash` 輸出的 `$'...'` 字串,PowerShell 命令將不會接收任何變數,且 `claude --debug` 會記錄 `Session environment is not all plain assignments`。Bash 命令仍會接收所有變數。在 Windows 上,PowerShell 命令也不會接收值中包含 `/` 或 `\` 的變數,因為 Git Bash 和 Windows 的路徑寫法不同。[沙箱化](/docs/zh-TW/sandboxing)的 PowerShell 命令不會接收任何變數。
1421 1444
1422<Note>1445<Note>
1423 `CLAUDE_ENV_FILE` 可用於 SessionStart、[Setup](#setup)、[CwdChanged](#cwdchanged) 與 [FileChanged](#filechanged) hook。其他 hook 事件無法存取此變數,在 PowerShell 中執行的 hook 也無法存取,無論是透過 [`"shell": "powershell"`](#command-hook-fields),或是在沒有 Git Bash 的 Windows 上預設如此。1446 `CLAUDE_ENV_FILE` 可供 SessionStart、[Setup](#setup)、[CwdChanged](#cwdchanged) 和 [FileChanged](#filechanged) hook 使用。其他 hook 事件無法存取此變數,在 PowerShell 中執行的 hook 也無法存取,無論是透過 [`"shell": "powershell"`](#command-hook-fields),還是在沒有 Git Bash 的 Windows 上預設執行。
1424</Note>1447</Note>
1425 1448
1426<h3 id="setup">1449<h3 id="setup">
1427 Setup1450 Setup
1428</h3>1451</h3>
1429 1452
1430僅在您以 `--init-only` 啟動 Claude Code,或在使用 `-p` 旗標的[非互動模式](/docs/zh-TW/headless)中搭配 `--init` 或 `--maintenance` 啟動時觸發。一般啟動時不會觸發。可用於您從 CI 或指令碼明確觸發的一次性相依套件安裝或排程清理,與一般工作階段啟動分開。若是每個工作階段的初始化,請改用 [SessionStart](#sessionstart)。1453僅在您以 `--init-only` 啟動 Claude Code,或在使用 `-p` 旗標的[非互動模式](/docs/zh-TW/headless)中搭配 `--init` 或 `--maintenance` 啟動時觸發。一般啟動時不會觸發。適合用於您從 CI 或指令碼明確觸發的一次性相依套件安裝或排程清理,與一般的工作階段啟動分開。若要進行每個工作階段的初始化,請改用 [SessionStart](#sessionstart)。
1431 1454
1432matcher 值對應觸發 hook 的 CLI 旗標:1455matcher 值對應觸發 hook 的 CLI 旗標:
1433 1456
1436| `init` | `claude --init-only` 或 `claude -p --init` |1459| `init` | `claude --init-only` 或 `claude -p --init` |
1437| `maintenance` | `claude -p --maintenance` |1460| `maintenance` | `claude -p --maintenance` |
1438 1461
1439當您執行 `claude --init-only` 時,Claude Code 會執行 Setup hook 以及具有 `startup` matcher 的 `SessionStart` hook,然後在不啟動對話的情況下結束。1462當您執行 `claude --init-only` 時,Claude Code 會執行 Setup hook 以及帶有 `startup` matcher 的 `SessionStart` hook,然後在不開始對話的情況下結束。
1440 1463
1441當您使用 `-p` 啟動或繼續對話時,也需要提供提示詞,可以作為引數或透過 stdin 管道傳入。當 `SessionStart` hook 提供了 [`initialUserMessage`](#sessionstart-decision-control),或您恢復的是具有[延後之工具呼叫](#defer-a-tool-call-for-later)的工作階段時,可以省略提示詞。1464當您以 `-p` 開始或繼續對話時,也需要提供提示詞,可作為引數或透過 stdin 管道傳入。當 `SessionStart` hook 提供 [`initialUserMessage`](#sessionstart-decision-control),或您恢復含有[延遲工具呼叫](#defer-a-tool-call-for-later)的工作階段時,可以省略提示詞。
1442 1465
1443成功時,`--init-only` 不會在終端機輸出任何內容。若要確認 hook 已執行,請以 `claude --debug-file <path> --init-only` 啟動,將 `<path>` 替換為日誌檔案位置,並在日誌中檢查 Setup 和 SessionStart hook 的項目。1466成功時,`--init-only` 不會在終端機印出任何內容。若要確認 hook 已執行,請以 `claude --debug-file <path> --init-only` 啟動,將 `<path>` 替換為日誌檔案位置,然後檢查日誌中的 Setup 和 SessionStart hook 項目。
1444 1467
1445由於 Setup 不會在每次啟動時觸發,需要安裝相依套件的外掛不能只依賴 Setup。實務上的做法是在首次使用時檢查相依套件,缺少時再安裝,例如以 hook 或 skill 檢測 `${CLAUDE_PLUGIN_DATA}/node_modules`,若不存在則執行 `npm install`。關於已安裝之相依套件的存放位置,請參閱[持久資料目錄](/docs/zh-TW/plugins/components#path-variables-and-persistent-data)。如果您透過市集發布外掛,可能不需要這種做法:Claude Code 在快取外掛時會[自動安裝符合條件的 Node.js 套件相依性](/docs/zh-TW/plugins/loading#node-js-package-dependencies)。1468由於 Setup 不會在每次啟動時觸發,需要安裝相依套件的外掛不能只依賴 Setup。實務上的做法是在首次使用時檢查相依套件,缺少時再安裝,例如使用一個 hook 或 skill 檢查 `${CLAUDE_PLUGIN_DATA}/node_modules`,若不存在則執行 `npm install`。關於已安裝相依套件的存放位置,請參閱[持久資料目錄](/docs/zh-TW/plugins/components#path-variables-and-persistent-data)。若您透過市集發布外掛,可能不需要此做法:Claude Code 在快取外掛時會[自動安裝符合條件的 Node.js 套件相依套件](/docs/zh-TW/plugins/loading#node-js-package-dependencies)。
1446 1469
1447<h4 id="setup-input">1470<h4 id="setup-input">
1448 Setup 輸入1471 Setup 輸入
1464 Setup 決策控制1487 Setup 決策控制
1465</h4>1488</h4>
1466 1489
1467Setup hook 無法阻擋;無論退出碼為何,執行都會繼續。在任何退出碼下,Claude Code 都會捨棄 Setup hook 的 [JSON 輸出欄位](#json-output),例如 `systemMessage`、`continue` 和 `hookSpecificOutput.additionalContext`。使用 `-p` 時,只有在您以 `--output-format stream-json --verbose` 啟動的情況下,Setup hook 的 stdout、stderr 和退出碼才會以 [`hook_response` 事件](/docs/zh-TW/headless#read-session-metadata)的形式出現在執行的輸出中。1490Setup hook 無法阻擋;無論退出碼為何,執行都會繼續。無論退出碼為何,Claude Code 都會捨棄 Setup hook 的 [JSON 輸出欄位](#json-output),例如 `systemMessage`、`continue` 和 `hookSpecificOutput.additionalContext`。使用 `-p` 時,只有在您以 `--output-format stream-json --verbose` 啟動的情況下,Setup hook 的 stdout、stderr 和退出碼才會以 [`hook_response` 事件](/docs/zh-TW/headless#read-session-metadata)的形式出現在執行輸出中。
1468 1491
1469Setup hook 可以存取 `CLAUDE_ENV_FILE`。寫入該檔案的變數會保存到工作階段中後續的 Bash 命令,與 [SessionStart hook](#persist-environment-variables) 相同。`Setup` 上只會執行 `type: "command"` hook。`Setup` 上的 `type: "mcp_tool"` hook 一律會被略過,如 [MCP 工具 hook 欄位](#mcp-tool-hook-fields)所述。1492Setup hook 可以存取 `CLAUDE_ENV_FILE`。寫入該檔案的變數會保存到工作階段後續的 Bash 命令中,與 [SessionStart hook](#persist-environment-variables) 相同。`Setup` 上只會執行 `type: "command"` hook。`Setup` 上的 `type: "mcp_tool"` hook 一律會被略過,如 [MCP tool hook 欄位](#mcp-tool-hook-fields)中所述。
1470 1493
1471<h3 id="instructionsloaded">1494<h3 id="instructionsloaded">
1472 InstructionsLoaded1495 InstructionsLoaded
1473</h3>1496</h3>
1474 1497
1475在 `CLAUDE.md` 或 `.claude/rules/*.md` 檔案載入上下文時觸發。此事件會在工作階段開始時針對預先載入的檔案觸發,之後在檔案延遲載入時再次觸發,例如當 Claude 存取包含巢狀 `CLAUDE.md` 的子目錄時,或具有 `paths:` frontmatter 的條件式規則相符時。此 hook 不支援阻擋或決策控制。它以非同步方式執行,用於可觀測性用途。1498當 `CLAUDE.md` 或 `.claude/rules/*.md` 檔案被載入情境時觸發。此事件會在工作階段開始時針對預先載入的檔案觸發,並在稍後檔案延遲載入時再次觸發,例如當 Claude 存取包含巢狀 `CLAUDE.md` 的子目錄,或帶有 `paths:` frontmatter 的條件式規則相符時。此 hook 不支援阻擋或決策控制。它以非同步方式執行,用於可觀察性目的。
1476 1499
1477當 Claude 透過 **Project instructions** 設定[直接讀取 `AGENTS.md`](/docs/zh-TW/memory#agents-md) 時,此事件不會觸發。當 `CLAUDE.md` 匯入您的 `AGENTS.md` 時會觸發,`load_reason` 與其他任何匯入的檔案一樣設為 `include`;當 `CLAUDE.md` 是指向它的符號連結時也會觸發,視為一般的 `CLAUDE.md` 載入。1500當 Claude 透過 **Project instructions** 設定[直接讀取 `AGENTS.md`](/docs/zh-TW/memory#agents-md) 時,此事件不會觸發。當 `CLAUDE.md` 匯入您的 `AGENTS.md` 時會觸發,此時 `load_reason` 與其他任何匯入的檔案一樣設為 `include`;當 `CLAUDE.md` 是指向它的符號連結時也會觸發,視為一般的 `CLAUDE.md` 載入。
1478 1501
1479matcher 會比對 `load_reason`。例如,使用 `"matcher": "session_start"` 可僅針對工作階段開始時載入的檔案觸發,或使用 `"matcher": "path_glob_match|nested_traversal"` 僅針對延遲載入觸發。1502matcher 會比對 `load_reason`。例如,使用 `"matcher": "session_start"` 僅針對工作階段開始時載入的檔案觸發,或使用 `"matcher": "path_glob_match|nested_traversal"` 僅針對延遲載入觸發。
1480 1503
1481<h4 id="instructionsloaded-input">1504<h4 id="instructionsloaded-input">
1482 InstructionsLoaded 輸入1505 InstructionsLoaded 輸入
1486 1509
1487| 欄位 | 說明 |1510| 欄位 | 說明 |
1488| :- | :- |1511| :- | :- |
1489| `file_path` | 已載入之指令檔案的絕對路徑 |1512| `file_path` | 已載入的指令檔案的絕對路徑 |
1490| `memory_type` | 檔案的範圍:`"User"`、`"Project"`、`"Local"` 或 `"Managed"` |1513| `memory_type` | 檔案的範圍:`"User"`、`"Project"`、`"Local"` 或 `"Managed"` |
1491| `load_reason` | 檔案載入的原因:`"session_start"`、`"nested_traversal"`、`"path_glob_match"`、`"include"` 或 `"compact"`。`"compact"` 值會在壓縮事件後重新載入指令檔案時觸發 |1514| `load_reason` | 載入檔案的原因:`"session_start"`、`"nested_traversal"`、`"path_glob_match"`、`"include"` 或 `"compact"`。`"compact"` 值會在壓縮事件後重新載入指令檔案時觸發 |
1492| `globs` | 來自檔案 `paths:` frontmatter 的路徑 glob 模式(若有)。僅在 `path_glob_match` 載入時出現 |1515| `globs` | 檔案 `paths:` frontmatter 中的路徑 glob 模式(若有)。僅在 `path_glob_match` 載入時出現 |
1493| `trigger_file_path` | 延遲載入時,其存取觸發此次載入的檔案路徑 |1516| `trigger_file_path` | 對於延遲載入,觸發此次載入的被存取檔案的路徑 |
1494| `parent_file_path` | `include` 載入時,包含此檔案的上層指令檔案路徑 |1517| `parent_file_path` | 對於 `include` 載入,包含此檔案的上層指令檔案的路徑 |
1495 1518
1496```json theme={null}1519```json theme={null}
1497{1520{
1509 InstructionsLoaded 決策控制1532 InstructionsLoaded 決策控制
1510</h4>1533</h4>
1511 1534
1512InstructionsLoaded hook 沒有決策控制。它們無法阻擋或修改指令載入。Claude Code 會捨棄它們的 [JSON 輸出欄位](#json-output),例如 `systemMessage` 和 `continue`。請將此事件用於稽核日誌、合規追蹤或可觀測性。1535InstructionsLoaded hook 沒有決策控制。它們無法阻擋或修改指令載入。Claude Code 會捨棄它們的 [JSON 輸出欄位](#json-output),例如 `systemMessage` 和 `continue`。請將此事件用於稽核日誌、合規追蹤或可觀察性。
1513 1536
1514<h3 id="userpromptsubmit">1537<h3 id="userpromptsubmit">
1515 UserPromptSubmit1538 UserPromptSubmit
1516</h3>1539</h3>
1517 1540
1518在提交提示詞時、Claude 處理之前執行。這讓您可以1541在提示詞送出時、Claude 處理之前執行。這可讓您
1519根據提示詞/對話加入額外的上下文、驗證提示詞,或1542根據提示詞或對話新增額外情境、驗證提示詞,或
1520阻擋特定類型的提示詞。1543阻擋特定類型的提示詞。
1521 1544
1522`UserPromptSubmit` hook 不只會在您輸入的提示詞上觸發。Claude Code 也會在下列情況執行它們:1545`UserPromptSubmit` hook 不僅會針對您輸入的提示詞觸發。Claude Code 也會在下列情況執行它們:
1523 1546
1524* [排程任務](/docs/zh-TW/scheduled-tasks)觸發時,包括 `/loop` 的每次迭代1547* [排程任務](/docs/zh-TW/scheduled-tasks)觸發時,包括 `/loop` 的每次迭代
1525* [背景 subagent](/docs/zh-TW/sub-agents#run-subagents-in-foreground-or-background) 向啟動它的工作階段回報時1548* [背景 subagent](/docs/zh-TW/sub-agents#run-subagents-in-foreground-or-background) 向啟動它的工作階段回報時
1526* [另一個工作階段傳送訊息](/docs/zh-TW/cross-session-messaging)到您的主要對話時1549* [另一個工作階段傳送訊息](/docs/zh-TW/cross-session-messaging)到您的主要對話時
1527 1550
1528`UserPromptSubmit` hook 對 `command`、`http` 和 `mcp_tool` 類型的預設逾時為 30 秒,短於大多數其他事件上這些類型的 600 秒預設值。由於此 hook 會在每個提示詞之前執行,並在完成前阻擋模型處理,卡住的 hook 會使工作階段停滯。如果您的 hook 需要更多時間,請在 hook 項目中設定 `timeout` 欄位。1551`UserPromptSubmit` hook 對於 `command`、`http` 和 `mcp_tool` 類型的預設逾時為 30 秒,短於這些類型在大多數其他事件上的 600 秒預設值。由於此 hook 在每個提示詞之前執行,並會阻擋模型處理直到完成,卡住的 hook 會使工作階段停滯。若您的 hook 需要更多時間,請在 hook 項目中設定 `timeout` 欄位。
1529 1552
1530除了以 [`async: true`](#run-hooks-in-the-background) 執行的命令 hook 之外,達到逾時的 `UserPromptSubmit` 命令、HTTP 或 MCP 工具 hook 會被取消,其輸出(包括任何 `additionalContext`)會被捨棄。提示詞仍會在沒有該上下文的情況下傳達給 Claude。若要改為阻擋提示詞,請在命令或 HTTP hook 上設定 [`onFailure: "block"`](#block-the-action-when-a-hook-fails)。逐字稿會顯示一則通知,說明是哪個 hook、觸發的逾時,以及輸出已被捨棄。1553除了以 [`async: true`](#run-hooks-in-the-background) 執行的 command hook 之外,達到逾時的 `UserPromptSubmit` command、HTTP 或 MCP tool hook 會被取消,其輸出(包括任何 `additionalContext`)會被捨棄。提示詞仍會在沒有該情境的情況下傳達給 Claude。若要改為阻擋提示詞,請在 command 或 HTTP hook 上設定 [`onFailure: "block"`](#block-the-action-when-a-hook-fails)。逐字稿會顯示一則通知,指出該 hook、觸發的逾時,以及輸出已被捨棄。
1531 1554
1532`UserPromptSubmit` 上達到逾時的 [Agent SDK 回呼 hook](/docs/zh-TW/agent-sdk/hooks) 會阻擋該提示詞,並顯示說明該 hook 和逾時的訊息,因為該處的回呼可能作為不得在失敗時放行的政策關卡。工作階段會繼續。在 v2.1.208 之前,該事件上的回呼逾時會以執行錯誤結束該回合。1555`UserPromptSubmit` 上的 [Agent SDK 回呼 hook](/docs/zh-TW/agent-sdk/hooks) 若達到逾時,會阻擋提示詞並顯示指出該 hook 和逾時的訊息,因為該處的回呼可能扮演不得在失敗時放行的政策閘門。工作階段會繼續。在 v2.1.208 之前,該事件上的回呼逾時會以執行錯誤結束該回合。
1533 1556
1534<h4 id="userpromptsubmit-input">1557<h4 id="userpromptsubmit-input">
1535 UserPromptSubmit 輸入1558 UserPromptSubmit 輸入
1536</h4>1559</h4>
1537 1560
1538除了[通用輸入欄位](#common-input-fields)之外,UserPromptSubmit hook 還會接收包含所提交文字的 `prompt` 欄位。折疊成 `[Pasted text #N]` 預留位置的貼上內容會在原位置展開後傳入。在 Claude Code [為 Claude 標記貼上文字](/docs/zh-TW/terminal-config#how-claude-treats-pasted-text)的工作階段中,展開的內容會位於 `<pasted_content id="…">` 行與 `</pasted_content id="…">` 行之間,因此如果您的 hook 會剖析提示詞,請將這些行納入考量。1561除了[通用輸入欄位](#common-input-fields)之外,UserPromptSubmit hook 還會接收包含所送出文字的 `prompt` 欄位。被收合為 `[Pasted text #N]` 預留位置的貼上內容會在原處展開後送達。在 Claude Code [為 Claude 標記貼上文字](/docs/zh-TW/terminal-config#how-claude-treats-pasted-text)的工作階段中,該展開內容位於 `<pasted_content id="…">` 行和 `</pasted_content id="…">` 行之間,因此若您的 hook 會解析提示詞,請將這些行納入考量。
1539 1562
1540當工作階段有自訂標題時,UserPromptSubmit hook 也會接收 `session_title`,其意義與 [SessionStart 的 `session_title` 欄位](#sessionstart-input)相同。1563當工作階段有自訂標題時,UserPromptSubmit hook 也會接收 `session_title`,其意義與 [SessionStart `session_title` 欄位](#sessionstart-input)相同。
1541 1564
1542```json theme={null}1565```json theme={null}
1543{1566{
1554 UserPromptSubmit 決策控制1577 UserPromptSubmit 決策控制
1555</h4>1578</h4>
1556 1579
1557`UserPromptSubmit` hook 可以控制是否處理已提交的提示詞,並加入上下文。所有 [JSON 輸出欄位](#json-output)皆可使用。1580`UserPromptSubmit` hook 可以控制是否處理所送出的提示詞,並新增情境。所有 [JSON 輸出欄位](#json-output)皆可使用。
1558 1581
1559在退出碼 0 時,有兩種方式可以將上下文加入對話:1582在退出碼為 0 時,有兩種方式可以將情境加入對話:
1560 1583
1561* **純文字 stdout**:Claude Code 會將其[視為純文字](#exit-code-0)的 stdout 加入 Claude 的上下文1584* **純文字 stdout**:Claude Code 會將其[視為純文字](#exit-code-0)的 stdout 加入 Claude 的情境
1562* **含 `additionalContext` 的 JSON**:使用下方的 JSON 格式以獲得更多控制。`additionalContext` 欄位會作為上下文加入1585* **帶有 `additionalContext` 的 JSON**:使用下方的 JSON 格式以獲得更多控制。`additionalContext` 欄位會作為情境加入
1563 1586
1564這兩個管道都不會產生可見的逐字稿項目。純 stdout 和 `additionalContext` 值各自會以開頭為 hook 名稱的系統提醒注入;Claude 兩者都會讀取。若要確認已傳遞,請查看[除錯日誌](#debug-hooks)。1587兩種管道都不會產生可見的逐字稿項目。純 stdout 和 `additionalContext` 值各自以 hook 名稱開頭的系統提醒形式注入;Claude 會讀取兩者。若要確認已傳遞,請查看[除錯日誌](#debug-hooks)。
1565 1588
1566若要阻擋提示詞,請傳回 `decision` 設為 `"block"` 的 JSON 物件:1589若要阻擋提示詞,請回傳 `decision` 設為 `"block"` 的 JSON 物件:
1567 1590
1568| 欄位 | 說明 |1591| 欄位 | 說明 |
1569| :- | :- |1592| :- | :- |
1570| `decision` | `"block"` 會在提示詞傳達給 Claude 之前將其停止。省略則允許提示詞繼續 |1593| `decision` | `"block"` 會在提示詞傳達給 Claude 之前將其停止。省略則允許提示詞繼續 |
1571| `reason` | 當 `decision` 為 `"block"` 時顯示給使用者。不會加入上下文 |1594| `reason` | 當 `decision` 為 `"block"` 時向使用者顯示。不會加入情境 |
1572| `additionalContext` | 與已提交之提示詞一同加入 Claude 上下文的字串。請參閱[為 Claude 加入上下文](#add-context-for-claude) |1595| `additionalContext` | 與所送出的提示詞一同加入 Claude 情境的字串。請參閱[為 Claude 新增情境](#add-context-for-claude) |
1573| `sessionTitle` | 設定工作階段標題。可用來依據提示詞內容自動命名工作階段 |1596| `sessionTitle` | 設定工作階段標題。可用於根據提示詞內容自動為工作階段命名 |
1574| `suppressOriginalPrompt` | 若在 hook 阻擋提示詞時為 `true`,則會將提示詞文字排除在阻擋訊息之外。請參閱[被阻擋的提示詞會留下什麼](#what-a-blocked-prompt-leaves-behind) |1597| `suppressOriginalPrompt` | 若 hook 阻擋提示詞時此值為 `true`,阻擋訊息中將不包含提示詞文字。請參閱[被阻擋的提示詞會留下什麼](#what-a-blocked-prompt-leaves-behind) |
1575 1598
1576以退出碼 2 阻擋的 hook 與 `reason` 的處理方式相同:阻擋訊息會向使用者顯示 stderr 文字,且不會加入上下文。1599以退出碼 2 阻擋的 hook,其處理方式與 `reason` 相同:阻擋訊息會向使用者顯示 stderr 文字,且不會加入情境。
1577 1600
1578```json theme={null}1601```json theme={null}
1579{1602{
1592 被阻擋的提示詞會留下什麼1615 被阻擋的提示詞會留下什麼
1593</h4>1616</h4>
1594 1617
1595被阻擋的提示詞永遠不會傳達給 Claude,但其文字並不會從所有地方移除。預設情況下,顯示給使用者的阻擋訊息結尾會是 `Original prompt:` 加上所提交的文字,而 Claude Code 會將該訊息寫入磁碟上工作階段的逐字稿檔案。若要將文字排除在訊息之外,請在 `hookSpecificOutput` 中輸出含 `"suppressOriginalPrompt": true` 的 JSON。無論 hook 是以 `decision: "block"` 還是以退出碼 2 阻擋,此設定都有效。1618被阻擋的提示詞永遠不會傳達給 Claude,但其文字並不會從所有地方移除。預設情況下,向使用者顯示的阻擋訊息結尾為 `Original prompt:`,後接所送出的文字,而 Claude Code 會將該訊息寫入磁碟上的工作階段逐字稿檔案。若要在訊息中省略該文字,請在 `hookSpecificOutput` 內印出帶有 `"suppressOriginalPrompt": true` 的 JSON。無論 hook 是以 `decision: "block"` 還是以退出碼 2 阻擋,此設定皆有效。
1596 1619
1597`suppressOriginalPrompt` 只會改變阻擋訊息。所提交的文字仍可能出現在本機檔案中,例如工作階段逐字稿和您的提示詞歷史記錄,因此阻擋 hook 並不是讓機密不寫入磁碟的方法。若要限制或移除這些檔案,請參閱[純文字儲存](/docs/zh-TW/claude-directory#plaintext-storage)和[清除本機資料](/docs/zh-TW/claude-directory#clear-local-data)。1620`suppressOriginalPrompt` 只會變更阻擋訊息。所送出的文字仍可能出現在本機檔案中,例如工作階段逐字稿和您的提示詞歷程記錄,因此阻擋 hook 並不是讓機密不落入磁碟的方法。若要限制或移除這些檔案,請參閱[純文字儲存](/docs/zh-TW/claude-directory#plaintext-storage)和[清除本機資料](/docs/zh-TW/claude-directory#clear-local-data)。
1598 1621
1599<h3 id="userpromptexpansion">1622<h3 id="userpromptexpansion">
1600 UserPromptExpansion1623 UserPromptExpansion
1601</h3>1624</h3>
1602 1625
1603在使用者輸入的命令展開為提示詞、傳達給 Claude 之前執行。可用來阻擋特定命令被直接呼叫、為特定 skill 注入上下文,或記錄使用者呼叫了哪些命令。例如,比對 `deploy` 的 hook 可以在核准檔案不存在時阻擋 `/deploy`,或比對審查 skill 的 hook 可以將團隊的審查清單附加為 `additionalContext`。1626在使用者輸入的命令展開為提示詞、傳達給 Claude 之前執行。可用於阻擋特定命令被直接呼叫、為特定 skill 注入情境,或記錄使用者呼叫了哪些命令。例如,比對 `deploy` 的 hook 可以在沒有核准檔案時阻擋 `/deploy`,或比對某個審查 skill 的 hook 可以將團隊的審查檢查清單作為 `additionalContext` 附加。
1604 1627
1605此事件涵蓋了 `PreToolUse` 所沒有涵蓋的路徑:比對 `Skill` 工具的 `PreToolUse` hook 只會在 Claude 呼叫該工具時觸發,但直接輸入 `/skillname` 會略過 `PreToolUse`。`UserPromptExpansion` 會在這條直接路徑上觸發。1628此事件涵蓋了 `PreToolUse` 未涵蓋的路徑:比對 `Skill` 工具的 `PreToolUse` hook 只會在 Claude 呼叫該工具時觸發,但直接輸入 `/skillname` 會繞過 `PreToolUse`。`UserPromptExpansion` 會在該直接路徑上觸發。
1606 1629
1607比對 `command_name`。將 matcher 留空即可在每個提示詞類型的命令上觸發。1630比對 `command_name`。將 matcher 留空可針對每個提示詞類型的命令觸發。
1608 1631
1609<h4 id="userpromptexpansion-input">1632<h4 id="userpromptexpansion-input">
1610 UserPromptExpansion 輸入1633 UserPromptExpansion 輸入
1611</h4>1634</h4>
1612 1635
1613除了[通用輸入欄位](#common-input-fields)之外,UserPromptExpansion hook 還會接收 `expansion_type`、`command_name`、`command_args`、`command_source` 以及原始的 `prompt` 字串。`expansion_type` 欄位對於 skill 和自訂命令為 `slash_command`,對於 MCP 伺服器提示詞則為 `mcp_prompt`。1636除了[通用輸入欄位](#common-input-fields)之外,UserPromptExpansion hook 還會接收 `expansion_type`、`command_name`、`command_args`、`command_source`,以及原始的 `prompt` 字串。`expansion_type` 欄位對於 skill 和自訂命令為 `slash_command`,對於 MCP 伺服器提示詞則為 `mcp_prompt`。
1614 1637
1615```json theme={null}1638```json theme={null}
1616{1639{
1631 UserPromptExpansion 決策控制1654 UserPromptExpansion 決策控制
1632</h4>1655</h4>
1633 1656
1634`UserPromptExpansion` hook 可以阻擋展開或加入上下文。所有 [JSON 輸出欄位](#json-output)皆可使用。1657`UserPromptExpansion` hook 可以阻擋展開或新增情境。所有 [JSON 輸出欄位](#json-output)皆可使用。
1635 1658
1636| 欄位 | 說明 |1659| 欄位 | 說明 |
1637| :- | :- |1660| :- | :- |
1638| `decision` | `"block"` 會阻止命令展開。省略則允許其繼續 |1661| `decision` | `"block"` 會阻止命令展開。省略則允許其繼續 |
1639| `reason` | 當 `decision` 為 `"block"` 時顯示給使用者 |1662| `reason` | 當 `decision` 為 `"block"` 時向使用者顯示 |
1640| `additionalContext` | 與展開後之提示詞一同加入 Claude 上下文的字串。請參閱[為 Claude 加入上下文](#add-context-for-claude) |1663| `additionalContext` | 與展開後的提示詞一同加入 Claude 情境的字串。請參閱[為 Claude 新增情境](#add-context-for-claude) |
1641 1664
1642以退出碼 2 阻擋的 hook 與 `reason` 的處理方式相同:阻擋訊息會向使用者顯示 stderr 文字。1665以退出碼 2 阻擋的 hook,其處理方式與 `reason` 相同:阻擋訊息會向使用者顯示 stderr 文字。
1643 1666
1644```json theme={null}1667```json theme={null}
1645{1668{
1656 MessageDisplay1679 MessageDisplay
1657</h3>1680</h3>
1658 1681
1659在助理訊息串流到畫面上時執行。Claude Code 會逐步顯示訊息:每當一批新完成的行準備好要呈現時,hook 就會以這些行執行一次,而 Claude Code 會在其位置呈現 hook 的替換文字。較長的訊息會產生多次呼叫;較短的訊息可能只產生一次。1682在助理訊息串流顯示到螢幕上時執行。Claude Code 會分段顯示訊息:每當有一批新完成的行準備好呈現時,hook 會以這些行執行一次,Claude Code 則在其位置呈現 hook 的替換文字。長訊息會產生多次呼叫;短訊息可能只產生一次。
1660 1683
1661MessageDisplay 可用於:1684使用 MessageDisplay 來:
1662 1685
1663* 移除 markdown 以呈現精簡的畫面1686* 移除 markdown 以呈現精簡的顯示
1664* 轉換 Agent SDK 應用程式向其使用者顯示的文字1687* 轉換 Agent SDK 應用程式向其使用者顯示的文字
1665* 從 Claude 的回應中遮蔽 API 金鑰或內部主機名稱1688* 從 Claude 的回應中遮蔽 API 金鑰或內部主機名稱
1666 1689
1667Claude Code 會保留每一批內容直到您的 hook 傳回,因此請讓 hook 保持快速。如果 hook 失敗或逾時,Claude Code 會顯示原始文字。此事件的預設逾時為 10 秒;如果您的 hook 需要更多時間,請在 hook 項目中設定 `timeout` 欄位。1690Claude Code 會保留每一批內容直到您的 hook 回傳,因此請讓 hook 保持快速。若 hook 失敗或逾時,Claude Code 會顯示原始文字。此事件的預設逾時為 10 秒;若您的 hook 需要更多時間,請在 hook 項目中設定 `timeout` 欄位。
1668 1691
1669MessageDisplay 僅影響顯示:替換文字只會改變畫面上呈現的內容。逐字稿以及 Claude 看到的內容會保留原始文字,因此 Claude 永遠不會看到替換內容,而詳細模式也會顯示原始文字。hook 只會接收助理訊息文字,因此工具結果和您輸入的文字會原樣呈現。1692MessageDisplay 僅影響顯示:替換文字只會變更螢幕上呈現的內容。逐字稿和 Claude 所見的內容會保留原始文字,因此 Claude 永遠看不到替換內容,詳細模式也會顯示原始文字。hook 只接收助理訊息的文字,因此工具結果和您輸入的文字會原封不動地呈現。
1670 1693
1671MessageDisplay 不支援 matcher,並會針對每則串流文字的助理訊息觸發;沒有文字的訊息(例如僅含工具呼叫的回應)不會觸發它。1694MessageDisplay 不支援 matcher,並會針對每則串流文字的助理訊息觸發;沒有文字的訊息(例如僅包含工具呼叫的回應)不會觸發它。
1672 1695
1673在非互動式執行中,包括 Agent SDK 查詢和 `claude -p`,MessageDisplay 會針對每則助理訊息執行一次,而不是每批行執行一次。這次單一呼叫會在訊息完成後到達,並攜帶完整的訊息文字:`index` 為 `0`、`final` 為 `true`,而 `delta` 包含整則訊息。收集每則訊息之 `delta` 文字的 hook,在兩種模式下都會收到相同的完整文字。1696在非互動式執行中,包括 Agent SDK 查詢和 `claude -p`,MessageDisplay 會對每則助理訊息執行一次,而不是每批行執行一次。這單次呼叫會在訊息完成後到達,並攜帶完整的訊息文字:`index` 為 `0`、`final` 為 `true`,`delta` 則包含整則訊息。收集每則訊息 `delta` 文字的 hook,在兩種模式下接收到的總文字相同。
1674 1697
1675<h4 id="messagedisplay-input">1698<h4 id="messagedisplay-input">
1676 MessageDisplay 輸入1699 MessageDisplay 輸入
1681| 欄位 | 說明 |1704| 欄位 | 說明 |
1682| :- | :- |1705| :- | :- |
1683| `turn_id` | 目前回合的 UUID |1706| `turn_id` | 目前回合的 UUID |
1684| `message_id` | 正在顯示之助理訊息的 UUID。在同一則訊息的每一批中都保持不變。這不是 API 的 `msg_…` id,因此無法與逐字稿的訊息 id 對應 |1707| `message_id` | 正在顯示的助理訊息的 UUID。在同一則訊息的每一批中都相同。這不是 API 的 `msg_…` id,因此無法與逐字稿的訊息 id 對應 |
1685| `index` | 此批次在訊息中從零開始的索引 |1708| `index` | 此批次在訊息中從零開始的索引 |
1686| `final` | 在訊息的最後一批時為 `true`。每則訊息恰好有一個最終批次 |1709| `final` | 在訊息的最後一批為 `true`。每則訊息恰有一個最終批次 |
1687| `delta` | 自上一批以來新完成的行,包含結尾的換行字元。一律為完整的行,但最終批次可能在行中間結束。在互動式執行中,當訊息以換行結尾時,最終批次的 delta 為空,因此請將 `final`(而非非空的 delta)視為訊息結束的訊號。在 Agent SDK 和 `claude -p` 執行中,單一呼叫會攜帶整則訊息 |1710| `delta` | 自上一批以來新完成的行,包含結尾換行字元。一律為完整的行,但最終批次可能在行中間結束。在互動式執行中,當訊息以換行結尾時,最終批次的 delta 為空,因此請將 `final`(而非非空的 delta)視為訊息結束的訊號。在 Agent SDK 和 `claude -p` 執行中,單次呼叫會攜帶整則訊息 |
1688 1711
1689```json theme={null}1712```json theme={null}
1690{1713{
1704 MessageDisplay 輸出1727 MessageDisplay 輸出
1705</h4>1728</h4>
1706 1729
1707除了所有 hook 都可使用的 [JSON 輸出欄位](#json-output)之外,MessageDisplay hook 還可以傳回 `displayContent`,以取代畫面上的 delta:1730除了所有 hook 都可使用的 [JSON 輸出欄位](#json-output)之外,MessageDisplay hook 還可以回傳 `displayContent`,以在螢幕上取代 delta:
1708 1731
1709| 欄位 | 說明 |1732| 欄位 | 說明 |
1710| :- | :- |1733| :- | :- |
1711| `displayContent` | 取代 delta 顯示的文字。省略則顯示原始內容 |1734| `displayContent` | 取代 delta 顯示的文字。省略則顯示原始內容 |
1712 1735
1713MessageDisplay hook 沒有決策控制。它們無法阻擋訊息,也無法改變儲存在逐字稿中或傳送給 Claude 的內容。Claude Code 會採用其 JSON 輸出中的 `displayContent`,並捨棄 `systemMessage` 和 `continue`。1736MessageDisplay hook 沒有決策控制。它們無法阻擋訊息,也無法變更儲存在逐字稿中或傳送給 Claude 的內容。Claude Code 會依據其 JSON 輸出中的 `displayContent` 採取動作,並捨棄 `systemMessage` 和 `continue`。
1714 1737
1715此範例會從 Claude 的回應中移除 markdown 格式,以純文字方式顯示。指令碼會從 stdin 讀取每一批內容,從 `delta` 中移除粗體標記和行內程式碼的反引號,並將結果作為 `displayContent` 傳回。1738此範例會從 Claude 的回應中移除 markdown 格式,以純文字方式顯示。指令碼會從 stdin 讀取每一批,從 `delta` 中移除粗體標記和行內程式碼反引號,並將結果作為 `displayContent` 回傳。
1716 1739
1717<Tabs>1740<Tabs>
1718 <Tab title="macOS/Linux">1741 <Tab title="macOS/Linux">
1719 在您的設定檔中為此事件註冊命令 hook:1742 在您的設定檔中為此事件註冊一個 command hook:
1720 1743
1721 ```json theme={null}1744 ```json theme={null}
1722 {1745 {
1745 </Tab>1768 </Tab>
1746 1769
1747 <Tab title="Windows (PowerShell)">1770 <Tab title="Windows (PowerShell)">
1748 註冊透過 PowerShell 執行指令碼的命令 hook:1771 註冊一個透過 PowerShell 執行指令碼的 command hook:
1749 1772
1750 ```json theme={null}1773 ```json theme={null}
1751 {1774 {
1771 }1794 }
1772 ```1795 ```
1773 1796
1774 `-NoProfile` 旗標會略過載入您的 PowerShell 設定檔,讓 hook 快速啟動,而 `-ExecutionPolicy Bypass` 則讓 PowerShell 可以執行本機指令碼檔案。1797 `-NoProfile` 旗標會略過載入您的 PowerShell 設定檔,讓 hook 快速啟動,而 `-ExecutionPolicy Bypass` 則讓 PowerShell 能執行本機指令碼檔案。
1775 1798
1776 將此指令碼儲存至專案中的 `.claude/hooks/plain-display.ps1`:1799 將此指令碼儲存至專案中的 `.claude/hooks/plain-display.ps1`:
1777 1800
1788 </Tab>1811 </Tab>
1789</Tabs>1812</Tabs>
1790 1813
1791沒有 markdown 的批次會原樣通過。如果指令碼失敗,例如因為缺少 `jq`,Claude Code 會顯示原始文字,並只在[除錯輸出](#debug-hooks)中記錄失敗,不會在工作階段中顯示。1814不含 markdown 的批次會原封不動地通過。若指令碼失敗,例如因為缺少 `jq`,Claude Code 會顯示原始文字,並只在[除錯輸出](#debug-hooks)中記錄該失敗,而不會在工作階段中顯示。
1792 1815
1793<h3 id="pretooluse">1816<h3 id="pretooluse">
1794 PreToolUse1817 PreToolUse
1795</h3>1818</h3>
1796 1819
1797在 Claude 建立工具參數之後、處理工具呼叫之前執行。比對除了 `EndConversation` 以外的任何工具名稱:內建工具,例如 `Bash`、`PowerShell`、`Edit`、`Write`、`Read`、`Glob`、`Grep`、`Agent`、`Workflow`、`WebFetch`、`WebSearch`、`AskUserQuestion` 和 `ExitPlanMode`,以及任何 [MCP 工具名稱](#match-mcp-tools)。1820在 Claude 建立工具參數之後、處理工具呼叫之前執行。比對 `EndConversation` 以外的任何工具名稱:內建工具如 `Bash`、`PowerShell`、`Edit`、`Write`、`Read`、`Glob`、`Grep`、`Agent`、`Workflow`、`WebFetch`、`WebSearch`、`AskUserQuestion` 和 `ExitPlanMode`,以及任何 [MCP 工具名稱](#match-mcp-tools)。
1798 1821
1799若要在特定檔案於磁碟上變更時執行 hook(無論是由誰寫入),請使用 [FileChanged](#filechanged),而不是依名稱比對編輯檔案的工具。與 PreToolUse 不同,Claude Code 會在變更之後執行 FileChanged hook,而且它們沒有決策控制,因此無法阻擋寫入。1822若要在特定檔案於磁碟上變更時執行 hook(無論是誰寫入的),請使用 [FileChanged](#filechanged),而不要依名稱比對檔案編輯工具。與 PreToolUse 不同,Claude Code 會在變更之後執行 FileChanged hook,且它們沒有決策控制,因此無法阻擋寫入。
1800 1823
1801<Warning>1824<Warning>
1802 PreToolUse 只在 Claude 呼叫工具時執行。您[在提示詞中以 `@` 參照](/docs/zh-TW/common-workflows#reference-files-and-directories)的檔案不經任何工具呼叫即被加入:Claude Code 在建構提示詞時插入其內容,因此不會為它們觸發任何 PreToolUse hook,包括比對 `Read` 的 hook。若要阻擋 `@` 參照特定路徑,請改用 [`Read` 拒絕規則](/docs/zh-TW/permissions#read-and-edit)。1825 PreToolUse 只在 Claude 呼叫工具時執行。預設情況下,您[在提示詞中以 `@` 參照](/docs/zh-TW/common-workflows#reference-files-and-directories)的檔案會在沒有任何工具呼叫的情況下加入。Claude Code 會在建構提示詞時插入其內容,因此不會為它們觸發任何 PreToolUse hook,包括比對 `Read` 的 hook。PreToolUse 也不會針對 [`EndConversation`](/docs/zh-TW/tools-reference#endconversation-tool-behavior) 觸發。
1826
1827 您可以阻擋特定路徑被 `@` 參照,或關閉插入功能:
1803 1828
1804 PreToolUse 也不會針對 [`EndConversation`](/docs/zh-TW/tools-reference#endconversation-tool-behavior) 觸發。1829 * **阻擋特定路徑**:為它們新增 [`Read` 拒絕規則](/docs/zh-TW/permissions#read-and-edit)
1830 * **關閉插入功能**:在您的 shell、使用者設定或受管設定中設定 [`CLAUDE_CODE_DISABLE_FILE_MENTIONS=1`](/docs/zh-TW/env-vars#variables)。Claude 接著會取得被提及的路徑,並附上一則說明,要求以其檔案工具讀取。若 Claude 這麼做,您相符的 PreToolUse hook 就會執行。此變數需要 Claude Code v2.1.299 或更新版本,且 Claude Code 會在專案設定和本機設定中忽略它。
1805</Warning>1831</Warning>
1806 1832
1807使用 [PreToolUse 決策控制](#pretooluse-decision-control)來允許、拒絕、詢問或延後工具呼叫。1833使用 [PreToolUse 決策控制](#pretooluse-decision-control)來允許、拒絕、詢問或延遲工具呼叫。
1808 1834
1809`PreToolUse` 上超過逾時的 [Agent SDK 回呼 hook](/docs/zh-TW/agent-sdk/hooks) 會阻擋工具呼叫,而 Claude 會收到說明該逾時的錯誤結果。其他 hook 傳回的明確拒絕仍然優先。1835`PreToolUse` 上的 [Agent SDK 回呼 hook](/docs/zh-TW/agent-sdk/hooks) 若超過逾時,會阻擋工具呼叫,而 Claude 會收到指出逾時的錯誤結果。其他 hook 回傳的明確拒絕仍會優先。
1810 1836
1811<h4 id="pretooluse-input">1837<h4 id="pretooluse-input">
1812 PreToolUse 輸入1838 PreToolUse 輸入
1814 1840
1815除了[通用輸入欄位](#common-input-fields)之外,PreToolUse hook 還會接收 `tool_name`、`tool_input` 和 `tool_use_id`。1841除了[通用輸入欄位](#common-input-fields)之外,PreToolUse hook 還會接收 `tool_name`、`tool_input` 和 `tool_use_id`。
1816 1842
1817對於 [MCP 工具](#match-mcp-tools),輸入還會攜帶 `mcp_server`,這是一個包含伺服器 `name` 以及說明伺服器定義來源之 `source` 的物件。`source` 的值包括 `plugin`、`sdk`,以及 `user` 和 `project` 等設定範圍。Agent SDK 參考文件中的 [`McpServerProvenance`](/docs/zh-TW/agent-sdk/typescript#mcpserverprovenance) 列出了所有值,並說明如何處理無法辨識的值。請依據 `source` 做出信任決策,而不是依據 `name` 或 `mcp__<server>__` 工具名稱前綴。`mcp_server` 欄位需要 Claude Code v2.1.274 或更新版本。1843對於 [MCP 工具](#match-mcp-tools),輸入還會攜帶 `mcp_server`,這是一個包含伺服器 `name` 以及說明伺服器定義來源之 `source` 的物件。`source` 的值包括 `plugin`、`sdk`,以及 `user` 和 `project` 等設定範圍。Agent SDK 參考文件中的 [`McpServerProvenance`](/docs/zh-TW/agent-sdk/typescript#mcpserverprovenance) 列出了所有值,並說明如何處理您無法辨識的值。請根據 `source` 而非 `name` 或 `mcp__<server>__` 工具名稱前綴來做信任決策。`mcp_server` 欄位需要 Claude Code v2.1.274 或更新版本。
1818 1844
1819對於檔案工具 `Write`、`Edit` 和 `Read`,`tool_input.file_path` 一律為絕對路徑:1845對於檔案工具 `Write`、`Edit` 和 `Read`,`tool_input.file_path` 一律為絕對路徑:
1820 1846
1821* Claude Code 會在 hook 執行前展開 `~` 和相對路徑,因此比對路徑的 hook 無法透過 `~` 或同一路徑的相對寫法繞過1847* Claude Code 會在 hook 執行前展開 `~` 和相對路徑,因此比對路徑的 hook 無法透過 `~` 或同一路徑的相對寫法被繞過
1822* 在 Windows 上,路徑會以反斜線分隔符號傳入,即使您的 hook 在 `$PWD` 看起來像 `/c/project` 的 Git Bash 下執行也是如此1848* 在 Windows 上,路徑會以反斜線分隔符號送達,即使您的 hook 在 Git Bash 下執行、`$PWD` 看起來像 `/c/project` 也是如此
1823* 以正斜線撰寫的比較(例如 `/src/` 檢查)永遠不會比對到反斜線路徑,工具呼叫會像 hook 沒有任何可阻擋的內容一樣繼續進行1849* 以正斜線撰寫的比較(例如 `/src/` 檢查)永遠不會比對到反斜線路徑,工具呼叫會如同 hook 沒有要阻擋的內容般繼續進行
1824* 比較前請先正規化分隔符號:在 Bash 中使用 `FILE_PATH="${FILE_PATH//\\//}"`,或在 Python 中使用 `file_path.replace("\\", "/")`,然後比對路徑片段(例如 `/src/`),而不是以 `^` 錨定,因為路徑是絕對路徑1850* 比較前請先正規化分隔符號:在 Bash 中使用 `FILE_PATH="${FILE_PATH//\\//}"`,或在 Python 中使用 `file_path.replace("\\", "/")`,然後比對 `/src/` 之類的路徑片段,而不要以 `^` 錨定,因為路徑是絕對路徑
1825 1851
1826在 Windows 上的 `Write` 呼叫會傳入:1852Windows 上的 `Write` 呼叫會傳遞:
1827 1853
1828```json theme={null}1854```json theme={null}
1829{1855{
1837}1863}
1838```1864```
1839 1865
1840`tool_input` 的欄位取決於工具:1866`tool_input` 欄位取決於工具:
1841 1867
1842<a id="bash" />1868<a id="bash" />
1843 1869
1850| 欄位 | 類型 | 範例 | 說明 |1876| 欄位 | 類型 | 範例 | 說明 |
1851| :- | :- | :- | :- |1877| :- | :- | :- | :- |
1852| `command` | string | `"npm test"` | 要執行的 shell 命令 |1878| `command` | string | `"npm test"` | 要執行的 shell 命令 |
1853| `description` | string | `"Run test suite"` | 選用的命令用途說明 |1879| `description` | string | `"Run test suite"` | 選用,說明命令用途 |
1854| `timeout` | number | `120000` | 選用的逾時(毫秒)。超過[上限](/docs/zh-TW/tools-reference#bash-tool-behavior)的值會被降為上限,而不會被拒絕 |1880| `timeout` | number | `120000` | 選用,以毫秒為單位的逾時。超過[上限](/docs/zh-TW/tools-reference#bash-tool-behavior)的值會被降至上限,而不會被拒絕 |
1855| `run_in_background` | boolean | `false` | 是否在背景執行命令 |1881| `run_in_background` | boolean | `false` | 是否在背景執行命令 |
1856 1882
1857當 Bash 命令變更 Git 儲存庫中的檔案時,Claude Code 可以記錄變更的內容。當 [`bashEditDiffEnabled`](/docs/zh-TW/settings-reference#basheditdiffenabled) 設定開啟記錄時,它會在每種權限模式下記錄變更;該設定的項目說明了哪些檔案可以設定它。否則,它只會在自動模式和 `bypassPermissions` 模式下記錄變更,而且只在 Claude Code 指示 Claude 透過 Bash 編輯檔案時記錄。將 `bashEditDiffEnabled` 設為 `false` 可關閉記錄。背景命令和唯讀命令不會攜帶差異。1883當 Bash 命令變更 Git 儲存庫中的檔案時,Claude Code 可以記錄變更內容。當 [`bashEditDiffEnabled`](/docs/zh-TW/settings-reference#basheditdiffenabled) 設定開啟記錄時,它會在每種權限模式下記錄變更;該設定的項目說明了哪些檔案可以設定它。否則,它只會在自動模式和 `bypassPermissions` 模式下記錄,且僅在 Claude Code 指示 Claude 透過 Bash 編輯檔案時才記錄。將 `bashEditDiffEnabled` 設為 `false` 可關閉記錄。背景命令和唯讀命令不會附帶差異。
1858 1884
1859接著,您的 [PostToolUse hook](#posttooluse) 會在 `tool_response.bashEditDiff` 中接收變更的檔案。此清單涵蓋命令執行期間儲存庫下變更的內容。Git 忽略的檔案以及子模組中的檔案不會列出。需要 Claude Code v2.1.269 或更新版本。1885接著,您的 [PostToolUse hook](#posttooluse) 會在 `tool_response.bashEditDiff` 中接收變更的檔案。此清單涵蓋命令執行期間儲存庫中發生的變更。Git 忽略的檔案和子模組中的檔案不會列出。需要 Claude Code v2.1.269 或更新版本。
1860 1886
1861<Note>1887<Note>
1862 此清單為盡力而為,目前處於公開測試版。Claude Code 可能遺漏變更、包含另一個程序同時變更的檔案,或在達到大小限制時停止。欄位結構可能會變更。請使用此清單來找出需要審查的內容,而不是用來強制執行政策。1888 此清單為盡力而為,且處於公開測試版。Claude Code 可能遺漏某項變更、納入另一個程序同時變更的檔案,或在達到大小限制時停止。欄位結構可能會變更。請使用此清單來找出需要審查的內容,而不要用來強制執行政策。
1863</Note>1889</Note>
1864 1890
1865`changedFiles` 和 `files` 列出命令變更的內容;其餘欄位說明該清單的完整度和可靠度。1891`changedFiles` 和 `files` 列出命令變更的內容;其餘欄位說明該清單的完整程度和可靠程度。
1866 1892
1867| 欄位 | 類型 | 範例 | 說明 |1893| 欄位 | 類型 | 範例 | 說明 |
1868| :- | :- | :- | :- |1894| :- | :- | :- | :- |
1869| `changedFiles` | array | `["/path/to/src/app.ts"]` | 命令變更之檔案的絕對路徑,最多 200 個。只要 `files` 包含差異或 `moreFiles` 大於零就會出現 |1895| `changedFiles` | array | `["/path/to/src/app.ts"]` | 命令變更的檔案絕對路徑,最多 200 個。只要 `files` 包含差異或 `moreFiles` 大於零時就會出現 |
1870| `files` | array | `[{"filePath": "/path/to/src/app.ts", "hunks": [...]}]` | 最多 5 個變更檔案的差異,供顯示用。對於命令新增或移除的檔案,`created` 或 `deleted` 為 `true` |1896| `files` | array | `[{"filePath": "/path/to/src/app.ts", "hunks": [...]}]` | 最多 5 個變更檔案的差異,供顯示用。對於命令新增或移除的檔案,`created` 或 `deleted` 為 `true` |
1871| `moreFiles` | number | `2` | 在 `files` 中沒有差異的變更檔案數量 |1897| `moreFiles` | number | `2` | 在 `files` 中沒有差異的變更檔案數量 |
1872| `unavailable` | boolean | `true` | 當差異不完整或無法取得時設定 |1898| `unavailable` | boolean | `true` | 當差異不完整或無法取得時設定 |
1873| `skipped` | boolean | `true` | 針對會移動工作樹的 Git 命令(例如 `git checkout` 或 `git stash`)設定,此時 Claude Code 不會取得差異 |1899| `skipped` | boolean | `true` | 針對會移動工作樹的 Git 命令設定,例如 `git checkout` 或 `git stash`,因此 Claude Code 不會取得差異 |
1874| `shared` | boolean | `true` | 當另一個 Bash 工具呼叫(例如 subagent 的呼叫)同時在同一個儲存庫中執行時設定,因此部分列出的變更可能來自該命令 |1900| `shared` | boolean | `true` | 當另一個 Bash 工具呼叫(例如 subagent 的呼叫)同時在相同儲存庫中執行時設定,因此部分列出的變更可能來自該命令 |
1875 1901
1876<a id="powershell" />1902<a id="powershell" />
1877 1903
1879 PowerShell1905 PowerShell
1880</h5>1906</h5>
1881 1907
1882執行 PowerShell 命令。各平台的可用性請參閱 [PowerShell 工具](/docs/zh-TW/tools-reference#powershell-tool)。1908執行 PowerShell 命令。關於各平台的可用性,請參閱 [PowerShell 工具](/docs/zh-TW/tools-reference#powershell-tool)。
1883 1909
1884欄位與 Bash 工具相同,命令字串位於 `command`:1910欄位與 Bash 工具相同,命令字串位於 `command`:
1885 1911
1886| 欄位 | 類型 | 範例 | 說明 |1912| 欄位 | 類型 | 範例 | 說明 |
1887| :- | :- | :- | :- |1913| :- | :- | :- | :- |
1888| `command` | string | `"Get-ChildItem -Recurse"` | 要執行的 PowerShell 命令 |1914| `command` | string | `"Get-ChildItem -Recurse"` | 要執行的 PowerShell 命令 |
1889| `description` | string | `"List files recursively"` | 選用的命令用途說明 |1915| `description` | string | `"List files recursively"` | 選用,說明命令用途 |
1890| `timeout` | number | `120000` | 選用的逾時(毫秒) |1916| `timeout` | number | `120000` | 選用,以毫秒為單位的逾時 |
1891| `run_in_background` | boolean | `false` | 是否在背景執行命令 |1917| `run_in_background` | boolean | `false` | 是否在背景執行命令 |
1892 1918
1893在檢查 shell 命令的 hook 中比對 `Bash|PowerShell`,以涵蓋兩種工具:1919在檢查 shell 命令的 hook 中比對 `Bash|PowerShell`,以涵蓋兩種工具:
1894 1920
1895* 在 Windows 上,只要啟用了 PowerShell 工具,Claude 就會將 PowerShell 視為主要 shell,並透過它路由 shell 命令。1921* 在 Windows 上,只要啟用了 PowerShell 工具,Claude 就會將 PowerShell 視為主要 shell,並透過它傳送 shell 命令。
1896* 在沒有 Git Bash 的 Windows 上,該工具會自動啟用,且 Claude Code 完全不會註冊 Bash 工具。1922* 在沒有 Git Bash 的 Windows 上,該工具會自動啟用,且 Claude Code 完全不會註冊 Bash 工具。
1897* 只比對 `Bash` 的 hook 在該處永遠不會觸發。1923* 只比對 `Bash` 的 hook 在那裡永遠不會觸發。
1898 1924
1899<h5 id="write">1925<h5 id="write">
1900 Write1926 Write
1904 1930
1905| 欄位 | 類型 | 範例 | 說明 |1931| 欄位 | 類型 | 範例 | 說明 |
1906| :- | :- | :- | :- |1932| :- | :- | :- | :- |
1907| `file_path` | string | `"/path/to/file.txt"` | 要寫入之檔案的絕對路徑 |1933| `file_path` | string | `"/path/to/file.txt"` | 要寫入的檔案的絕對路徑 |
1908| `content` | string | `"file content"` | 要寫入檔案的內容 |1934| `content` | string | `"file content"` | 要寫入檔案的內容 |
1909 1935
1910<h5 id="edit">1936<h5 id="edit">
1911 Edit1937 Edit
1912</h5>1938</h5>
1913 1939
1914取代既有檔案中的字串。1940取代現有檔案中的字串。
1915 1941
1916| 欄位 | 類型 | 範例 | 說明 |1942| 欄位 | 類型 | 範例 | 說明 |
1917| :- | :- | :- | :- |1943| :- | :- | :- | :- |
1918| `file_path` | string | `"/path/to/file.txt"` | 要編輯之檔案的絕對路徑 |1944| `file_path` | string | `"/path/to/file.txt"` | 要編輯的檔案的絕對路徑 |
1919| `old_string` | string | `"original text"` | 要尋找並取代的文字 |1945| `old_string` | string | `"original text"` | 要尋找並取代的文字 |
1920| `new_string` | string | `"replacement text"` | 取代文字 |1946| `new_string` | string | `"replacement text"` | 替換文字 |
1921| `replace_all` | boolean | `false` | 是否取代所有出現處 |1947| `replace_all` | boolean | `false` | 是否取代所有出現處 |
1922 1948
1923<h5 id="read">1949<h5 id="read">
1928 1954
1929| 欄位 | 類型 | 範例 | 說明 |1955| 欄位 | 類型 | 範例 | 說明 |
1930| :- | :- | :- | :- |1956| :- | :- | :- | :- |
1931| `file_path` | string | `"/path/to/file.txt"` | 要讀取之檔案的絕對路徑 |1957| `file_path` | string | `"/path/to/file.txt"` | 要讀取的檔案的絕對路徑 |
1932| `offset` | number | `10` | 選用的起始讀取行號 |1958| `offset` | number | `10` | 選用,開始讀取的行號 |
1933| `limit` | number | `50` | 選用的讀取行數 |1959| `limit` | number | `50` | 選用,要讀取的行數 |
1934 1960
1935<h5 id="glob">1961<h5 id="glob">
1936 Glob1962 Glob
1941| 欄位 | 類型 | 範例 | 說明 |1967| 欄位 | 類型 | 範例 | 說明 |
1942| :- | :- | :- | :- |1968| :- | :- | :- | :- |
1943| `pattern` | string | `"**/*.ts"` | 用來比對檔案的 glob 模式 |1969| `pattern` | string | `"**/*.ts"` | 用來比對檔案的 glob 模式 |
1944| `path` | string | `"/path/to/dir"` | 選用的搜尋目錄。預設為目前工作目錄 |1970| `path` | string | `"/path/to/dir"` | 選用,要搜尋的目錄。預設為目前的工作目錄 |
1945 1971
1946<h5 id="grep">1972<h5 id="grep">
1947 Grep1973 Grep
1948</h5>1974</h5>
1949 1975
1950以正規表示式搜尋檔案內容。1976使用正規表示式搜尋檔案內容。
1951 1977
1952| 欄位 | 類型 | 範例 | 說明 |1978| 欄位 | 類型 | 範例 | 說明 |
1953| :- | :- | :- | :- |1979| :- | :- | :- | :- |
1954| `pattern` | string | `"TODO.*fix"` | 要搜尋的正規表示式模式 |1980| `pattern` | string | `"TODO.*fix"` | 要搜尋的正規表示式模式 |
1955| `path` | string | `"/path/to/dir"` | 選用的搜尋檔案或目錄 |1981| `path` | string | `"/path/to/dir"` | 選用,要搜尋的檔案或目錄 |
1956| `glob` | string | `"*.ts"` | 選用的 glob 模式,用於篩選檔案 |1982| `glob` | string | `"*.ts"` | 選用,用於篩選檔案的 glob 模式 |
1957| `output_mode` | string | `"content"` | `"content"`、`"files_with_matches"` 或 `"count"`。預設為 `"files_with_matches"` |1983| `output_mode` | string | `"content"` | `"content"`、`"files_with_matches"` 或 `"count"`。預設為 `"files_with_matches"` |
1958| `-i` | boolean | `true` | 不區分大小寫搜尋 |1984| `-i` | boolean | `true` | 不區分大小寫的搜尋 |
1959| `multiline` | boolean | `false` | 啟用多行比對 |1985| `multiline` | boolean | `false` | 啟用多行比對 |
1960 1986
1961<h5 id="webfetch">1987<h5 id="webfetch">
1967| 欄位 | 類型 | 範例 | 說明 |1993| 欄位 | 類型 | 範例 | 說明 |
1968| :- | :- | :- | :- |1994| :- | :- | :- | :- |
1969| `url` | string | `"https://example.com/api"` | 要擷取內容的 URL |1995| `url` | string | `"https://example.com/api"` | 要擷取內容的 URL |
1970| `prompt` | string | `"Extract the API endpoints"` | 要在擷取內容上執行的提示詞 |1996| `prompt` | string | `"Extract the API endpoints"` | 對擷取內容執行的提示詞 |
1971| `offset` | number | `100000` | 從頁面開頭略過的選用字元數。Claude 會設定此值以繼續讀取長頁面。需要 Claude Code v2.1.290 或更新版本 |1997| `offset` | number | `100000` | 選用,從頁面開頭略過的字元數。Claude 會設定此值以繼續閱讀長頁面。需要 Claude Code v2.1.290 或更新版本 |
1972 1998
1973<h5 id="websearch">1999<h5 id="websearch">
1974 WebSearch2000 WebSearch
1986 Agent2012 Agent
1987</h5>2013</h5>
1988 2014
1989產生 [subagent](/docs/zh-TW/sub-agents)。2015產生一個 [subagent](/docs/zh-TW/sub-agents)。
1990 2016
1991| 欄位 | 類型 | 範例 | 說明 |2017| 欄位 | 類型 | 範例 | 說明 |
1992| :- | :- | :- | :- |2018| :- | :- | :- | :- |
1993| `prompt` | string | `"Find all API endpoints"` | agent 要執行的任務 |2019| `prompt` | string | `"Find all API endpoints"` | agent 要執行的任務 |
1994| `description` | string | `"Find API endpoints"` | 任務的簡短說明 |2020| `description` | string | `"Find API endpoints"` | 任務的簡短說明 |
1995| `subagent_type` | string | `"Explore"` | 要使用的專門 agent 類型 |2021| `subagent_type` | string | `"Explore"` | 要使用的專門 agent 類型 |
1996| `model` | string | `"sonnet"` | 選用的模型別名,用於覆寫預設值 |2022| `model` | string | `"sonnet"` | 選用,用來覆寫預設值的模型別名 |
1997 2023
1998當前景 Agent 呼叫完成時,您的 [PostToolUse hook](#posttooluse) 會在 `tool_response` 中接收 subagent 的結果和執行遙測。讀取這些欄位以檢查該次執行;若要彙總跨 subagent 的 token 和成本,請使用篩選 `query_source` 為 `"subagent"` 的 [token 和成本計數器](/docs/zh-TW/monitoring-usage#token-counter),因為 `totalTokens` 和 `usage` 只涵蓋最後一個請求:2024當前景 Agent 呼叫完成時,您的 [PostToolUse hook](#posttooluse) 會在 `tool_response` 中接收 subagent 的結果和執行遙測。讀取這些欄位以檢視執行情況;若要彙總各 subagent 的 token 和成本,請使用以 `query_source` `"subagent"` 篩選的 [token 和成本計數器](/docs/zh-TW/monitoring-usage#token-counter),因為 `totalTokens` 和 `usage` 只涵蓋最後一個請求:
1999 2025
2000| 欄位 | 類型 | 範例 | 說明 |2026| 欄位 | 類型 | 範例 | 說明 |
2001| :- | :- | :- | :- |2027| :- | :- | :- | :- |
2002| `status` | string | `"completed"` | 前景 subagent 為 `"completed"`,背景 subagent 為 `"async_launched"`。subagent 預設在背景執行,因此省略 `run_in_background` 的 Agent 呼叫也會產生 `"async_launched"` |2028| `status` | string | `"completed"` | 前景 subagent 為 `"completed"`,背景 subagent 為 `"async_launched"`。subagent 預設在背景執行,因此省略 `run_in_background` 的 Agent 呼叫也會產生 `"async_launched"` |
2003| `agentId` | string | `"a4d2c8f1e0b3a297"` | subagent 執行的識別碼 |2029| `agentId` | string | `"a4d2c8f1e0b3a297"` | subagent 執行的識別碼 |
2004| `content` | array | `[{"type": "text", "text": "Found 12 endpoints..."}]` | subagent 的最終文字區塊;對於透過 `SubagentHandback` 提交報告的 subagent,則以一則關於該移交的簡短說明取代 |2030| `content` | array | `[{"type": "text", "text": "Found 12 endpoints..."}]` | subagent 的最終文字區塊;對於透過 `SubagentHandback` 提交報告的 subagent,則以一則關於該交回的簡短說明代替 |
2005| `resolvedModel` | string | `"claude-sonnet-4-5"` | subagent 啟動時使用的模型,可能與請求的模型不同 |2031| `resolvedModel` | string | `"claude-sonnet-4-5"` | subagent 起始使用的模型,可能與所要求的模型不同 |
2006| `modelsUsed` | array | `["claude-sonnet-4-5", "claude-haiku-4-5"]` | 依序使用的模型,連續重複者會合併;只在執行途中切換模型時設定。需要 Claude Code v2.1.212 或更新版本 |2032| `modelsUsed` | array | `["claude-sonnet-4-5", "claude-haiku-4-5"]` | 依序使用的模型,連續重複者會合併;僅在執行中途切換模型時設定。需要 Claude Code v2.1.212 或更新版本 |
2007| `totalTokens` | number | `12450` | subagent 最後一個 API 請求的 token 數:輸入、輸出和快取 token 的合計。這不是整次執行的總計 |2033| `totalTokens` | number | `12450` | subagent 最後一個 API 請求的 token 數:輸入、輸出和快取 token 的總和。這不是整個執行的總計 |
2008| `totalDurationMs` | number | `48211` | subagent 執行的實際持續時間 |2034| `totalDurationMs` | number | `48211` | subagent 執行的實際經過時間 |
2009| `totalToolUseCount` | number | `7` | subagent 進行的工具呼叫次數 |2035| `totalToolUseCount` | number | `7` | subagent 進行的工具呼叫次數 |
2010| `usage` | object | `{"input_tokens": 8320, ...}` | 最後一個 API 請求依類型區分的 token 明細:`input_tokens`、`output_tokens`、`cache_creation_input_tokens`、`cache_read_input_tokens` |2036| `usage` | object | `{"input_tokens": 8320, ...}` | 最後一個 API 請求的各類型 token 明細:`input_tokens`、`output_tokens`、`cache_creation_input_tokens`、`cache_read_input_tokens` |
2011 2037
2012在 Claude Code v2.1.271 或更新版本中,使用 [`SubagentHandback`](/docs/zh-TW/tools-reference) 工具(Claude Code 在[自動模式](/docs/zh-TW/permission-modes#eliminate-prompts-with-auto-mode)中提供)執行的 subagent,會透過該工具提交報告,而不是以文字傳回。其 `completed` 結果的 `content` 欄位此時攜帶的是關於該移交的簡短說明,而非報告本身。若要讀取報告,請讓 `PreToolUse` 或 `PostToolUse` hook 比對 `SubagentHandback`,並讀取 `tool_input.message`。2038在 Claude Code v2.1.271 或更新版本中,以 [`SubagentHandback`](/docs/zh-TW/tools-reference) 工具執行的 subagent(Claude Code 在[自動模式](/docs/zh-TW/permission-modes#eliminate-prompts-with-auto-mode)中提供此工具)會透過該工具提交報告,而不是以文字回傳。此時其 `completed` 結果的 `content` 欄位會攜帶一則關於該交回的簡短說明,而非報告本身。若要讀取報告,請讓 `PreToolUse` 或 `PostToolUse` hook 比對 `SubagentHandback`,並讀取 `tool_input.message`。
2013 2039
2014對於背景 subagent,工具會在任務移至背景時傳回,因此 `tool_response` 不會攜帶用量欄位:背景啟動會立即傳回,而被 Claude Code 在執行途中移至背景的前景任務會在轉換時傳回。它包含 `status: "async_launched"`、`agentId`、`description`、`prompt`、`outputFile` 和 `resolvedModel`。2040對於背景 subagent,工具會在任務移至背景時回傳,因此 `tool_response` 不攜帶任何用量欄位:背景啟動會立即回傳,而被 Claude Code 在執行中途移至背景的前景任務則會在該轉換時回傳。它包含 `status: "async_launched"`、`agentId`、`description`、`prompt`、`outputFile` 和 `resolvedModel`。
2015 2041
2016在 `completed` 回應中,`resolvedModel` 指出 subagent 啟動時使用的模型,可能與 `tool_input` 中的 `model` 值不同,例如當 `availableModels` 或其他覆寫套用時。在 `async_launched` 回應中,`resolvedModel` 指出 agent 移至背景時使用中的模型,因此在移至背景之前發生的切換會反映在其中。`modelsUsed` 以及移至背景時的 `resolvedModel` 行為需要 Claude Code v2.1.212 或更新版本。2042在 `completed` 回應中,`resolvedModel` 指的是 subagent 起始使用的模型,可能與 `tool_input` 中的 `model` 值不同,例如套用了 `availableModels` 或其他覆寫時。在 `async_launched` 回應中,`resolvedModel` 指的是 agent 移至背景時所使用的模型,因此在移至背景之前發生的切換會反映在其中。`modelsUsed` 以及移至背景時的 `resolvedModel` 行為需要 Claude Code v2.1.212 或更新版本。
2017 2043
2018<a id="askuserquestion" />2044<a id="askuserquestion" />
2019 2045
2021 AskUserQuestion2047 AskUserQuestion
2022</h5>2048</h5>
2023 2049
2024向使用者提出一到四個選擇題。2050向使用者詢問一到四個多選題。
2025 2051
2026| 欄位 | 類型 | 範例 | 說明 |2052| 欄位 | 類型 | 範例 | 說明 |
2027| :- | :- | :- | :- |2053| :- | :- | :- | :- |
2028| `questions` | array | `[{"question": "Which framework?", "header": "Framework", "options": [{"label": "React", "description": "Component library"}, {"label": "Vue", "description": "Progressive framework"}], "multiSelect": false}]` | 要呈現的問題,每個問題包含 `question` 字串、簡短的 `header`、`options` 陣列,以及選用的 `multiSelect` 旗標 |2054| `questions` | array | `[{"question": "Which framework?", "header": "Framework", "options": [{"label": "React", "description": "Component library"}, {"label": "Vue", "description": "Progressive framework"}], "multiSelect": false}]` | 要呈現的問題,每個問題包含 `question` 字串、簡短的 `header`、`options` 陣列,以及選用的 `multiSelect` 旗標 |
2029| `answers` | object | `{"Which framework?": "React"}` | 選用。將問題文字對應到所選選項的標籤。多選答案會以逗號連接標籤。Claude 不會設定此欄位;請透過 `updatedInput` 提供以程式化方式回答 |2055| `answers` | object | `{"Which framework?": "React"}` | 選用。將問題文字對應到所選選項的標籤。多選答案會以逗號連接標籤。Claude 不會設定此欄位;若要以程式方式回答,請透過 `updatedInput` 提供 |
2030 2056
2031<h5 id="exitplanmode">2057<h5 id="exitplanmode">
2032 ExitPlanMode2058 ExitPlanMode
2033</h5>2059</h5>
2034 2060
2035呈現計畫並請使用者核准,之後 Claude 才會離開 [plan mode](/docs/zh-TW/permission-modes#analyze-before-you-edit-with-plan-mode)。Claude 會在呼叫工具之前將計畫寫入磁碟上的檔案,因此模型提供的原始 `tool_input` 通常是空的。Claude Code 會在將輸入傳給 hook 之前注入計畫內容和檔案路徑。2061呈現計畫,並在 Claude 離開 [plan mode](/docs/zh-TW/permission-modes#analyze-before-you-edit-with-plan-mode) 之前請使用者核准。Claude 會在呼叫工具之前將計畫寫入磁碟上的檔案,因此模型傳來的原始 `tool_input` 通常是空的。Claude Code 會在將輸入傳給 hook 之前注入計畫內容和檔案路徑。
2036 2062
2037| 欄位 | 類型 | 範例 | 說明 |2063| 欄位 | 類型 | 範例 | 說明 |
2038| :- | :- | :- | :- |2064| :- | :- | :- | :- |
2039| `plan` | string | `"## Refactor auth\n1. Extract..."` | Markdown 格式的計畫內容。從磁碟上的計畫檔案注入 |2065| `plan` | string | `"## Refactor auth\n1. Extract..."` | Markdown 格式的計畫內容。從磁碟上的計畫檔案注入 |
2040| `planFilePath` | string | `"/Users/.../plans/refactor-auth.md"` | 計畫檔案的路徑。注入 |2066| `planFilePath` | string | `"/Users/.../plans/refactor-auth.md"` | 計畫檔案的路徑。注入 |
2041| `allowedPrompts` | array | `[{"tool": "Bash", "prompt": "run tests"}]` | 已棄用。Claude Code 接受此欄位但會忽略它。在 v2.1.205 之前,它攜帶 Claude 為實作計畫而請求的基於提示詞的權限 |2067| `allowedPrompts` | array | `[{"tool": "Bash", "prompt": "run tests"}]` | 已棄用。Claude Code 會接受此欄位但予以忽略。在 v2.1.205 之前,它攜帶 Claude 為實作計畫所要求的以提示詞為基礎的權限 |
2042 2068
2043在 `PostToolUse` 中,`tool_response` 是一個物件,其 `plan` 和 `filePath` 欄位包含已核准的計畫,另外還有內部狀態旗標。請讀取 `tool_response.plan` 以取得計畫內容,而不要從磁碟重新讀取檔案。2069在 `PostToolUse` 中,`tool_response` 是一個物件,其中的 `plan` 和 `filePath` 欄位包含已核准的計畫,另外還有內部狀態旗標。請讀取 `tool_response.plan` 取得計畫內容,而不要從磁碟重新讀取檔案。
2044 2070
2045<h4 id="pretooluse-decision-control">2071<h4 id="pretooluse-decision-control">
2046 PreToolUse 決策控制2072 PreToolUse 決策控制
2047</h4>2073</h4>
2048 2074
2049`PreToolUse` hook 可以控制工具呼叫是否繼續。與其他使用頂層 `decision` 欄位的 hook 不同,PreToolUse 會在 `hookSpecificOutput` 物件內傳回其決策。這讓它擁有更豐富的控制:四種結果(允許、拒絕、詢問或延後),以及在執行前修改工具輸入的能力。2075`PreToolUse` hook 可以控制工具呼叫是否繼續。與其他使用頂層 `decision` 欄位的 hook 不同,PreToolUse 會在 `hookSpecificOutput` 物件內回傳其決策。這讓它擁有更豐富的控制:四種結果(允許、拒絕、詢問或延遲),以及在執行前修改工具輸入的能力。
2050 2076
2051| 欄位 | 說明 |2077| 欄位 | 說明 |
2052| :- | :- |2078| :- | :- |
2053| `permissionDecision` | `"allow"` 會略過權限提示,但[沒有任何模式會自動核准的動作](/docs/zh-TW/permission-modes#actions-no-mode-auto-approves)、[從網路路徑讀取](/docs/zh-TW/permissions#network-paths),以及需要[搭配 `updatedInput`](#allow-with-updatedinput) 的 `AskUserQuestion` 與 `ExitPlanMode` 除外。`"deny"` 會阻止工具呼叫。`"ask"` 會提示使用者確認。`"defer"` 會正常結束,讓工具稍後可以恢復。無論 hook 回傳什麼,[拒絕與詢問規則](/docs/zh-TW/permissions#manage-permissions)仍會被評估 |2079| `permissionDecision` | `"allow"` 會略過權限提示,但[沒有任何模式會自動核准的動作](/docs/zh-TW/permission-modes#actions-no-mode-auto-approves)、[從網路路徑讀取](/docs/zh-TW/permissions#network-paths),以及需要[搭配 `updatedInput`](#allow-with-updatedinput) 的 `AskUserQuestion` 和 `ExitPlanMode` 除外。`"deny"` 會阻止工具呼叫。`"ask"` 會提示使用者確認。`"defer"` 會正常結束,以便稍後恢復該工具。無論 hook 回傳什麼,[拒絕和詢問規則](/docs/zh-TW/permissions#manage-permissions)仍會被評估 |
2054| `permissionDecisionReason` | 對於 `"ask"`,會在權限提示中顯示給使用者。當 Claude Code 在無人能回應該提示的 `-p` 執行中[拒絕呼叫](/docs/zh-TW/headless#turn-off-permission-prompts-in-unattended-runs)時,Claude 會改在工具結果中讀取該原因。對於 `"deny"`,會顯示給 Claude。對於 `"allow"` 和 `"defer"`,只會寫入[除錯日誌](#debug-hooks) |2080| `permissionDecisionReason` | 對於 `"ask"`,會在權限提示中向使用者顯示。當 Claude Code 在沒有人能回應該提示的 `-p` 執行中[拒絕呼叫](/docs/zh-TW/headless#turn-off-permission-prompts-in-unattended-runs)時,Claude 會改為在工具結果中讀到原因。對於 `"deny"`,會向 Claude 顯示。對於 `"allow"` 和 `"defer"`,只會寫入[除錯日誌](#debug-hooks) |
2055| `updatedInput` | 在執行前修改工具的輸入參數。會取代整個輸入物件,因此請將未變更的欄位與修改過的欄位一併包含。Claude Code 會依據您的 hook 傳回的輸入(而非 Claude 傳送的輸入)評估權限規則以及 Bash 命令的[自動移至背景資格](/docs/zh-TW/tools-reference#foreground-commands-that-move-to-the-background)。搭配 `"allow"` 可自動核准,或搭配 `"ask"` 向使用者顯示修改後的輸入。對於 `"defer"` 會被忽略 |2081| `updatedInput` | 在執行前修改工具的輸入參數。會取代整個輸入物件,因此請將未變更的欄位與修改過的欄位一併包含。Claude Code 會根據您 hook 回傳的輸入(而非 Claude 傳送的輸入)評估權限規則,以及 Bash 命令的[自動移至背景資格](/docs/zh-TW/tools-reference#foreground-commands-that-move-to-the-background)。與 `"allow"` 搭配可自動核准,或與 `"ask"` 搭配向使用者顯示修改後的輸入。對於 `"defer"`,會被忽略 |
2056| `additionalContext` | 與工具結果一同加入 Claude 上下文的字串。當 `permissionDecision` 為 `"defer"` 時會被忽略。請參閱[為 Claude 加入上下文](#add-context-for-claude) |2082| `additionalContext` | 與工具結果一同加入 Claude 情境的字串。當 `permissionDecision` 為 `"defer"` 時會被忽略。請參閱[為 Claude 新增情境](#add-context-for-claude) |
2057 2083
2058當多個 PreToolUse hook 傳回不同的決策時,優先順序為 `deny` > `defer` > `ask` > `allow`。2084當多個 PreToolUse hook 回傳不同的決策時,優先順序為 `deny` > `defer` > `ask` > `allow`。
2059 2085
2060以退出碼 2 阻擋的 hook 與 `"deny"` 的處理方式相同:Claude 會將 stderr 訊息視為拒絕原因。2086以退出碼 2 阻擋的 hook,其處理方式與 `"deny"` 相同:Claude 會將 stderr 訊息視為拒絕原因。
2061 2087
2062當 hook 傳回 `"ask"` 時,顯示給使用者的權限提示會包含一個標示 hook 來源的標籤:來自任何設定檔或 agent frontmatter 的 hook 為 `[settings]`,外掛的 hook 為 `[plugin:<name>]`,來自 skill frontmatter 的 hook 則為 `[skill]`。這可協助使用者了解是哪個設定來源在請求確認。2088當 hook 回傳 `"ask"` 時,向使用者顯示的權限提示會包含一個標籤,指出該 hook 的來源:來自任何設定檔或 agent frontmatter 的 hook 為 `[settings]`,外掛的 hook 為 `[plugin:<name>]`,來自 skill frontmatter 的 hook 則為 `[skill]`。這有助於使用者了解是哪個設定來源在要求確認。
2063 2089
2064hook 的 `"ask"` 也會在[自動模式](/docs/zh-TW/permission-modes#eliminate-prompts-with-auto-mode)中強制顯示權限提示:分類器仍可拒絕工具呼叫,但無法在不提示的情況下核准該呼叫。在 v2.1.211 之前,分類器可以在不顯示 hook 所請求之提示的情況下,核准在[沙箱](/docs/zh-TW/sandboxing)外執行的 Bash 命令;分類器仍會對該命令套用自己的安全規則,而 hook 的 `"deny"` 一律會被遵守。2090hook 的 `"ask"` 也會在[自動模式](/docs/zh-TW/permission-modes#eliminate-prompts-with-auto-mode)中強制顯示權限提示:分類器仍可拒絕工具呼叫,但無法在不提示的情況下核准該呼叫。在 v2.1.211 之前,分類器可以在不顯示 hook 所要求之提示的情況下,核准在[沙箱](/docs/zh-TW/sandboxing)外執行的 Bash 命令;分類器仍會對該命令套用其自身的安全規則,而 hook 的 `"deny"` 一律會被遵守。
2065 2091
2066```json theme={null}2092```json theme={null}
2067{2093{
2078```2104```
2079 2105
2080<Note>2106<Note>
2081 PreToolUse 先前使用頂層的 `decision` 和 `reason` 欄位,但這些欄位在此事件中已棄用。請改用 `hookSpecificOutput.permissionDecision` 和 `hookSpecificOutput.permissionDecisionReason`。已棄用的值 `"approve"` 和 `"block"` 分別對應到 `"allow"` 和 `"deny"`。PostToolUse 和 Stop 等其他事件仍以頂層的 `decision` 和 `reason` 作為目前的格式。2107 PreToolUse 先前使用頂層的 `decision` 和 `reason` 欄位,但這些欄位在此事件中已棄用。請改用 `hookSpecificOutput.permissionDecision` 和 `hookSpecificOutput.permissionDecisionReason`。已棄用的值 `"approve"` 和 `"block"` 分別對應到 `"allow"` 和 `"deny"`。PostToolUse 和 Stop 等其他事件則繼續以頂層 `decision` 和 `reason` 作為其目前的格式。
2082</Note>2108</Note>
2083 2109
2084<h4 id="allow-with-updatedinput">2110<h4 id="allow-with-updatedinput">
2085 需要使用者互動的工具2111 需要使用者互動的工具
2086</h4>2112</h4>
2087 2113
2088`AskUserQuestion` 和 `ExitPlanMode` 需要使用者互動。在使用 `-p` 旗標的[非互動模式](/docs/zh-TW/headless)中,只有在執行具有可接收提示的[權限主機](/docs/zh-TW/headless#turn-off-permission-prompts-in-unattended-runs)(例如 Agent SDK 的 `canUseTool` 回呼)時,Claude Code 才會提供這些工具。2114`AskUserQuestion` 和 `ExitPlanMode` 需要使用者互動。在使用 `-p` 旗標的[非互動模式](/docs/zh-TW/headless)中,只有當執行具有可接收提示的[權限主機](/docs/zh-TW/headless#turn-off-permission-prompts-in-unattended-runs)(例如 Agent SDK 的 `canUseTool` 回呼)時,Claude Code 才會提供這些工具。
2089 2115
2090當 `PreToolUse` hook 執行下列動作時,即可滿足該需求:2116`PreToolUse` hook 在執行下列動作時即可滿足該需求:
2091 2117
20921. 從 stdin 讀取工具的輸入21181. 從 stdin 讀取工具的輸入
20932. 透過您自己的 UI 收集答案21192. 透過您自己的 UI 收集答案
20943. 傳回 `permissionDecision: "allow"`,並搭配包含答案的 `updatedInput`,讓工具在不提示的情況下執行21203. 回傳 `permissionDecision: "allow"`,並搭配包含答案的 `updatedInput`,讓工具在不提示的情況下執行
2095 2121
2096對這些工具而言,僅傳回 `"allow"` 是不夠的。2122對於這些工具,僅回傳 `"allow"` 是不夠的。
2097 2123
2098對於 `AskUserQuestion`,請回傳原始的 `questions` 陣列,並加入一個 [`answers`](#askuserquestion) 物件,將每個問題的文字對應到所選答案。此輸出以 `React` 回答一個問題:2124對於 `AskUserQuestion`,請回傳原始的 `questions` 陣列,並新增一個 [`answers`](#askuserquestion) 物件,將每個問題的文字對應到所選答案。此輸出以 `React` 回答一個問題:
2099 2125
2100```json theme={null}2126```json theme={null}
2101{2127{
2117}2143}
2118```2144```
2119 2145
2120伺服器以 [`_meta["anthropic/requiresUserInteraction"]`](/docs/zh-TW/mcp#require-approval-for-a-specific-tool) 標記的 MCP 工具則更為嚴格:無論是否搭配 `updatedInput`,hook 都無法以 `"allow"` 略過其核准提示,因為 Claude Code 無法確認 hook 已收集到該工具所需的互動。2146伺服器以 [`_meta["anthropic/requiresUserInteraction"]`](/docs/zh-TW/mcp#require-approval-for-a-specific-tool) 標記的 MCP 工具則更為嚴格:hook 無法以 `"allow"` 略過其核准提示,無論是否搭配 `updatedInput`,因為 Claude Code 無法確認 hook 已收集到該工具所需的互動。
2121 2147
2122<h4 id="defer-a-tool-call-for-later">2148<h4 id="defer-a-tool-call-for-later">
2123 延後工具呼叫2149 將工具呼叫延遲到稍後
2124</h4>2150</h4>
2125 2151
2126`"defer"` 適用於以子程序方式執行 `claude -p` 並讀取其 JSON 輸出的整合,例如 Agent SDK 應用程式或建構在 Claude Code 之上的自訂 UI。它讓呼叫端程序可以在工具呼叫處暫停 Claude、透過自己的介面收集輸入,然後從中斷處恢復。Claude Code 只在使用 `-p` 旗標的[非互動模式](/docs/zh-TW/headless)中採用此值。在互動式工作階段中,它會記錄警告並忽略 hook 結果。2152`"defer"` 適用於以子程序方式執行 `claude -p` 並讀取其 JSON 輸出的整合,例如 Agent SDK 應用程式或建構在 Claude Code 之上的自訂 UI。它讓呼叫端程序可以在工具呼叫處暫停 Claude、透過自己的介面收集輸入,然後從中斷處恢復。Claude Code 只在使用 `-p` 旗標的[非互動模式](/docs/zh-TW/headless)中遵守此值。在互動式工作階段中,它會記錄警告並忽略 hook 結果。
2127 2153
2128`AskUserQuestion` 工具是典型的情況:Claude 想詢問使用者某件事,但沒有終端機可以回答。`-p` 執行只有在具有[權限主機](/docs/zh-TW/headless#turn-off-permission-prompts-in-unattended-runs)(例如您以 `--permission-prompt-tool` 傳入的 MCP 工具)時才會提供 `AskUserQuestion`,因此請以權限主機啟動執行。往返流程如下:2154`AskUserQuestion` 工具是典型的情況:Claude 想詢問使用者某件事,但沒有終端機可供回答。`-p` 執行只有在具有[權限主機](/docs/zh-TW/headless#turn-off-permission-prompts-in-unattended-runs)時才會提供 `AskUserQuestion`,例如您以 `--permission-prompt-tool` 傳入的 MCP 工具,因此請以此方式啟動執行。來回流程如下:
2129 2155
21301. Claude 呼叫 `AskUserQuestion`。`PreToolUse` hook 觸發。21561. Claude 呼叫 `AskUserQuestion`。`PreToolUse` hook 觸發。
21312. hook 傳回 `permissionDecision: "defer"`。工具不會執行。程序以 `stop_reason: "tool_deferred"` 結束,待處理的工具呼叫保留在逐字稿中。21572. hook 回傳 `permissionDecision: "defer"`。工具不會執行。程序以 `stop_reason: "tool_deferred"` 結束,待處理的工具呼叫保留在逐字稿中。
21323. 呼叫端程序從 SDK 結果中讀取 `deferred_tool_use`,在自己的 UI 中呈現問題,並等待答案。21583. 呼叫端程序從 SDK 結果讀取 `deferred_tool_use`,在自己的 UI 中呈現問題,並等待答案。
21334. 呼叫端程序以相同的權限主機執行 `claude -p --resume <session-id>`。同一個工具呼叫再次觸發 `PreToolUse`。21594. 呼叫端程序以相同的權限主機執行 `claude -p --resume <session-id>`。同一個工具呼叫再次觸發 `PreToolUse`。
21345. hook 傳回 `permissionDecision: "allow"`,並在 `updatedInput` 中附上答案。工具執行,Claude 繼續。21605. hook 回傳 `permissionDecision: "allow"`,並在 `updatedInput` 中附上答案。工具執行,Claude 繼續。
2135 2161
2136`deferred_tool_use` 欄位攜帶工具的 `id`、`name` 和 `input`。`input` 是 Claude 為工具呼叫產生的參數,在執行前擷取:2162`deferred_tool_use` 欄位攜帶工具的 `id`、`name` 和 `input`。`input` 是 Claude 為該工具呼叫產生的參數,在執行前擷取:
2137 2163
2138```json theme={null}2164```json theme={null}
2139{2165{
2149}2175}
2150```2176```
2151 2177
2152沒有逾時或重試次數限制。工作階段會保留在磁碟上直到您恢復它,但受 [`cleanupPeriodDays`](/docs/zh-TW/settings-reference#cleanupperioddays) 保留清理的約束,該清理預設會在 30 天後依照[保留清理規則](/docs/zh-TW/claude-directory#cleaned-up-automatically)刪除工作階段檔案。如果在您恢復時答案尚未準備好,hook 可以再次傳回 `"defer"`,程序會以相同方式結束。呼叫端程序最終透過 hook 傳回 `"allow"` 或 `"deny"` 來決定何時結束迴圈。2178沒有逾時或重試次數限制。工作階段會保留在磁碟上直到您恢復它,但受 [`cleanupPeriodDays`](/docs/zh-TW/settings-reference#cleanupperioddays) 保留期清理的約束,該清理預設會在 30 天後依照[保留期清理規則](/docs/zh-TW/claude-directory#cleaned-up-automatically)刪除工作階段檔案。若恢復時答案尚未準備好,hook 可以再次回傳 `"defer"`,程序會以相同方式結束。呼叫端程序最終從 hook 回傳 `"allow"` 或 `"deny"`,藉此控制何時跳出迴圈。
2153 2179
2154`"defer"` 只在 Claude 於該回合中進行單一工具呼叫時有效。如果 Claude 一次進行多個工具呼叫,`"defer"` 會被忽略並發出警告,工具則透過一般權限流程繼續進行。此限制的存在是因為恢復時只能重新執行一個工具:無法在不讓其他呼叫處於未解決狀態的情況下,延後一批呼叫中的某一個。2180`"defer"` 只在 Claude 於該回合中進行單一工具呼叫時有效。若 Claude 同時進行多個工具呼叫,`"defer"` 會被忽略並顯示警告,工具則會經由一般的權限流程繼續。此限制的原因在於恢復時只能重新執行一個工具:無法在不讓其他呼叫懸而未決的情況下,延遲一批呼叫中的其中一個。
2155 2181
2156如果在您恢復時延後的工具已無法使用,程序會在 hook 觸發前以 `stop_reason: "tool_deferred_unavailable"` 和 `is_error: true` 結束。當提供該工具的 MCP 伺服器未在恢復的工作階段中連線時,就會發生這種情況。`deferred_tool_use` payload 仍會包含在內,讓您可以識別是哪個工具遺失了。2182若恢復時延遲的工具已不可用,程序會在 hook 觸發前以 `stop_reason: "tool_deferred_unavailable"` 和 `is_error: true` 結束。當提供該工具的 MCP 伺服器在恢復的工作階段中未連線時,就會發生這種情況。`deferred_tool_use` payload 仍會包含在內,讓您能辨識是哪個工具遺失了。
2157 2183
2158<Note>2184<Note>
2159 若要在 plan mode 中恢復延後的工作階段,請將 [`--permission-prompt-tool`](/docs/zh-TW/cli-reference#cli-flags) 與 `--resume` 一起傳入,讓 Claude Code 能呈現計畫以供核准。其他條件請參閱[以 `-p` 在 plan mode 中恢復](/docs/zh-TW/sessions#resume-in-plan-mode-with-p)。需要 Claude Code v2.1.246 或更新版本。2185 若要在 plan mode 中恢復延遲的工作階段,請將 [`--permission-prompt-tool`](/docs/zh-TW/cli-reference#cli-flags) 與 `--resume` 一起傳入,讓 Claude Code 能呈現計畫以供核准。其他條件請參閱[以 `-p` 在 plan mode 中恢復](/docs/zh-TW/sessions#resume-in-plan-mode-with-p)。需要 Claude Code v2.1.246 或更新版本。
2160 2186
2161 當您以 `-p` 恢復時,Claude Code 不會還原任何其他已儲存的權限模式。它會以新的 `claude -p` 執行所使用的權限模式啟動執行,因此如果延後的工作階段使用了 `--permission-mode` 或 `--dangerously-skip-permissions`,請再次傳入。當您以不含 `-p` 的 `claude --resume <session-id>` 恢復時,Claude Code 會還原已儲存的權限模式,例外情況列於[恢復時的權限模式](/docs/zh-TW/sessions#permission-mode-on-resume)。2187 當您以 `-p` 恢復時,Claude Code 不會還原任何其他已儲存的權限模式。它會以新的 `claude -p` 執行所使用的權限模式啟動,因此若延遲的工作階段使用了 `--permission-mode` 或 `--dangerously-skip-permissions`,請再次傳入。當您不使用 `-p`、以 `claude --resume <session-id>` 恢復時,Claude Code 會還原已儲存的權限模式,例外情況列於[恢復時的權限模式](/docs/zh-TW/sessions#permission-mode-on-resume)。
2162</Note>2188</Note>
2163 2189
2164<h3 id="permissionrequest">2190<h3 id="permissionrequest">
2165 PermissionRequest2191 PermissionRequest
2166</h3>2192</h3>
2167 2193
2168在 Claude Code 即將向您請求使用工具的權限時執行。在無法顯示提示的工作階段中,例如[非互動模式](/docs/zh-TW/headless)中的背景 subagent,Claude Code 仍會執行這些 hook,而如果沒有任何 hook 傳回決策,它會拒絕該工具呼叫。對於送達 `--permission-prompt-tool` 或 Agent SDK [`canUseTool` 回呼](/docs/zh-TW/agent-sdk/permissions)的呼叫,hook 會與您的主機並行執行,以先做出決定者為準。2194在 Claude Code 即將向您要求使用工具的權限時執行。在無法顯示提示的工作階段中,例如[非互動模式](/docs/zh-TW/headless)中的背景 subagent,Claude Code 仍會執行這些 hook,若沒有 hook 回傳決策,它會拒絕該工具呼叫。對於傳達到 `--permission-prompt-tool` 或 Agent SDK 的 [`canUseTool` 回呼](/docs/zh-TW/agent-sdk/permissions)的呼叫,hook 會與您的主機並行執行,並以先做出決定者為準。
2169使用 [PermissionRequest 決策控制](#permissionrequest-decision-control)代表使用者允許或拒絕。2195使用 [PermissionRequest 決策控制](#permissionrequest-decision-control)代表使用者允許或拒絕。
2170 2196
2171當您需要在 Claude 請求使用工具權限的當下取得訊號時,請使用此事件。Claude Code 只會在提示等待約六秒之後,才執行 `permission_prompt` 類型的 [Notification](#notification) hook。2197當您需要在 Claude 要求使用工具權限的當下取得訊號時,請使用此事件。Claude Code 只會在提示已等待約六秒後,才執行 `permission_prompt` 類型的 [Notification](#notification) hook。
2172 2198
2173Claude Code 不會針對沙箱化命令的[網路請求](/docs/zh-TW/sandboxing#network-isolation)執行 PermissionRequest hook。若要取得該提示的訊號,請使用 `permission_prompt` 通知類型。2199Claude Code 不會針對沙箱化命令的[網路請求](/docs/zh-TW/sandboxing#network-isolation)執行 PermissionRequest hook。若要取得該提示的訊號,請使用 `permission_prompt` 通知類型。
2174 2200
2178 PermissionRequest 輸入2204 PermissionRequest 輸入
2179</h4>2205</h4>
2180 2206
2181PermissionRequest hook 與 PreToolUse hook 一樣會接收 `tool_name` 和 `tool_input` 欄位,但沒有 `tool_use_id`。對於 MCP 工具,它們也會接收 [`mcp_server`](#pretooluse-input) 物件。選用的 `permission_suggestions` 陣列包含 Claude Code 針對此請求建議的[權限更新](#permission-update-entries),例如新增允許規則或變更權限模式。2207PermissionRequest hook 會接收 `tool_name` 與 `tool_input` 欄位,與 PreToolUse hook 相同,但不含 `tool_use_id`。對於 MCP 工具,它們也會接收 [`mcp_server`](#pretooluse-input) 物件。選用的 `permission_suggestions` 陣列包含 Claude Code 針對此請求建議的[權限更新](#permission-update-entries),例如新增允許規則或變更權限模式。
2182 2208
2183`permission_suggestions` 陣列並不是您所看到選項的確切清單,因為每個權限對話方塊都會建立自己的選項。某些對話方塊(例如檔案編輯的對話方塊)完全不讀取此陣列,而是從請求本身衍生選項。會讀取此陣列的對話方塊仍可能隱藏某個其建議仍保留在陣列中的選項,例如當 [`allowManagedPermissionRulesOnly`](/docs/zh-TW/settings-reference#allowmanagedpermissionrulesonly) 隱藏儲存規則的選項時。它也可能提供沒有對應建議項目的選項,例如 [**Yes, and switch to auto mode**](/docs/zh-TW/permission-modes#switch-permission-modes),它會直接變更權限模式,而不是透過權限更新。2209`permission_suggestions` 陣列並非您所看到選項的精確清單,因為每個權限對話框會自行建構其選項。有些對話框(例如用於檔案編輯的對話框)完全不讀取此陣列,而是從請求本身推導出選項。會讀取此陣列的對話框,仍可能隱藏某個建議仍保留在陣列中的選項,例如當 [`allowManagedPermissionRulesOnly`](/docs/zh-TW/settings-reference#allowmanagedpermissionrulesonly) 隱藏儲存規則的選項時。它也可能提供沒有對應建議項目的選項,例如 [**Yes, and switch to auto mode**](/docs/zh-TW/permission-modes#switch-permission-modes),此選項會直接變更權限模式,而非透過權限更新。
2184 2210
2185PreToolUse hook 會在每次工具呼叫之前執行,無論是否需要權限。PermissionRequest hook 只在 Claude Code 即將向您請求權限時執行,或在它原本會自動拒絕無法提示的呼叫時執行。這兩個事件都不會針對 [`EndConversation`](/docs/zh-TW/tools-reference#endconversation-tool-behavior) 觸發。2211PreToolUse hook 會在每次工具呼叫之前執行,無論是否需要權限。PermissionRequest hook 只會在 Claude Code 即將向您請求權限時執行,或在它原本會自動拒絕某個無法提示的呼叫時執行。這兩個事件都不會針對 [`EndConversation`](/docs/zh-TW/tools-reference#endconversation-tool-behavior) 觸發。
2186 2212
2187```json theme={null}2213```json theme={null}
2188{2214{
2211 PermissionRequest 決策控制2237 PermissionRequest 決策控制
2212</h4>2238</h4>
2213 2239
2214`PermissionRequest` hook 可以允許或拒絕權限請求。除了所有 hook 都可使用的 [JSON 輸出欄位](#json-output)之外,您的 hook 指令碼還可以傳回包含下列事件專屬欄位的 `decision` 物件:2240`PermissionRequest` hook 可以允許或拒絕權限請求。除了所有 hook 都可使用的 [JSON 輸出欄位](#json-output)之外,您的 hook 指令碼還可以回傳包含以下事件專屬欄位的 `decision` 物件:
2215 2241
2216| 欄位 | 說明 |2242| 欄位 | 說明 |
2217| :- | :- |2243| :- | :- |
2218| `behavior` | `"allow"` 授予權限,`"deny"` 拒絕權限。[拒絕和詢問規則](/docs/zh-TW/permissions#manage-permissions)仍會被評估,因此傳回 `"allow"` 的 hook 不會覆寫相符的拒絕規則 |2244| `behavior` | `"allow"` 授予權限,`"deny"` 拒絕權限。[拒絕與詢問規則](/docs/zh-TW/permissions#manage-permissions)仍會被評估,因此回傳 `"allow"` 的 hook 不會覆寫相符的拒絕規則 |
2219| `updatedInput` | 僅適用於 `"allow"`:在執行前修改工具的輸入參數。會取代整個輸入物件,因此請將未變更的欄位與修改過的欄位一併包含。修改後的輸入會再次依據拒絕和詢問規則評估 |2245| `updatedInput` | 僅適用於 `"allow"`:在執行前修改工具的輸入參數。會取代整個輸入物件,因此請將未變更的欄位與修改過的欄位一併包含。修改後的輸入會再次依據拒絕與詢問規則進行評估 |
2220| `updatedPermissions` | 僅適用於 `"allow"`:要套用的[權限更新項目](#permission-update-entries)陣列,例如新增允許規則或變更工作階段權限模式 |2246| `updatedPermissions` | 僅適用於 `"allow"`:要套用的[權限更新項目](#permission-update-entries)陣列,例如新增允許規則或變更工作階段的權限模式 |
2221| `message` | 僅適用於 `"deny"`:告訴 Claude 權限被拒絕的原因 |2247| `message` | 僅適用於 `"deny"`:告訴 Claude 權限被拒絕的原因 |
2222| `interrupt` | 僅適用於 `"deny"`:若為 `true`,則停止 Claude |2248| `interrupt` | 僅適用於 `"deny"`:若為 `true`,則停止 Claude |
2223 2249
2224以退出碼 2 結束但沒有 `decision` 物件的 hook 不會改變權限流程,其 stderr 會被捨棄。若要授予或拒絕請求,請回傳 `decision` 物件。2250以退出碼 2 結束但未提供 `decision` 物件的 hook 不會改變權限流程,且其 stderr 會被捨棄。若要授予或拒絕請求,請回傳 `decision` 物件。
2225 2251
2226```json theme={null}2252```json theme={null}
2227{2253{
2241 權限更新項目2267 權限更新項目
2242</h4>2268</h4>
2243 2269
2244`updatedPermissions` 輸出欄位與 [`permission_suggestions` 輸入欄位](#permissionrequest-input)都使用相同的項目物件陣列。每個項目都有一個 `type`,用來決定其他欄位,以及一個 `destination`,用來控制變更寫入的位置。2270`updatedPermissions` 輸出欄位與 [`permission_suggestions` 輸入欄位](#permissionrequest-input)都使用相同的項目物件陣列。每個項目都有一個決定其他欄位的 `type`,以及一個控制變更寫入位置的 `destination`。
2245 2271
2246| `type` | 欄位 | 效果 |2272| `type` | 欄位 | 效果 |
2247| :- | :- | :- |2273| :- | :- | :- |
2248| `addRules` | `rules`、`behavior`、`destination` | 新增權限規則。`rules` 是由 `{toolName, ruleContent?}` 物件組成的陣列。省略 `ruleContent` 即可比對整個工具。`behavior` 為 `"allow"`、`"deny"` 或 `"ask"` |2274| `addRules` | `rules`、`behavior`、`destination` | 新增權限規則。`rules` 是 `{toolName, ruleContent?}` 物件的陣列。省略 `ruleContent` 即可比對整個工具。`behavior` 為 `"allow"`、`"deny"` 或 `"ask"` |
2249| `replaceRules` | `rules`、`behavior`、`destination` | 以提供的 `rules` 取代 `destination` 中指定 `behavior` 的所有規則 |2275| `replaceRules` | `rules`、`behavior`、`destination` | 以提供的 `rules` 取代 `destination` 中指定 `behavior` 的所有規則 |
2250| `removeRules` | `rules`、`behavior`、`destination` | 移除指定 `behavior` 中相符的規則 |2276| `removeRules` | `rules`、`behavior`、`destination` | 移除指定 `behavior` 的相符規則 |
2251| `setMode` | `mode`、`destination` | 變更權限模式。有效的模式為 `default`、`auto`、`acceptEdits`、`dontAsk`、`bypassPermissions`、`plan`,以及作為 `default` 別名的 `manual` |2277| `setMode` | `mode`、`destination` | 變更權限模式。有效的模式為 `default`、`auto`、`acceptEdits`、`dontAsk`、`bypassPermissions`、`plan`,以及作為 `default` 別名的 `manual` |
2252| `addDirectories` | `directories`、`destination` | 新增工作目錄。`directories` 是由路徑字串組成的陣列 |2278| `addDirectories` | `directories`、`destination` | 新增工作目錄。`directories` 是路徑字串的陣列 |
2253| `removeDirectories` | `directories`、`destination` | 移除工作目錄 |2279| `removeDirectories` | `directories`、`destination` | 移除工作目錄 |
2254 2280
2255<Note>2281<Note>
2256 只有在啟動工作階段時已可使用略過模式的情況下,帶有 `bypassPermissions` 的 `setMode` 才會生效:`--dangerously-skip-permissions`、`--permission-mode bypassPermissions`、`--allow-dangerously-skip-permissions`,或是在[使用者設定、`--settings` 或受管設定](/docs/zh-TW/settings-reference#permissions-defaultmode)中設定 `permissions.defaultMode: "bypassPermissions"`。否則此更新不會產生任何作用。當 [`permissions.disableBypassPermissionsMode`](/docs/zh-TW/permissions#managed-settings) 停用該模式,或工作階段以[受限模式](/docs/zh-TW/cli-reference#cli-flags)啟動時,此更新同樣不會產生任何作用。2282 帶有 `bypassPermissions` 的 `setMode` 只有在您啟動工作階段時已可使用略過模式的情況下才會生效:`--dangerously-skip-permissions`、`--permission-mode bypassPermissions`、`--allow-dangerously-skip-permissions`,或在[使用者、`--settings` 或受管設定](/docs/zh-TW/settings-reference#permissions-defaultmode)中設定 `permissions.defaultMode: "bypassPermissions"`。否則此更新不會產生任何作用。當 [`permissions.disableBypassPermissionsMode`](/docs/zh-TW/permissions#managed-settings) 停用此模式,或工作階段以[受限模式](/docs/zh-TW/cli-reference#cli-flags)啟動時,此更新同樣不會產生任何作用。
2257 2283
2258 無論 `destination` 為何,`bypassPermissions` 都不會被保存為 `defaultMode`。2284 無論 `destination` 為何,`bypassPermissions` 都不會被保存為 `defaultMode`。
2259</Note>2285</Note>
2262 2288
2263| `destination` | 寫入位置 |2289| `destination` | 寫入位置 |
2264| :- | :- |2290| :- | :- |
2265| `session` | 僅存在於記憶體中,工作階段結束時捨棄 |2291| `session` | 僅在記憶體中,工作階段結束時捨棄 |
2266| `localSettings` | `.claude/settings.local.json` |2292| `localSettings` | `.claude/settings.local.json` |
2267| `projectSettings` | `.claude/settings.json` |2293| `projectSettings` | `.claude/settings.json` |
2268| `userSettings` | `~/.claude/settings.json` |2294| `userSettings` | `~/.claude/settings.json` |
2269 2295
2270hook 可以將收到的其中一個 `permission_suggestions` 原樣回傳,作為自己的 `updatedPermissions` 輸出。2296hook 可以將其接收到的其中一個 `permission_suggestions` 作為自己的 `updatedPermissions` 輸出回傳。
2271 2297
2272<h3 id="posttooluse">2298<h3 id="posttooluse">
2273 PostToolUse2299 PostToolUse
2275 2301
2276在工具成功完成後立即執行。2302在工具成功完成後立即執行。
2277 2303
2278依工具名稱比對,可用值與 PreToolUse 相同。2304依工具名稱比對,值與 PreToolUse 相同。
2279 2305
2280當工具名稱不是適合的篩選條件時,可以更廣泛地比對:2306當工具名稱不是合適的篩選條件時,可使用更廣泛的比對方式:
2281 2307
2282* 若要在任何工具成功完成後執行 hook,請省略 `matcher` 或將其設為 `"*"`。接著您的 hook 可以自行找出變更內容,例如執行 `git status --porcelain`,它也會列出 `git diff` 遺漏的未追蹤檔案。對於失敗的工具呼叫,請在 [PostToolUseFailure](#posttoolusefailure) 下新增相同的 hook。2308* 若要在任何工具成功完成後執行 hook,請省略 `matcher` 或將其設為 `"*"`。接著您的 hook 可以自行找出變更內容,例如執行 `git status --porcelain`,它也會列出 `git diff` 遺漏的未追蹤檔案。對於失敗的工具呼叫,請在 [PostToolUseFailure](#posttoolusefailure) 下加入相同的 hook。
2283* 若要在特定檔案於磁碟上變更時執行 hook(無論是誰寫入的),請使用 [FileChanged](#filechanged)。當 `Bash` 命令或 Claude Code 之外的程序重寫同一個檔案時,Claude Code 不會執行比對 `Edit|Write` 的 `PostToolUse` hook。2309* 若要在特定檔案於磁碟上變更時執行 hook(不論是由誰寫入),請使用 [FileChanged](#filechanged)。當 `Bash` 命令或 Claude Code 以外的程序重寫同一個檔案時,Claude Code 不會執行比對 `Edit|Write` 的 `PostToolUse` hook。
2284 2310
2285<h4 id="posttooluse-input">2311<h4 id="posttooluse-input">
2286 PostToolUse 輸入2312 PostToolUse 輸入
2287</h4>2313</h4>
2288 2314
2289`PostToolUse` hook 會在工具已成功執行後觸發。輸入同時包含 `tool_input`(傳送給工具的引數)與 `tool_response`(工具回傳的結果)。兩者的確切 schema 取決於工具。檔案工具的 `tool_input` 路徑格式與 [PreToolUse](#pretooluse-input) 相同:一律為絕對路徑,並使用平台原生的分隔符號,因此在 Windows 上為反斜線。若為 MCP 工具,輸入中也會帶有 [`mcp_server`](#pretooluse-input) 物件。2315`PostToolUse` hook 會在工具已成功執行後觸發。輸入同時包含 `tool_input`(傳送給工具的引數)與 `tool_response`(工具回傳的結果)。兩者的確切 schema 取決於工具。檔案工具的 `tool_input` 路徑格式與 [PreToolUse](#pretooluse-input) 相同:一律為絕對路徑,並使用平台原生的分隔符號,因此在 Windows 上為反斜線。對於 MCP 工具,輸入也會攜帶 [`mcp_server`](#pretooluse-input) 物件。
2290 2316
2291```json theme={null}2317```json theme={null}
2292{2318{
2311 2337
2312| 欄位 | 說明 |2338| 欄位 | 說明 |
2313| :- | :- |2339| :- | :- |
2314| `duration_ms` | 選用。工具執行時間(毫秒)。不包含權限提示與 PreToolUse hook 所花費的時間 |2340| `duration_ms` | 選用。工具執行時間(毫秒)。不包含花在權限提示與 PreToolUse hook 上的時間 |
2315 2341
2316<h4 id="posttooluse-decision-control">2342<h4 id="posttooluse-decision-control">
2317 PostToolUse 決策控制2343 PostToolUse 決策控制
2318</h4>2344</h4>
2319 2345
2320`PostToolUse` hook 可以在工具執行後向 Claude 提供回饋。除了所有 hook 皆可使用的 [JSON 輸出欄位](#json-output)外,您的 hook 指令碼還可以回傳下列事件專屬欄位:2346`PostToolUse` hook 可以在工具執行後向 Claude 提供回饋。除了所有 hook 都可使用的 [JSON 輸出欄位](#json-output)之外,您的 hook 指令碼還可以回傳以下事件專屬欄位:
2321 2347
2322| 欄位 | 說明 |2348| 欄位 | 說明 |
2323| :- | :- |2349| :- | :- |
2324| `decision` | `"block"` 會將 `reason` 附加在工具結果旁。Claude 仍會看到原始輸出;若要取代它,請使用 `updatedToolOutput` |2350| `decision` | `"block"` 會在工具結果旁加入 `reason`。Claude 仍會看到原始輸出;若要取代輸出,請使用 `updatedToolOutput` |
2325| `reason` | 當 `decision` 為 `"block"` 時向 Claude 顯示的說明 |2351| `reason` | 當 `decision` 為 `"block"` 時向 Claude 顯示的說明 |
2326| `additionalContext` | 與工具結果一起加入 Claude 上下文的字串。請參閱[為 Claude 新增上下文](#add-context-for-claude) |2352| `additionalContext` | 與工具結果一併加入 Claude 上下文的字串。請參閱[為 Claude 新增上下文](#add-context-for-claude) |
2327| `classifierContext` | 針對此次呼叫結果的簡短註記,提供給[自動模式](/docs/zh-TW/permission-modes#eliminate-prompts-with-auto-mode)分類器而非 Claude。請參閱[為自動模式分類器註記結果](#annotate-a-result-for-the-auto-mode-classifier)。需要 Claude Code v2.1.236 或更新版本 |2353| `classifierContext` | 關於此呼叫結果的簡短註記,提供給[自動模式](/docs/zh-TW/permission-modes#eliminate-prompts-with-auto-mode)分類器而非 Claude。請參閱[為自動模式分類器註記結果](#annotate-a-result-for-the-auto-mode-classifier)。需要 Claude Code v2.1.236 或更新版本 |
2328| `updatedToolOutput` | 在工具輸出傳送給 Claude 之前,以提供的值取代該輸出。此值必須符合工具的輸出結構 |2354| `updatedToolOutput` | 在將工具輸出傳送給 Claude 之前,以提供的值取代。該值必須符合工具的輸出結構 |
2329| `updatedMCPToolOutput` | 僅取代 [MCP 工具](#match-mcp-tools)的輸出。建議改用適用於所有工具的 `updatedToolOutput` |2355| `updatedMCPToolOutput` | 僅取代 [MCP 工具](#match-mcp-tools)的輸出。建議改用適用於所有工具的 `updatedToolOutput` |
2330 2356
2331以下範例會取代 `Bash` 呼叫的輸出。取代值符合 `Bash` 工具的輸出結構:2357以下範例取代了 `Bash` 呼叫的輸出。取代值符合 `Bash` 工具的輸出結構:
2332 2358
2333```json theme={null}2359```json theme={null}
2334{2360{
2346```2372```
2347 2373
2348<Warning>2374<Warning>
2349 `updatedToolOutput` 只會改變 Claude 看到的內容。hook 觸發時工具已經執行完畢,因此任何已寫入的檔案、已執行的命令或已傳送的網路請求都已經生效。OpenTelemetry 工具 span 與分析事件等遙測資料也會在 hook 執行前擷取原始輸出。若要在工具呼叫執行前阻止或修改它,請改用 [PreToolUse](#pretooluse) hook。2375 `updatedToolOutput` 只會改變 Claude 看到的內容。在 hook 觸發時工具早已執行,因此任何寫入的檔案、執行的命令或傳送的網路請求都已生效。OpenTelemetry 工具 span 與分析事件等遙測資料也會在 hook 執行前擷取原始輸出。若要在工具呼叫執行前加以阻止或修改,請改用 [PreToolUse](#pretooluse) hook。
2350 2376
2351 取代值必須符合工具的輸出結構。內建工具回傳的是結構化物件,而非純字串。例如,`Bash` 回傳的物件包含 `stdout`、`stderr`、`interrupted` 與 `isImage` 欄位。對於內建工具,不符合工具輸出 schema 的值會被忽略,並改用原始輸出。MCP 工具的輸出則會直接傳遞,不經 schema 驗證。移除 Claude 需要的錯誤細節,可能導致它基於錯誤的假設繼續進行。2377 取代值必須符合工具的輸出結構。內建工具回傳的是結構化物件而非純字串。例如,`Bash` 回傳的物件包含 `stdout`、`stderr`、`interrupted` 與 `isImage` 欄位。對於內建工具,不符合工具輸出 schema 的值會被忽略,並改用原始輸出。MCP 工具的輸出會直接傳遞,不進行 schema 驗證。移除 Claude 所需的錯誤細節,可能導致它基於錯誤的假設繼續進行。
2352</Warning>2378</Warning>
2353 2379
2354<h4 id="annotate-a-result-for-the-auto-mode-classifier">2380<h4 id="annotate-a-result-for-the-auto-mode-classifier">
2355 為自動模式分類器註記結果2381 為自動模式分類器註記結果
2356</h4>2382</h4>
2357 2383
2358回傳 `classifierContext`,即可將關於工具呼叫結果的簡短註記傳送給[自動模式](/docs/zh-TW/permission-modes#eliminate-prompts-with-auto-mode)分類器,而非傳送給 Claude。分類器[永遠不會收到工具結果本身](/docs/zh-TW/permission-modes#how-the-classifier-evaluates-actions),因此這個欄位是在分類器審查後續動作之前,告知它某次呼叫回傳了什麼的受支援方式。此欄位需要 Claude Code v2.1.236 或更新版本。2384回傳 `classifierContext`,即可將關於工具呼叫結果的簡短註記傳送給[自動模式](/docs/zh-TW/permission-modes#eliminate-prompts-with-auto-mode)分類器,而非傳送給 Claude。分類器[永遠不會接收工具結果本身](/docs/zh-TW/permission-modes#how-the-classifier-evaluates-actions),因此此欄位是在分類器審查後續動作之前,告知它呼叫回傳內容的受支援方式。此欄位需要 Claude Code v2.1.236 或更新版本。
2359 2385
2360以下範例告知分類器某個查詢輸出的來源:2386以下範例告訴分類器查詢輸出的來源:
2361 2387
2362```json theme={null}2388```json theme={null}
2363{2389{
2368}2394}
2369```2395```
2370 2396
2371分類器對此註記的重視程度,取決於您在何處設定該 hook:2397分類器對該註記的重視程度,取決於您在何處設定 hook:
2372 2398
2373* **在 Claude Code 中設定的 hook**:對於來自設定檔、外掛、skill 與 agent frontmatter 的 hook,分類器會將註記視為未經驗證、由應用程式提供的上下文。註記永遠不會確立使用者意圖;若註記聲稱您核准或要求了某件事,分類器會將該聲明與您在對話中的實際訊息進行核對2399* **在 Claude Code 中設定的 hook**:對於來自設定檔、外掛、skill 與 agent frontmatter 的 hook,分類器會將註記視為未經驗證、由應用程式提供的上下文。註記永遠無法確立使用者意圖;若註記聲稱您核准或要求了某件事,分類器會將該聲明與您在對話中的訊息進行比對
2374* **程序內的 Agent SDK 回呼**:當嵌入 Claude Code 的應用程式將 hook 註冊為 [TypeScript SDK 回呼](/docs/zh-TW/agent-sdk/hooks),並在即時工作階段期間回傳註記時,分類器可能會將註記中轉述的使用者陳述視為使用者意圖。這類陳述可以滿足分類器原本會接受來自您訊息的同意要求,但它永遠無法解除您自己的訊息也無法解除的封鎖。工作階段恢復後,Claude Code 會將還原的註記視為未經驗證的上下文。當兩類來源的 hook 都為同一次呼叫加上註記時,分類器會將合併後的註記視為未經驗證2400* **程序內的 Agent SDK 回呼**:當嵌入 Claude Code 的應用程式將 hook 註冊為 [TypeScript SDK 回呼](/docs/zh-TW/agent-sdk/hooks),並在即時工作階段期間回傳註記時,分類器可能會將註記中轉述的使用者陳述視為使用者意圖。此類陳述可以滿足分類器原本會接受您所傳送訊息作為依據的同意要求,但永遠無法解除您自己的訊息也無法解除的封鎖。工作階段恢復後,Claude Code 會將還原的註記視為未經驗證的上下文。當兩類 hook 都對同一個呼叫進行註記時,分類器會將合併後的註記視為未經驗證
2375 2401
2376Claude Code 在傳遞註記時會套用下列限制:2402Claude Code 在傳遞註記時會套用以下限制:
2377 2403
2378* **長度**:Claude Code 將單一工具呼叫的註記上限設為 2,000 個字元,超出部分會被截斷。此上限由回應該呼叫的所有 hook 共用2404* **長度**:Claude Code 將單一工具呼叫的註記上限設為 2,000 個字元,並截斷其餘部分。此上限由回應該呼叫的所有 hook 共用
2379* **僅限同步回應**:對於[在背景執行](#run-hooks-in-the-background)的 hook,Claude Code 會忽略其回應中的此欄位,因為該回應會在 Claude Code 記錄工具結果之後才抵達2405* **僅限同步回應**:Claude Code 會忽略[在背景執行](#run-hooks-in-the-background)之 hook 回應中的此欄位,因為該回應會在 Claude Code 記錄工具結果之後才抵達
2380* **分類器不記錄的呼叫**:分類器的逐字稿會省略唯讀查詢,例如檔案讀取與搜尋。附加在這類呼叫上的註記會被 Claude Code 捨棄2406* **分類器不記錄的呼叫**:分類器的逐字稿會省略唯讀查詢,例如檔案讀取與搜尋。附加在這些呼叫上的註記會被 Claude Code 捨棄
2381* **與改寫的互動**:當註記描述的是您以 `updatedToolOutput` 取代的輸出時,請在同一個 hook 回應中回傳這兩個欄位。若該改寫遭到拒絕,或被另一個 hook 的改寫取代,Claude Code 會捨棄該註記。若您回傳註記時未搭配改寫,即使另一個 hook 改寫了輸出,Claude Code 仍會傳遞該註記2407* **與重寫的互動**:當註記描述的是您以 `updatedToolOutput` 取代的輸出時,請在同一個 hook 回應中同時回傳這兩個欄位。若該重寫遭拒或被其他 hook 的重寫取代,Claude Code 會捨棄該註記。若您回傳註記時未進行重寫,即使有其他 hook 重寫了輸出,Claude Code 仍會傳遞該註記
2382 2408
2383<Warning>2409<Warning>
2384 分類器會將您放在 `classifierContext` 中的內容視為來自託管該工作階段之應用程式的資訊,因此請勿將不受信任的工具輸出或第三方文字複製到其中。請將註記限定為關於這一次呼叫的簡短斷言,例如關於其來源的事實,或使用者對此呼叫的陳述;請勿使用此欄位傳遞無關的訊息或一連串事件。2410 分類器會將您放入 `classifierContext` 的內容視為來自承載工作階段之應用程式的資訊,因此請勿將不受信任的工具輸出或第三方文字複製到其中。請將註記限縮為關於此單一呼叫的簡短陳述,例如其來源的事實或使用者對其的陳述;請勿使用此欄位傳遞不相關的訊息或一連串事件。
2385</Warning>2411</Warning>
2386 2412
2387<h3 id="posttoolusefailure">2413<h3 id="posttoolusefailure">
2388 PostToolUseFailure2414 PostToolUseFailure
2389</h3>2415</h3>
2390 2416
2391在已開始執行的工具失敗時執行:工具拋出錯誤,或 MCP 工具回傳錯誤結果。可用來記錄失敗、傳送警示,或向 Claude 提供修正性回饋。2417在已開始執行的工具失敗時執行:工具擲出錯誤,或 MCP 工具回傳錯誤結果。可用於記錄失敗、傳送警示,或向 Claude 提供修正回饋。
2392 2418
2393依工具名稱比對,可用值與 PreToolUse 相同。2419依工具名稱比對,值與 PreToolUse 相同。
2394 2420
2395<Note>2421<Note>
2396 對於在執行前就被拒絕的工具呼叫,此事件不會觸發:未知的工具名稱、未通過 schema 或工具專屬驗證的輸入,或權限遭拒。驗證拒絕會以 `tool_use_error` 結果回傳,且發生在 hook 執行之前,因此既不會觸發 `PreToolUse`,也不會觸發 `PostToolUseFailure`。權限遭拒會觸發 `PreToolUse`,但不會觸發此事件;請參閱 [PermissionDenied](#permissiondenied)。2422 此事件不會針對執行前就被拒絕的工具呼叫觸發:未知的工具名稱、未通過 schema 或工具專屬驗證的輸入,或權限拒絕。驗證拒絕會以 `tool_use_error` 結果回傳,且發生在 hook 執行之前,因此既不會觸發 `PreToolUse`,也不會觸發 `PostToolUseFailure`。權限拒絕會觸發 `PreToolUse`,但不會觸發此事件;請參閱 [PermissionDenied](#permissiondenied)。
2397</Note>2423</Note>
2398 2424
2399<h4 id="posttoolusefailure-input">2425<h4 id="posttoolusefailure-input">
2400 PostToolUseFailure 輸入2426 PostToolUseFailure 輸入
2401</h4>2427</h4>
2402 2428
2403PostToolUseFailure hook 會收到與 PostToolUse 相同的 `tool_name` 與 `tool_input` 欄位,以及作為頂層欄位的錯誤資訊。若為 MCP 工具,還會收到 [`mcp_server`](#pretooluse-input) 物件。例如,失敗的 `npm test` 命令可能會傳遞:2429PostToolUseFailure hook 會接收與 PostToolUse 相同的 `tool_name` 與 `tool_input` 欄位,並以頂層欄位提供錯誤資訊。對於 MCP 工具,它們也會接收 [`mcp_server`](#pretooluse-input) 物件。例如,失敗的 `npm test` 命令可能會傳遞:
2404 2430
2405```json theme={null}2431```json theme={null}
2406{2432{
2423 2449
2424| 欄位 | 說明 |2450| 欄位 | 說明 |
2425| :- | :- |2451| :- | :- |
2426| `error` | 描述問題的字串。格式取決於失敗的工具 |2452| `error` | 描述發生何種錯誤的字串。格式取決於失敗的工具 |
2427| `is_interrupt` | 選用的布林值。當失敗是以中止的形式傳達給 Claude Code,而非由工具回報的錯誤時為 true。取消執行中的工具不會觸發此 hook;工具結果會改為帶有中斷訊息 |2453| `is_interrupt` | 選用的布林值。當失敗是以中止形式抵達 Claude Code,而非工具所回報的錯誤時為 true。取消正在執行的工具不會觸發此 hook;工具結果會改為攜帶中斷訊息 |
2428| `duration_ms` | 選用。工具執行時間(毫秒)。不包含權限提示與 PreToolUse hook 所花費的時間 |2454| `duration_ms` | 選用。工具執行時間(毫秒)。不包含花在權限提示與 PreToolUse hook 上的時間 |
2429 2455
2430`error` 字串通常與 Claude 收到的失敗工具結果文字相同。其格式因工具與失敗情況而異。請讓您的 hook 依據 `tool_name`、`is_interrupt` 以及第一行的 `Exit code N` 來判斷;字串的其餘部分請視為顯示文字,而非穩定的格式。2456`error` 字串通常與 Claude 收到的失敗工具結果文字相同。其格式因工具與失敗情況而異。請讓您的 hook 以 `tool_name`、`is_interrupt` 以及 `Exit code N` 第一行為判斷依據;將字串的其餘部分視為顯示文字,而非穩定的格式。
2431 2457
2432* 對於 Bash 與 PowerShell,已執行並結束的命令會產生第一行 `Exit code N`,接著是命令產生的所有輸出,stdout 與 stderr 交錯成一個區塊2458* 對於 Bash 與 PowerShell,已執行並結束的命令會產生第一行 `Exit code N`,接著是命令所產生的任何輸出,以單一區塊呈現,stdout 與 stderr 交錯
2433* 當 Claude Code 無法啟動 shell 程序本身時,payload 也可能只帶有一則沒有退出碼行的失敗訊息2459* 當 Claude Code 無法啟動 shell 程序本身時,payload 也可能只攜帶沒有退出碼行的單純失敗訊息
2434* Claude Code 會在 `... [N characters truncated] ...` 標記周圍對長字串進行中段截斷,並可能插入自己的行,例如 `Command timed out after 2m 0s`2460* Claude Code 會以 `... [N characters truncated] ...` 標記為中心截斷長字串的中間部分,也可能插入自己的行,例如 `Command timed out after 2m 0s`
2435 2461
2436<h4 id="posttoolusefailure-decision-control">2462<h4 id="posttoolusefailure-decision-control">
2437 PostToolUseFailure 決策控制2463 PostToolUseFailure 決策控制
2438</h4>2464</h4>
2439 2465
2440`PostToolUseFailure` hook 可以在工具失敗後向 Claude 提供上下文。除了所有 hook 皆可使用的 [JSON 輸出欄位](#json-output)外,您的 hook 指令碼還可以回傳下列事件專屬欄位:2466`PostToolUseFailure` hook 可以在工具失敗後向 Claude 提供上下文。除了所有 hook 都可使用的 [JSON 輸出欄位](#json-output)之外,您的 hook 指令碼還可以回傳以下事件專屬欄位:
2441 2467
2442| 欄位 | 說明 |2468| 欄位 | 說明 |
2443| :- | :- |2469| :- | :- |
2444| `additionalContext` | 與錯誤一起加入 Claude 上下文的字串。請參閱[為 Claude 新增上下文](#add-context-for-claude) |2470| `additionalContext` | 與錯誤一併加入 Claude 上下文的字串。請參閱[為 Claude 新增上下文](#add-context-for-claude) |
2445 2471
2446```json theme={null}2472```json theme={null}
2447{2473{
2456 PostToolBatch2482 PostToolBatch
2457</h3>2483</h3>
2458 2484
2459在一個批次中的每個工具呼叫都處理完畢後執行一次,時間點在 Claude Code 向模型傳送下一個請求之前。`PostToolUse` 會針對每個工具觸發一次,這表示當 Claude 進行平行工具呼叫時,它會同時觸發多次。`PostToolBatch` 則會以完整批次恰好觸發一次,因此適合用來注入取決於所執行工具集合、而非任何單一工具的上下文。此事件沒有 matcher。2485在批次中的每個工具呼叫都已完成後執行一次,於 Claude Code 向模型傳送下一個請求之前。`PostToolUse` 會針對每個工具各觸發一次,這表示當 Claude 進行平行工具呼叫時,它會同時觸發。`PostToolBatch` 則會以完整批次精確觸發一次,因此適合用來注入取決於所執行工具集合、而非任何單一工具的上下文。此事件沒有 matcher。
2460 2486
2461<h4 id="posttoolbatch-input">2487<h4 id="posttoolbatch-input">
2462 PostToolBatch 輸入2488 PostToolBatch 輸入
2463</h4>2489</h4>
2464 2490
2465除了[共通輸入欄位](#common-input-fields)外,PostToolBatch hook 還會收到 `tool_calls`,這是一個描述批次中每個工具呼叫的陣列:2491除了[通用輸入欄位](#common-input-fields)之外,PostToolBatch hook 還會接收 `tool_calls`,這是一個描述批次中每個工具呼叫的陣列:
2466 2492
2467```json theme={null}2493```json theme={null}
2468{2494{
2488}2514}
2489```2515```
2490 2516
2491`tool_response` 包含的內容與模型在對應 `tool_result` 區塊中收到的內容相同。其值為序列化字串或內容區塊陣列,與工具產生時完全一致。以 `Read` 為例,這代表帶有行號前綴的文字,而非原始檔案內容。回應可能很大,因此請只解析您需要的欄位。2517`tool_response` 包含模型在對應 `tool_result` 區塊中收到的相同內容。該值是序列化後的字串或內容區塊陣列,與工具輸出的內容完全一致。對於 `Read`,這表示是帶有行號前綴的文字,而非原始檔案內容。回應可能很大,因此請只解析您需要的欄位。
2492 2518
2493<Note>2519<Note>
2494 `tool_response` 的結構與 `PostToolUse` 的不同。`PostToolUse` 傳遞的是工具的結構化 `Output` 物件,例如 `Write` 的 `{filePath: "...", type: "create"}`;`PostToolBatch` 傳遞的則是模型看到的序列化 `tool_result` 內容。2520 `tool_response` 的結構與 `PostToolUse` 不同。`PostToolUse` 傳遞的是工具的結構化 `Output` 物件,例如 `Write` 的 `{filePath: "...", type: "create"}`;`PostToolBatch` 傳遞的則是模型所看到的序列化 `tool_result` 內容。
2495</Note>2521</Note>
2496 2522
2497<h4 id="posttoolbatch-decision-control">2523<h4 id="posttoolbatch-decision-control">
2498 PostToolBatch 決策控制2524 PostToolBatch 決策控制
2499</h4>2525</h4>
2500 2526
2501`PostToolBatch` hook 可以為 Claude 注入上下文。除了所有 hook 皆可使用的 [JSON 輸出欄位](#json-output)外,您的 hook 指令碼還可以回傳下列事件專屬欄位:2527`PostToolBatch` hook 可以為 Claude 注入上下文。除了所有 hook 都可使用的 [JSON 輸出欄位](#json-output)之外,您的 hook 指令碼還可以回傳以下事件專屬欄位:
2502 2528
2503| 欄位 | 說明 |2529| 欄位 | 說明 |
2504| :- | :- |2530| :- | :- |
2513}2539}
2514```2540```
2515 2541
2516回傳 `decision: "block"` 或 `continue: false` 會在下一次模型呼叫前停止代理式迴圈。封鎖訊息來自 JSON 的 `reason` 或 `stopReason`,或在退出碼 2 時來自 stderr。您會在逐字稿中看到它以警告形式顯示,且它會保留在對話中,因此對話繼續時 Claude 也會看到它。2542回傳 `decision: "block"` 或 `continue: false` 會在下一次模型呼叫前停止代理式迴圈。封鎖訊息來自 JSON 的 `reason` 或 `stopReason`,或在退出碼 2 時來自 stderr。您會在逐字稿中看到它以警告形式呈現,且它會保留在對話中,因此 Claude 會在對話繼續時看到它。
2517 2543
2518<h3 id="permissiondenied">2544<h3 id="permissiondenied">
2519 PermissionDenied2545 PermissionDenied
2520</h3>2546</h3>
2521 2547
2522在[自動模式](/docs/zh-TW/permission-modes#eliminate-prompts-with-auto-mode)拒絕工具呼叫時執行,包括在沒有分類器判定的情況下拒絕,原因是[與自動模式分開的安全檢查拒絕了分類器本身的請求](/docs/zh-TW/errors#auto-mode-cannot-determine-the-safety-of-an-action),或分類器的回應無法解析。此 hook 只會在自動模式下觸發:當您手動拒絕權限對話方塊、`PreToolUse` hook 封鎖呼叫,或 `deny` 規則相符時,它都不會執行。可用來記錄拒絕、調整設定,或告知模型它可以重試該工具呼叫。2548在[自動模式](/docs/zh-TW/permission-modes#eliminate-prompts-with-auto-mode)拒絕工具呼叫時執行,包括在沒有分類器判定的情況下拒絕,原因是[獨立於自動模式之外的安全檢查拒絕了分類器本身的請求](/docs/zh-TW/errors#auto-mode-cannot-determine-the-safety-of-an-action),或其回應無法解析。此 hook 只會在自動模式下觸發:當您手動拒絕權限對話框、`PreToolUse` hook 封鎖呼叫,或 `deny` 規則相符時,都不會執行。可用於記錄拒絕、調整設定,或告知模型它可以重試該工具呼叫。
2523 2549
2524依工具名稱比對,可用值與 PreToolUse 相同。2550依工具名稱比對,值與 PreToolUse 相同。
2525 2551
2526<h4 id="permissiondenied-input">2552<h4 id="permissiondenied-input">
2527 PermissionDenied 輸入2553 PermissionDenied 輸入
2528</h4>2554</h4>
2529 2555
2530除了[共通輸入欄位](#common-input-fields)外,PermissionDenied hook 還會收到 `tool_name`、`tool_input`、`tool_use_id` 與 `reason`。若為 MCP 工具,還會收到 [`mcp_server`](#pretooluse-input) 物件。2556除了[通用輸入欄位](#common-input-fields)之外,PermissionDenied hook 還會接收 `tool_name`、`tool_input`、`tool_use_id` 與 `reason`。對於 MCP 工具,它們也會接收 [`mcp_server`](#pretooluse-input) 物件。
2531 2557
2532```json theme={null}2558```json theme={null}
2533{2559{
2548 2574
2549| 欄位 | 說明 |2575| 欄位 | 說明 |
2550| :- | :- |2576| :- | :- |
2551| `reason` | 拒絕原因。若為分類器判定,在大多數工作階段中會以方括號標示相符的規則,例如 `[Data Exfiltration]`;其他形式請參閱[檢視拒絕](/docs/zh-TW/auto-mode-config#review-denials)。若為[無判定的拒絕](#permissiondenied-decision-control),則以 `Auto mode could not evaluate this action and is blocking it for safety` 開頭。若因分類器模型無法使用而拒絕,則為固定文字 `Classifier unavailable` |2577| `reason` | 拒絕原因。對於分類器判定,在大多數工作階段中,它會以方括號標示相符的規則,例如 `[Data Exfiltration]`;其他形式請參閱[審查拒絕](/docs/zh-TW/auto-mode-config#review-denials)。對於[無判定的拒絕](#permissiondenied-decision-control),它以 `Auto mode could not evaluate this action and is blocking it for safety` 開頭。對於因分類器模型無法使用而產生的拒絕,它是固定文字 `Classifier unavailable` |
2552 2578
2553<h4 id="permissiondenied-decision-control">2579<h4 id="permissiondenied-decision-control">
2554 PermissionDenied 決策控制2580 PermissionDenied 決策控制
2555</h4>2581</h4>
2556 2582
2557PermissionDenied hook 可以告知模型它可以重試遭拒的工具呼叫。回傳一個將 `hookSpecificOutput.retry` 設為 `true` 的 JSON 物件:2583PermissionDenied hook 可以告知模型它可以重試被拒絕的工具呼叫。回傳一個 `hookSpecificOutput.retry` 設為 `true` 的 JSON 物件:
2558 2584
2559```json theme={null}2585```json theme={null}
2560{2586{
2565}2591}
2566```2592```
2567 2593
2568當 `retry` 為 `true` 時,Claude Code 會在對話中加入一則訊息,告知模型它可以重試該工具呼叫。Claude Code 本身不會撤銷該拒絕。如果您的 hook 沒有回傳 JSON,或回傳 `retry: false`,拒絕就會維持,模型會收到原始的拒絕訊息。2594當 `retry` 為 `true` 時,Claude Code 會在對話中加入一則訊息,告知模型它可以重試該工具呼叫。Claude Code 本身不會撤銷拒絕。若您的 hook 未回傳 JSON,或回傳 `retry: false`,拒絕維持有效,模型會收到原始的拒絕訊息。
2569 2595
2570當分類器[對該動作沒有做出判定](/docs/zh-TW/errors#auto-mode-cannot-determine-the-safety-of-an-action)時,Claude Code 會忽略 `retry: true`:分類器的回應無法解析,或與自動模式分開的安全檢查拒絕了分類器本身的請求。對於這些拒絕,Claude Code 已在拒絕訊息中告知模型應稍後重試還是繼續進行。2596當分類器[未對該動作產生判定](/docs/zh-TW/errors#auto-mode-cannot-determine-the-safety-of-an-action)時,Claude Code 會忽略 `retry: true`:其回應無法解析,或獨立於自動模式之外的安全檢查拒絕了分類器本身的請求。對於這些拒絕,Claude Code 已在拒絕訊息中告知模型應稍後重試或繼續其他工作。
2571 2597
2572<h3 id="notification">2598<h3 id="notification">
2573 Notification2599 Notification
2575 2601
2576在 Claude Code 傳送通知時執行。依通知類型比對。省略 matcher 即可針對所有通知類型執行 hook。2602在 Claude Code 傳送通知時執行。依通知類型比對。省略 matcher 即可針對所有通知類型執行 hook。
2577 2603
2578即使關閉桌面通知,您仍會收到這些 hook 事件:`preferredNotifChannel` 設定(包括 `notifications_disabled`)只會改變您收到提醒的方式,而不會影響您的 hook 是否執行。2604即使關閉了桌面通知,您仍會收到這些 hook 事件:`preferredNotifChannel` 設定(包括 `notifications_disabled`)只會改變您接收提醒的方式,而不會影響您的 hook 是否執行。
2579 2605
2580| Matcher | 觸發時機 |2606| Matcher | 觸發時機 |
2581| :- | :- |2607| :- | :- |
2582| `permission_prompt` | Claude 需要您核准工具使用或沙箱化命令的[網路請求](/docs/zh-TW/sandboxing#network-isolation),且提示已等待約六秒 |2608| `permission_prompt` | Claude 需要您核准工具使用或沙箱化命令的[網路請求](/docs/zh-TW/sandboxing#network-isolation),且提示已等待約六秒 |
2583| `idle_prompt` | Claude 約 60 秒前已完成回應,且您之後未曾輸入 |2609| `idle_prompt` | Claude 約在 60 秒前完成回應,且您之後未曾輸入 |
2584| `auth_success` | 身分驗證完成 |2610| `auth_success` | 身分驗證完成 |
2585| `elicitation_dialog` | MCP 伺服器開啟了 elicitation 表單,且您約六秒未輸入 |2611| `elicitation_dialog` | MCP 伺服器開啟 elicitation 表單,且您約六秒未輸入 |
2586| `elicitation_url_dialog` | MCP 伺服器要求您開啟瀏覽器 URL,且您約六秒未輸入 |2612| `elicitation_url_dialog` | MCP 伺服器要求您開啟瀏覽器 URL,且您約六秒未輸入 |
2587| `elicitation_complete` | MCP 伺服器回報 [URL 模式 elicitation](#elicitation-input) 已完成 |2613| `elicitation_complete` | MCP 伺服器回報 [URL 模式 elicitation](#elicitation-input) 已完成 |
2588| `elicitation_response` | MCP elicitation 回應已傳回伺服器 |2614| `elicitation_response` | MCP elicitation 回應被傳回伺服器 |
2589| `agent_needs_input` | 在終端機中開啟 [agent view](/docs/zh-TW/agent-view) 時,背景工作階段開始等待您的輸入。當終端機工作階段向您顯示 [agent team 隊員的終端機設定問題](/docs/zh-TW/agent-teams#choose-a-display-mode),或自動模式關於[分類器請求費用](/docs/zh-TW/auto-mode-classifier-billing)的通知,且您約六秒未輸入時,也會觸發 |2615| `agent_needs_input` | 在終端機中開啟 [agent 檢視](/docs/zh-TW/agent-view)時,某個背景工作階段開始等待您的輸入。當終端機工作階段向您顯示 [agent team 隊員的終端機設定問題](/docs/zh-TW/agent-teams#choose-a-display-mode),或自動模式關於[分類器請求費用](/docs/zh-TW/auto-mode-classifier-billing)的通知,且您約六秒未輸入時,也會觸發 |
2590| `agent_completed` | 背景工作階段完成或失敗。僅在終端機中開啟 [agent view](/docs/zh-TW/agent-view) 時觸發 |2616| `agent_completed` | 背景工作階段完成或失敗。僅在終端機中開啟 [agent 檢視](/docs/zh-TW/agent-view)時觸發 |
2591| `quota_auto_resume_fired` | 在 claude.ai 用量上限暫停您的任務後,Claude Code 繼續執行該任務:於重設時,或當您在等待期間於 Claude Code 中所做的某些事情(例如新增用量點數、升級方案或切換模型)使用量再次可用時提前繼續,但有[模型設定例外](/docs/zh-TW/interactive-mode#wait-for-a-usage-limit-to-reset) |2617| `quota_auto_resume_fired` | Claude Code 在 claude.ai 用量上限暫停您的任務後繼續執行:在重設時,或在等待期間您於 Claude Code 中所做的某些動作(例如新增用量點數、升級方案或切換模型)使用量再次可用時提前繼續,但有[模型設定例外](/docs/zh-TW/interactive-mode#wait-for-a-usage-limit-to-reset) |
2592| `quota_auto_resume_stale` | claude.ai 用量上限在您的電腦休眠超過約 30 分鐘期間重設。Claude Code 會等待您按下 `Enter`,而不是直接繼續。若休眠時間較短,它會繼續並改為觸發 `quota_auto_resume_fired` |2618| `quota_auto_resume_stale` | claude.ai 用量上限在您的電腦休眠超過約 30 分鐘期間重設。Claude Code 會等待您按下 `Enter`,而非繼續執行。若休眠時間較短,它會繼續執行並改為觸發 `quota_auto_resume_fired` |
2593| `quota_auto_resume_disabled` | Claude Code 結束對 claude.ai 用量上限的等待,但未繼續您的任務:[`autoContinueAtUsageLimit`](/docs/zh-TW/settings-reference#autocontinueatusagelimit) 已關閉,或在 Claude Code 自行開始的等待期間重設時間延後超過 24 小時、繼續的任務持續觸及上限,或繼續動作在抵達模型前遭到封鎖。當您按下 `Esc` 或 `Ctrl+C`,或選擇 **Don't continue automatically** 時不會觸發 |2619| `quota_auto_resume_disabled` | Claude Code 結束對 claude.ai 用量上限的等待,且未繼續您的任務:[`autoContinueAtUsageLimit`](/docs/zh-TW/settings-reference#autocontinueatusagelimit) 已關閉,或在 Claude Code 自行開始的等待期間重設時間延後超過 24 小時、繼續的任務持續觸及上限,或繼續執行在抵達模型之前遭到封鎖。當您按下 `Esc` 或 `Ctrl+C`,或選擇 **Don't continue automatically** 時不會觸發 |
2594 2620
2595`quota_auto_resume_fired`、`quota_auto_resume_stale` 與 `quota_auto_resume_disabled` 類型需要 Claude Code v2.1.234 或更新版本。2621`quota_auto_resume_fired`、`quota_auto_resume_stale` 與 `quota_auto_resume_disabled` 類型需要 Claude Code v2.1.234 或更新版本。
2596 2622
2599針對隊員終端機設定問題的 `agent_needs_input` 需要 Claude Code v2.1.248 或更新版本。2625針對隊員終端機設定問題的 `agent_needs_input` 需要 Claude Code v2.1.248 或更新版本。
2600 2626
2601<Note>2627<Note>
2602 `permission_prompt`、`idle_prompt`、`elicitation_dialog` 與 `elicitation_url_dialog` 類型與桌面通知共用相同的時機,因此在終端機工作階段中,只有當您看起來已離開終端機時才會看到它們:2628 `permission_prompt`、`idle_prompt`、`elicitation_dialog` 與 `elicitation_url_dialog` 類型與桌面通知共用相同的時機,因此在終端機工作階段中,只有當您看起來不在終端機前時才會看到它們:
2603 2629
2604 * 預期在您約六秒未輸入後出現 `permission_prompt`。計時器在權限提示出現時開始,每次按鍵都會延後它。若要在 Claude 要求使用工具的權限時立即執行 hook,請改用 [PermissionRequest](#permissionrequest)。2630 * 當您約六秒未輸入時,預期會出現 `permission_prompt`。計時器從權限提示出現時開始,每次按鍵都會使其延後。若要在 Claude 請求使用工具的權限時立即執行 hook,請改用 [PermissionRequest](#permissionrequest)。
2605 * 預期在 Claude 完成回應約 60 秒後出現 `idle_prompt`,且僅限於您之後未曾輸入,並且沒有背景 agent(例如背景 [subagent](/docs/zh-TW/sub-agents))仍在執行時。Claude Code 在等待 claude.ai 用量上限重設期間不會傳送 `idle_prompt`。當等待自行結束時,會改為觸發其中一個 `quota_auto_resume_*` 類型。2631 * 在 Claude 完成回應約 60 秒後,預期會出現 `idle_prompt`,但前提是您之後未曾輸入,且沒有背景 agent(例如背景 [subagent](/docs/zh-TW/sub-agents))仍在執行。Claude Code 在等待 claude.ai 用量上限重設期間不會傳送 `idle_prompt`。當等待自行結束時,會改為觸發其中一個 `quota_auto_resume_*` 類型。
2606 * 預期在您約六秒未輸入後,針對 elicitation 表單出現 `elicitation_dialog`,或針對瀏覽器 URL 請求出現 `elicitation_url_dialog`。兩者與 `permission_prompt` 共用相同的六秒門檻:計時器在對話方塊出現時開始,每次按鍵都會延後它。2632 * 當您約六秒未輸入時,預期會針對 elicitation 表單出現 `elicitation_dialog`,或針對瀏覽器 URL 請求出現 `elicitation_url_dialog`。兩者與 `permission_prompt` 共用相同的六秒門檻:計時器從對話框出現時開始,每次按鍵都會使其延後。
2607 2633
2608 在另一個對話方塊仍顯示於畫面上時抵達的權限請求或 elicitation,會維持相同的六秒門檻,並從請求抵達時開始計時。其通知可能會在該請求仍在已開啟的對話方塊後方等待時送達給您。2634 在另一個對話框顯示於畫面上時抵達的權限請求或 elicitation,仍適用相同的六秒門檻,從請求抵達時開始計時。其通知可能會在請求仍於開啟的對話框後方等待時送達您。
2609</Note>2635</Note>
2610 2636
2611在 Claude Code 將權限請求傳送到 Agent SDK 的 [`canUseTool` 回呼](/docs/zh-TW/agent-sdk/user-input)的工作階段中(Claude Desktop 與 VS Code 擴充功能即以此方式託管 Claude Code),Claude Code 對 `permission_prompt` 的計時方式不同:2637在 Claude Code 將權限請求傳送至 Agent SDK 的 [`canUseTool` 回呼](/docs/zh-TW/agent-sdk/user-input)的工作階段中(也就是 Claude Desktop 與 VS Code 擴充功能承載 Claude Code 的方式),Claude Code 對 `permission_prompt` 的計時方式不同:
2612 2638
2613* 預期在 Claude 要求權限約六秒後出現 `permission_prompt`。Claude Code 不會因為您正在輸入而延後它。2639* 預期會在 Claude 請求權限約六秒後出現 `permission_prompt`。Claude Code 不會因為您輸入而延後它。
2614* 如果您或 [PermissionRequest](#permissionrequest) hook 較早回應,Claude Code 就不會執行 `permission_prompt`。2640* 若您或 [PermissionRequest](#permissionrequest) hook 較早回應,Claude Code 不會執行 `permission_prompt`。
2615* 將 [`CLAUDE_CODE_DISABLE_PERMISSION_PROMPT_NOTIFY_HOOKS`](/docs/zh-TW/env-vars) 設為 `1`,即可在這些工作階段中關閉 `permission_prompt`。2641* 將 [`CLAUDE_CODE_DISABLE_PERMISSION_PROMPT_NOTIFY_HOOKS`](/docs/zh-TW/env-vars) 設為 `1`,即可在這些工作階段中關閉 `permission_prompt`。
2616 2642
2617在 v2.1.233 之前,`permission_prompt` 不會在這些工作階段中觸發。2643在 v2.1.233 之前,`permission_prompt` 不會在這些工作階段中觸發。
2618 2644
2619使用不同的 matcher,可依通知類型執行不同的處理程式。以下設定會在 Claude 需要權限核准時觸發權限專用的警示指令碼,並在 Claude 閒置時觸發另一個通知:2645使用不同的 matcher,即可依通知類型執行不同的處理常式。以下設定會在 Claude 需要權限核准時觸發權限專屬的警示指令碼,並在 Claude 閒置時觸發另一個通知:
2620 2646
2621```json theme={null}2647```json theme={null}
2622{2648{
2649 Notification 輸入2675 Notification 輸入
2650</h4>2676</h4>
2651 2677
2652除了[共通輸入欄位](#common-input-fields)外,Notification hook 還會收到帶有通知文字的 `message`、選用的 `title`,以及指出觸發類型的 `notification_type`。2678除了[通用輸入欄位](#common-input-fields)之外,Notification hook 還會接收包含通知文字的 `message`、選用的 `title`,以及指出觸發類型的 `notification_type`。
2653 2679
2654```json theme={null}2680```json theme={null}
2655{2681{
2663}2689}
2664```2690```
2665 2691
2666Notification hook 無法封鎖或修改通知。Claude Code 會捨棄其 `systemMessage` 與 `continue` 欄位,但仍會輸出 [`terminalSequence`](#emit-terminal-notifications),這正是桌面通知範例所依賴的。Notification hook 的用途是產生副作用,例如將通知轉送到外部服務。2692Notification hook 無法封鎖或修改通知。Claude Code 會捨棄其 `systemMessage` 與 `continue` 欄位,但仍會輸出 [`terminalSequence`](#emit-terminal-notifications),桌面通知範例正是仰賴此欄位。Notification hook 的用途是產生副作用,例如將通知轉送至外部服務。
2667 2693
2668<h3 id="subagentstart">2694<h3 id="subagentstart">
2669 SubagentStart2695 SubagentStart
2670</h3>2696</h3>
2671 2697
2672在 Claude 以 Agent 工具產生 subagent 時、在 Claude [恢復 subagent](/docs/zh-TW/sub-agents#resume-subagents) 時,以及每次程序內 [agent team](/docs/zh-TW/agent-teams) 隊員處理新訊息時執行。支援以 matcher 依 agent 類型名稱篩選。對於內建 agent,這是 agent 名稱,例如 `general-purpose`、`Explore` 或 `Plan`。對於[自訂 subagent](/docs/zh-TW/sub-agents),這是 agent frontmatter 中的 `name` 欄位,而非檔案名稱。2698在 Claude 使用 Agent 工具產生 subagent 時、在 Claude [恢復 subagent](/docs/zh-TW/sub-agents#resume-subagents) 時,以及每次程序內 [agent team](/docs/zh-TW/agent-teams) 隊員處理新訊息時執行。支援使用 matcher 依 agent 類型名稱篩選。對於內建 agent,這是 agent 名稱,例如 `general-purpose`、`Explore` 或 `Plan`。對於[自訂 subagent](/docs/zh-TW/sub-agents),這是 agent frontmatter 中的 `name` 欄位,而非檔案名稱。
2673 2699
2674對於由[外掛](/docs/zh-TW/plugins/overview)提供的 subagent,agent 類型是外掛範圍的識別碼,例如 `my-plugin:reviewer`,而非單純的 frontmatter 名稱。冒號會使外掛範圍的名稱走正規表示式路徑,因此請以 `^` 與 `$` 錨定 matcher 以進行精確比對:`^my-plugin:reviewer$`。2700對於由[外掛](/docs/zh-TW/plugins/overview)提供的 subagent,agent 類型是外掛範圍的識別碼,例如 `my-plugin:reviewer`,而非單純的 frontmatter 名稱。冒號會使外掛範圍的名稱走正規表示式路徑,因此請以 `^` 與 `$` 錨定 matcher 以進行精確比對:`^my-plugin:reviewer$`。
2675 2701
2677 SubagentStart 輸入2703 SubagentStart 輸入
2678</h4>2704</h4>
2679 2705
2680除了[共通輸入欄位](#common-input-fields)外,SubagentStart hook 還會收到帶有 subagent 唯一識別碼的 `agent_id`,以及帶有 matcher 篩選依據之 agent 名稱的 `agent_type`。2706除了[通用輸入欄位](#common-input-fields)之外,SubagentStart hook 還會接收包含 subagent 唯一識別碼的 `agent_id`,以及包含 matcher 篩選依據之 agent 名稱的 `agent_type`。
2681 2707
2682```json theme={null}2708```json theme={null}
2683{2709{
2690}2716}
2691```2717```
2692 2718
2693SubagentStart hook 無法封鎖 subagent 的建立,但可以將上下文注入 subagent。除了所有 hook 皆可使用的 [JSON 輸出欄位](#json-output)外,您還可以回傳:2719SubagentStart hook 無法封鎖 subagent 的建立,但可以將上下文注入 subagent。除了所有 hook 都可使用的 [JSON 輸出欄位](#json-output)之外,您還可以回傳:
2694 2720
2695| 欄位 | 說明 |2721| 欄位 | 說明 |
2696| :- | :- |2722| :- | :- |
2697| `additionalContext` | 在 subagent 對話開始時、其第一個提示詞之前加入其上下文的字串。請參閱[為 Claude 新增上下文](#add-context-for-claude) |2723| `additionalContext` | 在 subagent 對話開始時、其第一個提示詞之前,加入 subagent 上下文的字串。請參閱[為 Claude 新增上下文](#add-context-for-claude) |
2698 2724
2699```json theme={null}2725```json theme={null}
2700{2726{
2705}2731}
2706```2732```
2707 2733
2708當 hook 針對同一個 subagent 再次執行時,只有在 subagent 的上下文中尚未保有先前執行的副本時,Claude Code 才會注入回傳的上下文。啟動時注入的副本會保留在原處,使 subagent 的[提示快取](/docs/zh-TW/prompt-caching#subagents-and-the-cache)保持完整。在[自動壓縮](/docs/zh-TW/sub-agents#auto-compaction)捨棄該副本後,Claude Code 會再次注入下一次執行的上下文。2734當 hook 針對同一個 subagent 再次執行時,只有在 subagent 的上下文尚未保有先前執行所注入的副本時,Claude Code 才會注入回傳的上下文。啟動時注入的副本會保留在原處,使 subagent 的[提示快取](/docs/zh-TW/prompt-caching#subagents-and-the-cache)保持完整。在[自動壓縮](/docs/zh-TW/sub-agents#auto-compaction)捨棄該副本後,Claude Code 會再次注入下一次執行的上下文。
2709 2735
2710<h3 id="subagentstop">2736<h3 id="subagentstop">
2711 SubagentStop2737 SubagentStop
2712</h3>2738</h3>
2713 2739
2714在 Claude Code subagent 完成回應時執行。依 agent 類型比對,可用值與 SubagentStart 相同。2740在 Claude Code subagent 完成回應時執行。依 agent 類型比對,值與 SubagentStart 相同。
2715 2741
2716<h4 id="subagentstop-input">2742<h4 id="subagentstop-input">
2717 SubagentStop 輸入2743 SubagentStop 輸入
2718</h4>2744</h4>
2719 2745
2720除了[共通輸入欄位](#common-input-fields)外,SubagentStop hook 還會收到 `stop_hook_active`、`agent_id`、`agent_type`、`agent_transcript_path` 與 `last_assistant_message`。`agent_type` 欄位是用於 matcher 篩選的值。`transcript_path` 是主工作階段的逐字稿,而 `agent_transcript_path` 則是 subagent 自己的逐字稿,儲存在巢狀的 `subagents/` 資料夾中。`last_assistant_message` 欄位包含 subagent 最終回應的文字內容,因此 hook 不需解析逐字稿檔案即可存取。2746除了[通用輸入欄位](#common-input-fields)之外,SubagentStop hook 還會接收 `stop_hook_active`、`agent_id`、`agent_type`、`agent_transcript_path` 與 `last_assistant_message`。`agent_type` 欄位是用於 matcher 篩選的值。`transcript_path` 是主工作階段的逐字稿,而 `agent_transcript_path` 則是儲存在巢狀 `subagents/` 資料夾中的 subagent 自身逐字稿。`last_assistant_message` 欄位包含 subagent 最終回應的文字內容,因此 hook 無需解析逐字稿檔案即可存取。
2721 2747
2722並非每個 SubagentStop 事件都來自 Claude 產生的 subagent。Claude Code 也會為其部分功能執行內部 agent,例如[提示詞建議](/docs/zh-TW/interactive-mode#prompt-suggestions)與 [`/btw` 旁支問題](/docs/zh-TW/interactive-mode#side-questions-with-%2Fbtw),當其中之一完成時也會觸發 SubagentStop。對於這些事件,`agent_type` 是工作階段本身執行時所用的 agent 名稱,例如透過 [`--agent`](/docs/zh-TW/cli-reference#cli-flags) 或 [`agent` 設定](/docs/zh-TW/settings-reference#agent)設定的名稱;若工作階段未使用 agent,則為空字串。2748並非每個 SubagentStop 事件都來自 Claude 所產生的 subagent。Claude Code 也會為其自身的某些功能執行內部 agent,例如[提示詞建議](/docs/zh-TW/interactive-mode#prompt-suggestions)與 [`/btw` 旁支問題](/docs/zh-TW/interactive-mode#side-questions-with-%2Fbtw),當其中之一完成時,SubagentStop 也會觸發。對於這些事件,`agent_type` 是工作階段本身執行時所使用的 agent 名稱,例如以 [`--agent`](/docs/zh-TW/cli-reference#cli-flags) 或 [`agent` 設定](/docs/zh-TW/settings-reference#agent)所設定者;若工作階段未使用任何 agent 執行,則為空字串。
2723 2749
2724指名 agent 類型的 `matcher` 不會比對到空的 `agent_type`。matcher 省略、為 `""` 或 `"*"`,或是可比對空字串之正規表示式的 hook,也會針對 `agent_type` 為空的事件執行。2750指定 agent 類型的 `matcher` 不會比對空的 `agent_type`。matcher 被省略、為 `""` 或 `"*"`,或是可比對空字串之正規表示式的 hook,也會針對 `agent_type` 為空的事件執行。
2725 2751
2726在 Claude Code v2.1.271 或更新版本中,使用 [`SubagentHandback`](/docs/zh-TW/tools-reference) 工具執行的 subagent 會在停止前透過該工具傳遞其報告。此時 `last_assistant_message` 欄位保存的是 subagent 的結尾文字(若有),而非傳遞的報告。報告是該呼叫的 `message` 輸入,比對 `SubagentHandback` 的 `PreToolUse` 或 `PostToolUse` hook 會以 `tool_input.message` 收到它。2752在 Claude Code v2.1.271 或更新版本中,使用 [`SubagentHandback`](/docs/zh-TW/tools-reference) 工具執行的 subagent 會在停止之前透過該工具傳遞其報告。此時 `last_assistant_message` 欄位保存的是 subagent 的結尾文字(若有),而非所傳遞的報告。報告是該呼叫的 `message` 輸入,比對 `SubagentHandback` 的 `PreToolUse` 或 `PostToolUse` hook 會以 `tool_input.message` 接收它。
2727 2753
2728SubagentStop hook 也會收到 [Stop 輸入](#stop-input)中所述的 `background_tasks` 與 `session_crons` 陣列。這兩個陣列的範圍都是父工作階段,而非 subagent。2754SubagentStop hook 也會接收 [Stop 輸入](#stop-input)中所述的 `background_tasks` 與 `session_crons` 陣列。這兩個陣列的範圍都是父工作階段,而非 subagent。
2729 2755
2730```json theme={null}2756```json theme={null}
2731{2757{
2744}2770}
2745```2771```
2746 2772
2747SubagentStop hook 使用與 [Stop hook](#stop-decision-control) 相同的決策控制格式,包括將 `hookEventName` 設為 `"SubagentStop"` 的 `hookSpecificOutput.additionalContext`,用於讓 subagent 繼續執行的非錯誤回饋。回傳帶有 `reason` 的 `decision: "block"` 會讓 subagent 繼續執行,並將 `reason` 作為其下一個指令傳遞給 subagent。以退出碼 2 封鎖的 hook 也會以相同方式傳遞其 stderr 訊息。若要在 subagent 返回後將上下文注入父工作階段,請改在 `Agent` 工具上使用 [`PostToolUse`](#posttooluse) hook。2773SubagentStop hook 使用與 [Stop hook](#stop-decision-control) 相同的決策控制格式,包括將 `hookEventName` 設為 `"SubagentStop"` 的 `hookSpecificOutput.additionalContext`,用於提供讓 subagent 繼續執行的非錯誤回饋。回傳帶有 `reason` 的 `decision: "block"` 會讓 subagent 繼續執行,並將 `reason` 作為下一個指令傳遞給 subagent。以退出碼 2 封鎖的 hook 也會以相同方式傳遞其 stderr 訊息。若要在 subagent 回傳後將上下文注入父工作階段,請改為在 `Agent` 工具上使用 [`PostToolUse`](#posttooluse) hook。
2748 2774
2749<h3 id="taskcreated">2775<h3 id="taskcreated">
2750 TaskCreated2776 TaskCreated
2751</h3>2777</h3>
2752 2778
2753在透過 `TaskCreate` 工具建立任務時執行。可用來強制執行命名慣例、要求任務說明,或阻止建立特定任務。在[沒有 Task 工具的工作階段](/docs/zh-TW/tools-reference#task-tool-availability)中,此事件不會觸發。2779在透過 `TaskCreate` 工具建立任務時執行。可用於強制執行命名慣例、要求任務說明,或防止建立特定任務。在[沒有 Task 工具的工作階段](/docs/zh-TW/tools-reference#task-tool-availability)中,此事件不會觸發。
2754 2780
2755TaskCreated hook 不支援 matcher,每次發生時都會觸發。2781TaskCreated hook 不支援 matcher,每次發生時都會觸發。
2756 2782
2758 TaskCreated 輸入2784 TaskCreated 輸入
2759</h4>2785</h4>
2760 2786
2761除了[共通輸入欄位](#common-input-fields)外,TaskCreated hook 還會收到 `task_id`、`task_subject`,以及選用的 `task_description`、`teammate_name` 與 `team_name`。2787除了[通用輸入欄位](#common-input-fields)之外,TaskCreated hook 還會接收 `task_id`、`task_subject`,以及選用的 `task_description`、`teammate_name` 與 `team_name`。
2762 2788
2763```json theme={null}2789```json theme={null}
2764{2790{
2777| 欄位 | 說明 |2803| 欄位 | 說明 |
2778| :- | :- |2804| :- | :- |
2779| `task_id` | 正在建立之任務的識別碼 |2805| `task_id` | 正在建立之任務的識別碼 |
2780| `task_subject` | 任務的標題 |2806| `task_subject` | 任務標題 |
2781| `task_description` | 任務的詳細說明。可能不存在 |2807| `task_description` | 任務的詳細說明。可能不存在 |
2782| `teammate_name` | 建立任務之隊員的名稱。可能不存在 |2808| `teammate_name` | 建立任務之隊員的名稱。可能不存在 |
2783| `team_name` | 已棄用。衍生自工作階段的團隊名稱;將在未來的版本中移除 |2809| `team_name` | 已棄用。衍生自工作階段的團隊名稱;將在未來版本中移除 |
2784| `agent_id` | 在此事件中,此[共通輸入欄位](#common-input-fields)識別建立任務的 subagent 或[程序內隊員](/docs/zh-TW/agent-teams#choose-a-display-mode)。可能不存在。需要 Claude Code v2.1.290 或更新版本 |2810| `agent_id` | 在此事件中,此[通用輸入欄位](#common-input-fields)識別建立任務的 subagent 或[程序內隊員](/docs/zh-TW/agent-teams#choose-a-display-mode)。可能不存在。需要 Claude Code v2.1.290 或更新版本 |
2785 2811
2786<h4 id="taskcreated-decision-control">2812<h4 id="taskcreated-decision-control">
2787 TaskCreated 決策控制2813 TaskCreated 決策控制
2788</h4>2814</h4>
2789 2815
2790TaskCreated hook 可以透過退出碼 2 或 JSON 決策封鎖建立。無論採用哪種方式,Claude Code 都會刪除該任務,並將您的訊息作為工具的錯誤回傳給 Claude。Claude Code 會忽略此事件的 `continue: false`,Claude 會繼續工作。2816TaskCreated hook 可以使用退出碼 2 或 JSON 決策封鎖建立。無論哪種方式,Claude Code 都會刪除該任務,並將您的訊息作為工具錯誤回傳給 Claude。Claude Code 會忽略此事件的 `continue: false`,Claude 會繼續工作。
2791 2817
2792* **退出碼 2**:Claude Code 會將 stderr 文字作為訊息回傳。2818* **退出碼 2**:Claude Code 會將 stderr 文字作為訊息回傳。
2793* **JSON `{"decision": "block", "reason": "..."}`**:Claude Code 會將 `reason` 作為訊息回傳。2819* **JSON `{"decision": "block", "reason": "..."}`**:Claude Code 會將 `reason` 作為訊息回傳。
2794 2820
2795以下範例會封鎖主旨不符合規定格式的任務:2821以下範例會封鎖主旨不符合必要格式的任務:
2796 2822
2797```bash theme={null}2823```bash theme={null}
2798#!/bin/bash2824#!/bin/bash
2811 TaskCompleted2837 TaskCompleted
2812</h3>2838</h3>
2813 2839
2814在任務被標記為已完成時執行。這會在兩種情況下觸發:任何 agent 透過 TaskUpdate 工具明確將任務標記為已完成時,或 [agent team](/docs/zh-TW/agent-teams) 隊員在仍有進行中任務的情況下結束其回合時。可用來在任務關閉前強制執行完成條件,例如通過測試或 lint 檢查。2840在任務被標記為已完成時執行。此事件會在兩種情況下觸發:任何 agent 透過 TaskUpdate 工具明確將任務標記為已完成時,或 [agent team](/docs/zh-TW/agent-teams) 隊員在仍有進行中任務的情況下結束其回合時。可用於在任務關閉前強制執行完成條件,例如通過測試或 lint 檢查。
2815 2841
2816TaskCompleted hook 不支援 matcher,每次發生時都會觸發。2842TaskCompleted hook 不支援 matcher,每次發生時都會觸發。
2817 2843
2819 TaskCompleted 輸入2845 TaskCompleted 輸入
2820</h4>2846</h4>
2821 2847
2822除了[共通輸入欄位](#common-input-fields)外,TaskCompleted hook 還會收到 `task_id`、`task_subject`,以及選用的 `task_description`、`teammate_name` 與 `team_name`。2848除了[通用輸入欄位](#common-input-fields)之外,TaskCompleted hook 還會接收 `task_id`、`task_subject`,以及選用的 `task_description`、`teammate_name` 與 `team_name`。
2823 2849
2824```json theme={null}2850```json theme={null}
2825{2851{
2839| 欄位 | 說明 |2865| 欄位 | 說明 |
2840| :- | :- |2866| :- | :- |
2841| `task_id` | 正在完成之任務的識別碼 |2867| `task_id` | 正在完成之任務的識別碼 |
2842| `task_subject` | 任務的標題 |2868| `task_subject` | 任務標題 |
2843| `task_description` | 任務的詳細說明。可能不存在 |2869| `task_description` | 任務的詳細說明。可能不存在 |
2844| `teammate_name` | 完成任務之隊員的名稱。可能不存在 |2870| `teammate_name` | 完成任務之隊員的名稱。可能不存在 |
2845| `team_name` | 已棄用。衍生自工作階段的團隊名稱;將在未來的版本中移除 |2871| `team_name` | 已棄用。衍生自工作階段的團隊名稱;將在未來版本中移除 |
2846| `agent_id` | 在此事件中,此[共通輸入欄位](#common-input-fields)識別完成任務的 subagent 或[程序內隊員](/docs/zh-TW/agent-teams#choose-a-display-mode)。可能不存在。需要 Claude Code v2.1.290 或更新版本 |2872| `agent_id` | 在此事件中,此[通用輸入欄位](#common-input-fields)識別完成任務的 subagent 或[程序內隊員](/docs/zh-TW/agent-teams#choose-a-display-mode)。可能不存在。需要 Claude Code v2.1.290 或更新版本 |
2847 2873
2848<h4 id="taskcompleted-decision-control">2874<h4 id="taskcompleted-decision-control">
2849 TaskCompleted 決策控制2875 TaskCompleted 決策控制
2851 2877
2852TaskCompleted hook 支援兩種控制任務完成的方式:2878TaskCompleted hook 支援兩種控制任務完成的方式:
2853 2879
2854* **退出碼 2**:任務不會被標記為已完成,stderr 訊息會作為回饋傳回給模型。2880* **退出碼 2**:任務不會被標記為已完成,且 stderr 訊息會作為回饋傳回給模型。
2855* **JSON `{"continue": false, "stopReason": "..."}`**:當事件是由隊員結束其回合所觸發時,會完全停止該隊員,行為與 `Stop` hook 相同。`stopReason` 會顯示給使用者。當事件是由 `TaskUpdate` 工具觸發時,Claude Code 會忽略 `continue: false`;退出碼 2 仍會封鎖完成。2881* **JSON `{"continue": false, "stopReason": "..."}`**:當事件是由隊員結束其回合所觸發時,會完全停止該隊員,與 `Stop` hook 的行為一致。`stopReason` 會顯示給使用者。當事件是由 `TaskUpdate` 工具觸發時,Claude Code 會忽略 `continue: false`;退出碼 2 仍會封鎖完成。
2856 2882
2857以下範例會執行測試,並在測試失敗時封鎖任務完成:2883以下範例會執行測試,並在測試失敗時封鎖任務完成:
2858 2884
2874 Stop2900 Stop
2875</h3>2901</h3>
2876 2902
2877在主要的 Claude Code agent 完成回應時執行。如果停止是因使用者中斷所致,則不會執行。API 錯誤會改為觸發2903在主要 Claude Code agent 完成回應時執行。若停止是由使用者中斷所造成,則不會執行。API 錯誤會改為觸發
2878[StopFailure](#stopfailure)。2904[StopFailure](#stopfailure)。
2879 2905
2880<Tip>2906<Tip>
2881 [`/goal`](/docs/zh-TW/goal) 命令是以工作階段為範圍、基於提示詞之 Stop hook 的內建捷徑。當您希望 Claude 持續朝某個條件努力,而不想撰寫 hook 設定時,請使用它。2907 [`/goal`](/docs/zh-TW/goal) 命令是工作階段範圍、以提示詞為基礎之 Stop hook 的內建捷徑。當您希望 Claude 持續朝某個條件努力,又不想撰寫 hook 設定時,請使用它。
2882</Tip>2908</Tip>
2883 2909
2884<h4 id="stop-input">2910<h4 id="stop-input">
2885 Stop 輸入2911 Stop 輸入
2886</h4>2912</h4>
2887 2913
2888除了[共通輸入欄位](#common-input-fields)外,Stop hook 還會收到 `stop_hook_active`、`last_assistant_message`、`background_tasks` 與 `session_crons`。當 Claude Code 已因 stop hook 而繼續執行時,`stop_hook_active` 欄位為 `true`。請檢查此值或處理逐字稿,以避免在永遠不會解決的條件上持續封鎖。2914除了[通用輸入欄位](#common-input-fields)之外,Stop hook 還會接收 `stop_hook_active`、`last_assistant_message`、`background_tasks` 與 `session_crons`。當 Claude Code 已因 stop hook 而繼續執行時,`stop_hook_active` 欄位為 `true`。請檢查此值或處理逐字稿,以避免因永遠無法解決的條件而持續封鎖。
2889 2915
2890Claude Code 套用了 8 次連續繼續的上限:在 stop hook 連續讓回合繼續八次後,Claude Code 會覆寫下一次封鎖並結束該回合。每當 Claude 呼叫工具時,連續繼續的次數就會重設。若要提高上限,請設定 [`CLAUDE_CODE_STOP_HOOK_BLOCK_CAP`](/docs/zh-TW/env-vars)。2916Claude Code 套用 8 次連續繼續的上限:在 stop hook 連續讓回合繼續八次之後,Claude Code 會覆寫下一次封鎖並結束回合。每當 Claude 呼叫工具時,連續繼續的次數就會重設。若要提高上限,請設定 [`CLAUDE_CODE_STOP_HOOK_BLOCK_CAP`](/docs/zh-TW/env-vars)。
2891 2917
2892`last_assistant_message` 欄位包含 Claude 最終回應的文字內容,因此 hook 不需解析逐字稿檔案即可存取。對於針對剛完成之回合採取動作的 hook(例如朗讀或通知 hook),請使用此欄位而非讀取 `transcript_path`:並非所有版本都保證逐字稿檔案在 Stop 時已包含最終訊息。2918`last_assistant_message` 欄位包含 Claude 最終回應的文字內容,因此 hook 無需解析逐字稿檔案即可存取。對於針對剛完成之回合採取動作的 hook(例如朗讀或通知 hook),請使用此欄位,而非讀取 `transcript_path`:在所有版本中,逐字稿檔案並不保證在 Stop 時已包含最終訊息。
2893 2919
2894`background_tasks` 與 `session_crons` 陣列讓 hook 能夠區分「工作階段已結束」與「工作階段已暫停,正等待背景工作將其喚醒」。當任務登錄可存取時,兩個陣列都會存在;若沒有進行中或已排程的項目,則為空陣列。2920`background_tasks` 與 `session_crons` 陣列讓 hook 能夠區分「工作階段已完成」與「工作階段已暫停,等待背景工作將其喚醒」。當任務登錄可存取時,這兩個陣列都會存在;當沒有任何進行中或已排程的項目時,它們為空。
2895 2921
2896`background_tasks` 中的每個項目描述一個進行中的任務,並使用下列欄位:2922`background_tasks` 中的每個項目描述一個進行中的任務,並使用以下欄位:
2897 2923
2898| 欄位 | 說明 |2924| 欄位 | 說明 |
2899| :- | :- |2925| :- | :- |
2900| `id` | 任務識別碼 |2926| `id` | 任務識別碼 |
2901| `type` | 易讀的任務類型標籤,例如 `shell`、`subagent`、`monitor`、`workflow`、`teammate`、`cloud session` 或 `MCP task`。每個標籤識別建立該任務的 Claude Code 功能。對於無法辨識的類型,會退回使用原始的判別值 |2927| `type` | 易於理解的任務類型標籤,例如 `shell`、`subagent`、`monitor`、`workflow`、`teammate`、`cloud session` 或 `MCP task`。每個標籤識別建立該任務的 Claude Code 功能。對於無法辨識的類型,會退回使用原始的區別值 |
2902| `status` | 目前的任務狀態 |2928| `status` | 目前的任務狀態 |
2903| `description` | 自由文字說明,上限為 1000 個字元,遭截斷時字串內會帶有 `… [+N chars]` 標記 |2929| `description` | 自由文字說明,上限為 1000 個字元,截斷時會在字串內加上 `… [+N chars]` 標記 |
2904| `command` | shell 命令列,上限為 1000 個字元。僅存在於 `shell` 任務 |2930| `command` | shell 命令列,上限為 1000 個字元。僅存在於 `shell` 任務 |
2905| `agent_type` | subagent 類型名稱。僅存在於 `subagent` 任務 |2931| `agent_type` | subagent 類型名稱。僅存在於 `subagent` 任務 |
2906| `server` | MCP 伺服器名稱。僅存在於 `monitor` 與 `MCP task` 任務 |2932| `server` | MCP 伺服器名稱。僅存在於 `monitor` 與 `MCP task` 任務 |
2907| `tool` | MCP 工具名稱。僅存在於 `monitor` 與 `MCP task` 任務 |2933| `tool` | MCP 工具名稱。僅存在於 `monitor` 與 `MCP task` 任務 |
2908| `name` | 工作流程名稱。僅存在於 `workflow` 任務 |2934| `name` | 工作流程名稱。僅存在於 `workflow` 任務 |
2909 2935
2910`session_crons` 中的每個項目描述一個以工作階段為範圍的排程喚醒,來源為 `CronCreate`、`ScheduleWakeup` 與 `/loop`:2936`session_crons` 中的每個項目描述一個工作階段範圍的排程喚醒,來源為 `CronCreate`、`ScheduleWakeup` 與 `/loop`:
2911 2937
2912| 欄位 | 說明 |2938| 欄位 | 說明 |
2913| :- | :- |2939| :- | :- |
2914| `id` | Cron 任務識別碼 |2940| `id` | Cron 任務識別碼 |
2915| `schedule` | Cron 運算式,例如 `0 9 * * 1-5` |2941| `schedule` | Cron 運算式,例如 `0 9 * * 1-5` |
2916| `recurring` | 對於排程只編碼單一觸發時間的一次性喚醒為 `false`,對於每次比對都會再次觸發的任務為 `true` |2942| `recurring` | 對於排程僅編碼單一觸發時間的一次性喚醒為 `false`,對於每次相符時都會重新觸發的任務為 `true` |
2917| `prompt` | cron 觸發時提交的提示詞,上限為 1000 個字元,並使用相同的 `… [+N chars]` 標記 |2943| `prompt` | cron 觸發時提交的提示詞,上限為 1000 個字元,並使用相同的 `… [+N chars]` 標記 |
2918 2944
2919以下範例顯示一個帶有一個進行中 shell 任務與一個週期性 cron 的 Stop 輸入:2945以下範例顯示一個包含一個進行中 shell 任務與一個週期性 cron 的 Stop 輸入:
2920 2946
2921```json theme={null}2947```json theme={null}
2922{2948{
2951 Stop 決策控制2977 Stop 決策控制
2952</h4>2978</h4>
2953 2979
2954`Stop` 與 `SubagentStop` hook 可以控制 Claude 是否繼續。除了所有 hook 皆可使用的 [JSON 輸出欄位](#json-output)外,您的 hook 指令碼還可以回傳下列事件專屬欄位:2980`Stop` 與 `SubagentStop` hook 可以控制 Claude 是否繼續。除了所有 hook 都可使用的 [JSON 輸出欄位](#json-output)之外,您的 hook 指令碼還可以回傳以下事件專屬欄位:
2955 2981
2956| 欄位 | 說明 |2982| 欄位 | 說明 |
2957| :- | :- |2983| :- | :- |
2958| `decision` | `"block"` 會阻止 Claude 停止。省略則允許 Claude 停止 |2984| `decision` | `"block"` 會阻止 Claude 停止。省略則允許 Claude 停止 |
2959| `reason` | 當 `decision` 為 `"block"` 時為必填。告訴 Claude 為何應該繼續 |2985| `reason` | 當 `decision` 為 `"block"` 時為必要欄位。告訴 Claude 為何應該繼續 |
2960| `hookSpecificOutput.additionalContext` | 給 Claude 的非錯誤回饋。對話會繼續,讓 Claude 可以據此採取動作,但與 `decision: "block"` 不同,它在逐字稿中會顯示為 hook 回饋,而非 hook 錯誤 |2986| `hookSpecificOutput.additionalContext` | 給 Claude 的非錯誤回饋。對話會繼續,讓 Claude 可據以行動,但與 `decision: "block"` 不同,它在逐字稿中會顯示為 hook 回饋,而非 hook 錯誤 |
2961 2987
2962以退出碼 2 封鎖的 hook 會以與 `reason` 相同的方式傳遞:Claude 會收到 stderr 訊息,作為它應該繼續的原因說明。2988以退出碼 2 封鎖的 hook 與 `reason` 的路由方式相同:Claude 會將 stderr 訊息作為其應繼續的原因說明。
2963 2989
2964```json theme={null}2990```json theme={null}
2965{2991{
2968}2994}
2969```2995```
2970 2996
2971當 hook 依設計運作並為 Claude 提供指引時,例如「在結束前執行測試套件」,請使用 `additionalContext`。它會透過與 `decision: "block"` 相同的迴圈保護機制(即 `stop_hook_active` 輸入與 8 次連續繼續上限)讓對話繼續,但逐字稿會將其標示為 `Stop hook feedback`,且不會顯示 hook 錯誤通知:2997當 hook 依設計運作並為 Claude 提供指引時(例如「完成前請執行測試套件」),請使用 `additionalContext`。它會透過與 `decision: "block"` 相同的迴圈保護機制讓對話繼續,也就是 `stop_hook_active` 輸入與 8 次連續繼續的上限,但逐字稿會將其標記為 `Stop hook feedback`,且不會顯示 hook 錯誤通知:
2972 2998
2973```json theme={null}2999```json theme={null}
2974{3000{
2983 StopFailure3009 StopFailure
2984</h3>3010</h3>
2985 3011
2986當回合因 API 錯誤而結束時,取代 [Stop](#stop) 執行。除了 [`terminalSequence`](#emit-terminal-notifications) 之外,Claude Code 會忽略此 hook 的輸出與退出碼。當 Claude 因速率限制、身分驗證問題或其他 API 錯誤而無法完成回應時,可用來記錄失敗、傳送警示或採取復原動作。3012當回合因 API 錯誤而結束時,取代 [Stop](#stop) 執行。除了 [`terminalSequence`](#emit-terminal-notifications) 之外,Claude Code 會忽略此 hook 的輸出與退出碼。當 Claude 因速率限制、身分驗證問題或其他 API 錯誤而無法完成回應時,可用於記錄失敗、傳送警示或採取復原動作。
2987 3013
2988<h4 id="stopfailure-input">3014<h4 id="stopfailure-input">
2989 StopFailure 輸入3015 StopFailure 輸入
2990</h4>3016</h4>
2991 3017
2992除了[共通輸入欄位](#common-input-fields)外,StopFailure hook 還會收到 `error`、選用的 `error_details`,以及選用的 `last_assistant_message`。`error` 欄位識別錯誤類型,並用於 matcher 篩選。3018除了[通用輸入欄位](#common-input-fields)之外,StopFailure hook 還會接收 `error`、選用的 `error_details`,以及選用的 `last_assistant_message`。`error` 欄位識別錯誤類型,並用於 matcher 篩選。
2993 3019
2994| 欄位 | 說明 |3020| 欄位 | 說明 |
2995| :- | :- |3021| :- | :- |
2996| `error` | 錯誤類型:`rate_limit`、`overloaded`、`authentication_failed`、`oauth_org_not_allowed`、`account_on_hold`、`billing_error`、`invalid_request`、`model_not_found`、`server_error`、`max_output_tokens`、`cloud_credential_error` 或 `unknown` |3022| `error` | 錯誤類型:`rate_limit`、`overloaded`、`authentication_failed`、`oauth_org_not_allowed`、`account_on_hold`、`billing_error`、`invalid_request`、`model_not_found`、`server_error`、`max_output_tokens`、`cloud_credential_error` 或 `unknown` |
2997| `error_details` | 關於錯誤的其他詳細資訊(若有) |3023| `error_details` | 關於錯誤的其他細節(若有) |
2998| `last_assistant_message` | 對話中顯示的已呈現錯誤文字。與 `Stop` 及 `SubagentStop` 中此欄位保存 Claude 的對話輸出不同,對於 `StopFailure`,它包含 API 錯誤字串本身,例如 `"API Error: Rate limit reached"` |3024| `last_assistant_message` | 對話中顯示的已呈現錯誤文字。與 `Stop` 和 `SubagentStop` 中此欄位保存 Claude 的對話輸出不同,對於 `StopFailure`,它包含 API 錯誤字串本身,例如 `"API Error: Rate limit reached"` |
2999 3025
3000```json theme={null}3026```json theme={null}
3001{3027{
3009}3035}
3010```3036```
3011 3037
3012StopFailure hook 沒有決策控制。它們僅用於通知與記錄日誌。3038StopFailure hook 沒有決策控制。它們僅用於通知與記錄目的。
3013 3039
3014<h3 id="teammateidle">3040<h3 id="teammateidle">
3015 TeammateIdle3041 TeammateIdle
3016</h3>3042</h3>
3017 3043
3018在 [agent team](/docs/zh-TW/agent-teams) 隊員結束其回合、即將進入閒置時執行。可用來在隊員停止工作前強制執行品質關卡,例如要求通過 lint 檢查或驗證輸出檔案存在。3044在 [agent team](/docs/zh-TW/agent-teams) 隊員結束其回合、即將進入閒置時執行。可用於在隊員停止工作前強制執行品質關卡,例如要求通過 lint 檢查或確認輸出檔案存在。
3019 3045
3020TeammateIdle hook 不支援 matcher,每次發生時都會觸發。3046TeammateIdle hook 不支援 matcher,每次發生時都會觸發。
3021 3047
3023 TeammateIdle 輸入3049 TeammateIdle 輸入
3024</h4>3050</h4>
3025 3051
3026除了[共通輸入欄位](#common-input-fields)外,TeammateIdle hook 還會收到 `teammate_name` 與 `team_name`。3052除了[通用輸入欄位](#common-input-fields)之外,TeammateIdle hook 還會接收 `teammate_name` 與 `team_name`。
3027 3053
3028```json theme={null}3054```json theme={null}
3029{3055{
3040| 欄位 | 說明 |3066| 欄位 | 說明 |
3041| :- | :- |3067| :- | :- |
3042| `teammate_name` | 即將進入閒置之隊員的名稱 |3068| `teammate_name` | 即將進入閒置之隊員的名稱 |
3043| `team_name` | 已棄用。衍生自工作階段的團隊名稱;將在未來的版本中移除 |3069| `team_name` | 已棄用。衍生自工作階段的團隊名稱;將在未來版本中移除 |
3044| `agent_id` | 在此事件中,此[共通輸入欄位](#common-input-fields)識別即將進入閒置的[程序內隊員](/docs/zh-TW/agent-teams#choose-a-display-mode)。可能不存在。需要 Claude Code v2.1.290 或更新版本 |3070| `agent_id` | 在此事件中,此[通用輸入欄位](#common-input-fields)識別即將進入閒置的[程序內隊員](/docs/zh-TW/agent-teams#choose-a-display-mode)。可能不存在。需要 Claude Code v2.1.290 或更新版本 |
3045 3071
3046<h4 id="teammateidle-decision-control">3072<h4 id="teammateidle-decision-control">
3047 TeammateIdle 決策控制3073 TeammateIdle 決策控制
3049 3075
3050TeammateIdle hook 支援兩種控制隊員行為的方式:3076TeammateIdle hook 支援兩種控制隊員行為的方式:
3051 3077
3052* **退出碼 2**:隊員會收到 stderr 訊息作為回饋,並繼續工作而不進入閒置。3078* **退出碼 2**:隊員會接收 stderr 訊息作為回饋,並繼續工作而非進入閒置。
3053* **JSON `{"continue": false, "stopReason": "..."}`**:完全停止該隊員,行為與 `Stop` hook 相同。`stopReason` 會顯示給使用者。3079* **JSON `{"continue": false, "stopReason": "..."}`**:完全停止該隊員,與 `Stop` hook 的行為一致。`stopReason` 會顯示給使用者。
3054 3080
3055以下範例會在允許隊員進入閒置前,檢查建置產物是否存在:3081以下範例會在允許隊員進入閒置之前,檢查建置產物是否存在:
3056 3082
3057```bash theme={null}3083```bash theme={null}
3058#!/bin/bash3084#!/bin/bash
3069 ConfigChange3095 ConfigChange
3070</h3>3096</h3>
3071 3097
3072在工作階段期間設定檔變更時執行。可用來稽核設定變更、強制執行安全政策,或封鎖對設定檔未經授權的修改。3098在工作階段期間設定檔變更時執行。可用於稽核設定變更、強制執行安全政策,或封鎖對設定檔的未經授權修改。
3073 3099
3074當設定檔、受管政策檔或 skill 檔案變更時,Claude Code 會執行 ConfigChange hook。對於受管政策,只有在 `managed-settings.json` 或 `managed-settings.d/` 中的檔案變更時才會執行。對於[伺服器受管設定](/docs/zh-TW/server-managed-settings),以及對 macOS 受管偏好設定或 Windows 登錄政策的變更,它會直接套用而不執行這些 hook。在啟用 [`wslInheritsWindowsSettings`](/docs/zh-TW/settings-reference#wslinheritswindowssettings) 的 WSL 上,它也會在其政策輪詢時套用變更後的 Windows 端受管設定檔,而不執行這些 hook。3100當設定檔、受管政策檔案或 skill 檔案變更時,Claude Code 會執行 ConfigChange hook。對於受管政策,只有在 `managed-settings.json` 或 `managed-settings.d/` 中的檔案變更時才會執行。它會套用[伺服器受管設定](/docs/zh-TW/server-managed-settings)以及 macOS 受管偏好設定或 Windows 登錄政策的變更,但不會執行這些 hook。在啟用 [`wslInheritsWindowsSettings`](/docs/zh-TW/settings-reference#wslinheritswindowssettings) 的 WSL 上,它也會在政策輪詢時套用已變更的 Windows 端受管設定檔,而不執行這些 hook。
3075 3101
3076matcher 會依設定來源進行篩選:3102matcher 依設定來源進行篩選:
3077 3103
3078| Matcher | 觸發時機 |3104| Matcher | 觸發時機 |
3079| :- | :- |3105| :- | :- |
3107 ConfigChange 輸入3133 ConfigChange 輸入
3108</h4>3134</h4>
3109 3135
3110除了[共通輸入欄位](#common-input-fields)外,ConfigChange hook 還會收到 `source`,以及選用的 `file_path`。`source` 欄位指出變更的是哪種設定類型,`file_path` 則提供被修改之特定檔案的路徑。3136除了[通用輸入欄位](#common-input-fields)之外,ConfigChange hook 還會接收 `source` 以及選用的 `file_path`。`source` 欄位指出變更的設定類型,而 `file_path` 提供被修改之特定檔案的路徑。
3111 3137
3112```json theme={null}3138```json theme={null}
3113{3139{
3124 ConfigChange 決策控制3150 ConfigChange 決策控制
3125</h4>3151</h4>
3126 3152
3127ConfigChange hook 可以阻止設定變更生效。使用退出碼 2 或 JSON `decision` 即可阻止變更。遭封鎖時,新的設定不會套用到執行中的工作階段。3153ConfigChange hook 可以封鎖設定變更使其不生效。使用退出碼 2 或 JSON `decision` 即可阻止變更。遭封鎖時,新設定不會套用至正在執行的工作階段。
3128 3154
3129| 欄位 | 說明 |3155| 欄位 | 說明 |
3130| :- | :- |3156| :- | :- |
3138}3164}
3139```3165```
3140 3166
3141`policy_settings` 的變更無法被封鎖。當電腦上的受管設定檔變更時,hook 仍會針對 `policy_settings` 來源觸發,因此您可以用它們記錄這些編輯,但任何封鎖決策都會被忽略。這可確保企業受管設定一律生效。當[伺服器受管設定](/docs/zh-TW/server-managed-settings)抵達或重新整理時,Claude Code 不會執行 `ConfigChange` hook。3167`policy_settings` 變更無法被封鎖。當機器上的受管設定檔變更時,hook 仍會針對 `policy_settings` 來源觸發,因此您可以用它們記錄這些編輯,但任何封鎖決策都會被忽略。這可確保企業受管設定一律生效。當[伺服器受管設定](/docs/zh-TW/server-managed-settings)抵達或重新整理時,Claude Code 不會執行 `ConfigChange` hook。
3142 3168
3143Claude Code 會依據 ConfigChange hook JSON 輸出中的封鎖決策採取動作,並捨棄 `systemMessage` 與 `continue`。無論您是以 `reason` 還是以退出碼 2 時的 stderr 封鎖,遭封鎖的變更都不會向您或 Claude 顯示任何訊息。Claude Code 只會在偵錯日誌中寫入一行。3169Claude Code 會依據 ConfigChange hook JSON 輸出中的封鎖決策採取行動,並捨棄 `systemMessage` 與 `continue`。無論您是以 `reason` 封鎖,還是以退出碼 2 搭配 stderr 封鎖,被封鎖的變更都不會向您或 Claude 顯示任何訊息。Claude Code 只會在除錯日誌中寫入一行。
3144 3170
3145<h3 id="cwdchanged">3171<h3 id="cwdchanged">
3146 CwdChanged3172 CwdChanged
3147</h3>3173</h3>
3148 3174
3149在主對話中的 shell 命令變更工作目錄時執行,例如 Claude 執行 `cd` 命令時。可用來回應目錄變更:重新載入環境變數、啟用專案專屬的工具鏈,或自動執行設定指令碼。可與 [FileChanged](#filechanged) 搭配,用於像 [direnv](https://direnv.net/) 這類管理各目錄環境的工具。3175當主對話中的 shell 命令變更工作目錄時執行,例如 Claude 執行 `cd` 命令時。可用於對目錄變更做出反應:重新載入環境變數、啟用專案專屬的工具鏈,或自動執行設定指令碼。可與 [FileChanged](#filechanged) 搭配,用於 [direnv](https://direnv.net/) 等管理各目錄環境的工具。
3150 3176
3151CwdChanged hook 可以存取 [`CLAUDE_ENV_FILE`](#persist-environment-variables)。寫入該檔案的變數會延續到後續的 Bash 命令中,直到下一次 CwdChanged 事件時由 Claude Code 清除。3177CwdChanged hook 可以存取 [`CLAUDE_ENV_FILE`](#persist-environment-variables)。寫入該檔案的變數會保留至後續的 Bash 命令中,直到下一個 CwdChanged 事件時由 Claude Code 清除。
3152 3178
3153CwdChanged 不支援 matcher,每次發生時都會觸發。3179CwdChanged 不支援 matcher,每次發生時都會觸發。
3154 3180
3156 CwdChanged 輸入3182 CwdChanged 輸入
3157</h4>3183</h4>
3158 3184
3159除了[共通輸入欄位](#common-input-fields)外,CwdChanged hook 還會收到 `old_cwd` 與 `new_cwd`。3185除了[通用輸入欄位](#common-input-fields)之外,CwdChanged hook 還會接收 `old_cwd` 與 `new_cwd`。
3160 3186
3161```json theme={null}3187```json theme={null}
3162{3188{
3173 CwdChanged 輸出3199 CwdChanged 輸出
3174</h4>3200</h4>
3175 3201
3176除了所有 hook 皆可使用的 [JSON 輸出欄位](#json-output)外,CwdChanged hook 還可以回傳 `watchPaths`,以動態設定 [FileChanged](#filechanged) 要監看哪些檔案路徑:3202除了所有 hook 都可使用的 [JSON 輸出欄位](#json-output)之外,CwdChanged hook 還可以回傳 `watchPaths`,以動態設定 [FileChanged](#filechanged) 要監看的檔案路徑:
3177 3203
3178| 欄位 | 說明 |3204| 欄位 | 說明 |
3179| :- | :- |3205| :- | :- |
3180| `watchPaths` | 絕對路徑的陣列。會取代目前的動態監看清單。來自您 `matcher` 設定的路徑一律會被監看。回傳空陣列會清除動態清單,這在進入新目錄時很常見 |3206| `watchPaths` | 絕對路徑的陣列。取代目前的動態監看清單。來自您 `matcher` 設定的路徑一律會被監看。回傳空陣列會清除動態清單,這在進入新目錄時很常見 |
3181 3207
3182CwdChanged hook 沒有決策控制。它們無法封鎖目錄變更。3208CwdChanged hook 沒有決策控制。它們無法封鎖目錄變更。
3183 3209
3184Claude Code 會從其 JSON 輸出中讀取 `watchPaths` 與 `systemMessage`,並捨棄 `continue`。在互動式工作階段中,它會將 `systemMessage` 顯示為簡短的終端機通知。該訊息不會傳到 SDK 訊息串流。3210Claude Code 會從其 JSON 輸出中讀取 `watchPaths` 與 `systemMessage`,並捨棄 `continue`。在互動式工作階段中,它會將 `systemMessage` 顯示為簡短的終端機通知。該訊息不會進入 SDK 訊息串流。
3185 3211
3186<h3 id="directoryadded">3212<h3 id="directoryadded">
3187 DirectoryAdded3213 DirectoryAdded
3188</h3>3214</h3>
3189 3215
3190在您於工作階段中途以 `/add-dir` 命令新增工作目錄後,或在 SDK 用戶端以 `register_repo_root` 控制請求新增工作目錄後執行。可用來準備新加入的儲存庫,例如安裝其相依套件。3216在您於工作階段中途使用 `/add-dir` 命令新增工作目錄後,或在 SDK 用戶端以 `register_repo_root` 控制請求新增工作目錄後執行。可用於準備新加入的儲存庫,例如安裝其相依套件。
3191 3217
3192在下列情況中,Claude Code 不會觸發此事件:3218在以下情況下,Claude Code 不會觸發此事件:
3193 3219
3194* 您以 `--add-dir` 啟動旗標傳入目錄;這些目錄由 [SessionStart](#sessionstart) 涵蓋3220* 您透過 `--add-dir` 啟動旗標傳入目錄;[SessionStart](#sessionstart) 涵蓋這些目錄
3195* 您在 `/permissions` 的 Workspace 分頁中新增目錄3221* 您在 `/permissions` 的 Workspace 分頁上新增目錄
3196* 您新增的目錄已經是工作目錄,或位於工作目錄內3222* 您新增的目錄已經是工作目錄或位於工作目錄之內
3197 3223
3198Claude Code 會在重新整理沙箱與權限狀態後觸發 DirectoryAdded,因此當您的 hook 執行時,沙箱化的工具已經能看到新目錄。hook 命令本身則在沙箱之外執行。3224Claude Code 會在重新整理沙箱與權限狀態之後觸發 DirectoryAdded,因此當您的 hook 執行時,沙箱化的工具已能看到新目錄。hook 命令本身則在沙箱外執行。
3199 3225
3200Claude Code 不會等待 hook:新增動作會立即完成,而 hook 會以 600 秒的預設逾時在背景執行。3226Claude Code 不會等待 hook:新增動作會立即完成,而 hook 會在背景以預設的 600 秒逾時執行。
3201 3227
3202matcher 會依目錄的新增方式進行篩選:3228matcher 依目錄的新增方式進行篩選:
3203 3229
3204| Matcher | 觸發時機 |3230| Matcher | 觸發時機 |
3205| :- | :- |3231| :- | :- |
3206| `slash_command` | 您以 `/add-dir` 新增目錄 |3232| `slash_command` | 您使用 `/add-dir` 新增目錄 |
3207| `register_repo_root` | SDK 用戶端以 `register_repo_root` 控制請求新增目錄 |3233| `register_repo_root` | SDK 用戶端以 `register_repo_root` 控制請求新增目錄 |
3208 3234
3209<h4 id="directoryadded-input">3235<h4 id="directoryadded-input">
3210 DirectoryAdded 輸入3236 DirectoryAdded 輸入
3211</h4>3237</h4>
3212 3238
3213除了[共通輸入欄位](#common-input-fields)外,DirectoryAdded hook 還會收到 `directory` 與 `source`。3239除了[通用輸入欄位](#common-input-fields)之外,DirectoryAdded hook 還會接收 `directory` 與 `source`。
3214 3240
3215| 欄位 | 說明 |3241| 欄位 | 說明 |
3216| :- | :- |3242| :- | :- |
3228}3254}
3229```3255```
3230 3256
3231DirectoryAdded hook 沒有決策控制。它們無法封鎖新增動作,因為 hook 執行時新增動作已經完成。Claude Code 會捨棄其 JSON 輸出中的 `continue` 欄位,並依來源以不同方式呈現其餘內容:3257DirectoryAdded hook 沒有決策控制。它們無法封鎖新增動作,因為在 hook 執行時新增已經完成。Claude Code 會捨棄其 JSON 輸出中的 `continue` 欄位,並依來源以不同方式呈現其餘部分:
3232 3258
3233* `slash_command`:Claude Code 會在下一個對話回合中,將 hook 的 `systemMessage` 作為上下文傳遞給 Claude,而不是顯示給您。逐字稿中會顯示失敗 hook 的數量。完整的失敗輸出會寫入偵錯日誌3259* `slash_command`:Claude Code 會在下一個對話回合將 hook 的 `systemMessage` 作為上下文傳遞給 Claude,而不是顯示給您。失敗 hook 的數量會顯示在逐字稿中。完整的失敗輸出會寫入除錯日誌
3234* `register_repo_root`:Claude Code 只會將 `systemMessage` 輸出與失敗輸出寫入偵錯日誌3260* `register_repo_root`:Claude Code 只會將 `systemMessage` 輸出與失敗輸出寫入除錯日誌
3235 3261
3236<h3 id="filechanged">3262<h3 id="filechanged">
3237 FileChanged3263 FileChanged
3238</h3>3264</h3>
3239 3265
3240在受監看的檔案於磁碟上變更時執行。Claude Code 是以檔案系統監看器偵測變更,而不是檢查工具呼叫,因此無論是什麼變更了檔案,它都會執行 hook:`Edit` 或 `Write` 工具呼叫、Claude 以 `Bash` 執行的指令碼,或完全在 Claude Code 之外的程序。常見用途是在專案設定檔變更時重新載入環境變數。3266在受監看的檔案於磁碟上發生變更時執行。Claude Code 透過檔案系統監看器偵測變更,而非檢查工具呼叫,因此無論是什麼變更了該檔案,它都會執行 hook:`Edit` 或 `Write` 工具呼叫、Claude 以 `Bash` 執行的指令碼,或完全在 Claude Code 之外的程序。常見的用途是在專案設定檔變更時重新載入環境變數。
3241 3267
3242此事件的 `matcher` 有兩個作用:3268此事件的 `matcher` 具有兩種作用:
3243 3269
3244* **建立監看清單**:該值會以 `|` 分割,每個片段都會被註冊為工作目錄中的字面檔案名稱,因此 `".envrc|.env"` 會恰好監看這兩個檔案。正規表示式模式在此沒有用處:像 `^\.env` 這樣的值會監看一個名稱字面上為 `^\.env` 的檔案。3270* **建立監看清單**:該值會以 `|` 分割,每個片段都會被註冊為工作目錄中的字面檔名,因此 `".envrc|.env"` 會精確監看這兩個檔案。正規表示式在此沒有用處:像 `^\.env` 這樣的值會監看一個字面名稱為 `^\.env` 的檔案。
3245* **篩選要執行的 hook**:當受監看的檔案變更時,同一個值會依據標準的 [matcher 規則](#matcher-patterns),針對變更檔案的基本名稱篩選要執行哪些 hook 群組。3271* **篩選要執行的 hook**:當受監看的檔案變更時,同一個值會依據標準的 [matcher 規則](#matcher-patterns),針對變更檔案的基本名稱篩選要執行哪些 hook 群組。
3246 3272
3247以下範例會在 `data.csv` 發生任何變更後(包括 `Bash` 命令或外部指令碼重寫該檔案)正規化其換行字元:3273此範例會在任何變更之後(包括 `Bash` 命令或外部指令碼改寫該檔案)正規化 `data.csv` 中的行尾字元:
3248 3274
3249```json theme={null}3275```json theme={null}
3250{3276{
3264}3290}
3265```3291```
3266 3292
3267hook 會從 stdin 上 [JSON 輸入](#filechanged-input)的 `file_path` 欄位讀取變更檔案的絕對路徑。其 `grep` 防護條件檢查的正是 `perl` 移除的內容,也就是行尾的 CR,因此正規化之後的那次執行會直接結束而不碰觸檔案。較寬鬆的防護條件會造成無限迴圈,因為即使 `perl -i` 沒有替換任何內容,它仍會重寫檔案,而 Claude Code 在每次重寫後都會再次執行 hook。請將此指令碼儲存於 `/path/to/normalize-line-endings.sh` 並設為可執行:3293此 hook 會從 stdin 上 [JSON 輸入](#filechanged-input)的 `file_path` 欄位讀取變更檔案的絕對路徑。它的 `grep` 防護條件所檢查的,正是 `perl` 所移除的內容,也就是行尾的 CR,因此正規化之後的那次執行會直接結束而不觸碰該檔案。較寬鬆的防護條件會造成無限迴圈,因為即使 `perl -i` 沒有取代任何內容也會改寫檔案,而 Claude Code 會在每次改寫後再次執行此 hook。請將此指令碼儲存於 `/path/to/normalize-line-endings.sh` 並設為可執行:
3268 3294
3269```bash theme={null}3295```bash theme={null}
3270#!/bin/bash3296#!/bin/bash
3274fi3300fi
3275```3301```
3276 3302
3277若要確認 hook 是否運作,請要求 Claude 以 `Bash` 命令在 `data.csv` 末尾附加一行 CRLF。Claude Code 會執行 hook,檔案最後會變成 LF 換行。3303若要確認 hook 是否正常運作,請要求 Claude 以 `Bash` 命令在 `data.csv` 附加一行 CRLF。Claude Code 會執行此 hook,檔案最終會使用 LF 行尾。
3278 3304
3279若要監看無法事先指名的檔案,請從 hook 回傳 [`watchPaths`](#filechanged-output) 以動態更新監看清單。Claude Code 只有在有東西指名要監看的檔案時才會啟動監看器,因此請以 matcher 至少指名一個檔案的 FileChanged 群組,或以回傳 `watchPaths` 的 [SessionStart](#sessionstart-decision-control) 或 [CwdChanged](#cwdchanged) hook 來初始化清單。當受監看的檔案變更時,matcher 仍會篩選要執行哪些 hook 群組,因此請讓處理動態路徑的群組省略 matcher,這樣它會比對每個受監看的檔案,且不會在監看清單中新增任何項目。`"*"` matcher 也會比對每個檔案,但 Claude Code 會像處理其他值一樣將它註冊到監看清單中,作為一個名為 `*` 的字面檔案。3305若要監看無法事先指名的檔案,請從 hook 傳回 [`watchPaths`](#filechanged-output) 以動態更新監看清單。Claude Code 只有在有東西指名要監看的檔案時才會啟動監看器,因此請以一個 matcher 至少指名一個檔案的 FileChanged 群組,或以傳回 `watchPaths` 的 [SessionStart](#sessionstart-decision-control) 或 [CwdChanged](#cwdchanged) hook 來初始化清單。當受監看的檔案變更時,matcher 仍會篩選要執行哪些 hook 群組,因此請讓處理動態路徑的群組省略 matcher,這樣它會符合每個受監看的檔案,且不會在監看清單中新增任何項目。`"*"` matcher 同樣會符合每個檔案,但 Claude Code 會像處理其他值一樣將其註冊到監看清單中,成為一個字面名稱為 `*` 的檔案。
3280 3306
3281FileChanged hook 可以存取 [`CLAUDE_ENV_FILE`](#persist-environment-variables)。寫入該檔案的變數會延續到後續的 Bash 命令中,直到下一次 [CwdChanged](#cwdchanged) 事件時由 Claude Code 清除。3307FileChanged hook 可以存取 [`CLAUDE_ENV_FILE`](#persist-environment-variables)。寫入該檔案的變數會持續套用到後續的 Bash 命令,直到下一次 [CwdChanged](#cwdchanged) 事件發生時由 Claude Code 清除為止。
3282 3308
3283<h4 id="filechanged-input">3309<h4 id="filechanged-input">
3284 FileChanged 輸入3310 FileChanged 輸入
3285</h4>3311</h4>
3286 3312
3287除了[共通輸入欄位](#common-input-fields)外,FileChanged hook 還會收到 `file_path` 與 `event`。3313除了[通用輸入欄位](#common-input-fields)之外,FileChanged hook 還會收到 `file_path` 與 `event`。
3288 3314
3289| 欄位 | 說明 |3315| 欄位 | 說明 |
3290| :- | :- |3316| :- | :- |
3291| `file_path` | 變更之檔案的絕對路徑 |3317| `file_path` | 變更檔案的絕對路徑 |
3292| `event` | 發生的情況:修改檔案為 `"change"`,建立檔案為 `"add"`,刪除檔案為 `"unlink"` |3318| `event` | 發生的情況:`"change"` 表示檔案已修改,`"add"` 表示檔案已建立,`"unlink"` 表示檔案已刪除 |
3293 3319
3294```json theme={null}3320```json theme={null}
3295{3321{
3306 FileChanged 輸出3332 FileChanged 輸出
3307</h4>3333</h4>
3308 3334
3309除了所有 hook 皆可使用的 [JSON 輸出欄位](#json-output)外,FileChanged hook 還可以回傳 `watchPaths`,以動態更新要監看哪些檔案路徑:3335除了所有 hook 皆可使用的 [JSON 輸出欄位](#json-output)之外,FileChanged hook 還可以傳回 `watchPaths`,以動態更新要監看的檔案路徑:
3310 3336
3311| 欄位 | 說明 |3337| 欄位 | 說明 |
3312| :- | :- |3338| :- | :- |
3313| `watchPaths` | 絕對路徑的陣列。會取代目前的動態監看清單。來自您 `matcher` 設定的路徑一律會被監看。當您的 hook 指令碼根據變更的檔案發現其他要監看的檔案時,請使用此欄位 |3339| `watchPaths` | 絕對路徑的陣列。會取代目前的動態監看清單。來自您 `matcher` 設定的路徑一律會被監看。當您的 hook 指令碼根據變更的檔案發現其他需要監看的檔案時,請使用此欄位 |
3314 3340
3315FileChanged hook 沒有決策控制。它們無法阻止檔案變更發生。3341FileChanged hook 沒有決策控制。它們無法阻止檔案變更發生。
3316 3342
3317Claude Code 會從其 JSON 輸出中讀取 `watchPaths` 與 `systemMessage`,並捨棄 `continue`。在互動式工作階段中,它會將 `systemMessage` 顯示為簡短的終端機通知。該訊息不會傳到 SDK 訊息串流。3343Claude Code 會從其 JSON 輸出讀取 `watchPaths` 與 `systemMessage`,並捨棄 `continue`。在互動式工作階段中,它會將 `systemMessage` 顯示為簡短的終端機通知。該訊息不會傳送到 SDK 訊息串流。
3318 3344
3319<h3 id="worktreecreate">3345<h3 id="worktreecreate">
3320 WorktreeCreate3346 WorktreeCreate
3322 3348
3323在 Claude Code 建立 worktree 時執行,例如以下情況:3349在 Claude Code 建立 worktree 時執行,例如以下情況:
3324 3350
3325* 您使用 `claude --worktree` 啟動工作階段3351* 您以 `claude --worktree` 啟動工作階段
3326* Claude 在工作階段中建立 worktree,並使用 [`EnterWorktree`](/docs/zh-TW/tools-reference) 工具切換進入3352* Claude 在工作階段期間建立 worktree,並以 [`EnterWorktree`](/docs/zh-TW/tools-reference) 工具切換進入
3327* [subagent 使用 `isolation: "worktree"`](/docs/zh-TW/sub-agents#choose-the-subagent-scope)3353* [subagent 使用 `isolation: "worktree"`](/docs/zh-TW/sub-agents#choose-the-subagent-scope)
3328* [工作流程](/docs/zh-TW/workflows#migrate-many-files-in-parallel)在其自己的 worktree 中執行 agent3354* [工作流程](/docs/zh-TW/workflows#migrate-many-files-in-parallel)在自己的 worktree 中執行 agent
3329* Claude Code 將[背景工作階段](/docs/zh-TW/agent-view#how-file-edits-are-isolated)隔離在其自己的 worktree 中3355* Claude Code 將[背景工作階段](/docs/zh-TW/agent-view#how-file-edits-are-isolated)隔離在其自己的 worktree 中
3330* `worktree` 模式下的 [`claude remote-control`](/docs/zh-TW/remote-control#start-a-remote-control-session) 在其自己的 worktree 中啟動工作階段3356* `worktree` 模式下的 [`claude remote-control`](/docs/zh-TW/remote-control#start-a-remote-control-session) 在自己的 worktree 中啟動工作階段
3331 3357
3332當 Claude 透過 Bash 工具執行 `git worktree add` 而非呼叫 `EnterWorktree` 時,您的 WorktreeCreate hook 不會執行。若要檢查或封鎖該命令,請新增一個使用 `Bash` matcher 的 [`PreToolUse`](#pretooluse) hook。3358當 Claude 透過 Bash 工具執行 `git worktree add`,而非呼叫 `EnterWorktree` 時,您的 WorktreeCreate hook 不會執行。若要檢查或封鎖該命令,請新增一個使用 `Bash` matcher 的 [`PreToolUse`](#pretooluse) hook。
3333 3359
3334預設情況下,Claude Code 會使用 `git worktree` 建立隔離的工作副本。設定 WorktreeCreate hook 會取代該預設的 git 行為,讓您可以使用不同的版本控制系統,例如 SVN、Perforce 或 Mercurial。3360根據預設,Claude Code 會使用 `git worktree` 建立隔離的工作副本。設定 WorktreeCreate hook 會取代該預設的 git 行為,讓您可以使用其他版本控制系統,例如 SVN、Perforce 或 Mercurial。
3335 3361
3336由於 hook 會完全取代預設行為,因此不會處理 [`.worktreeinclude`](/docs/zh-TW/worktrees#copy-gitignored-files-into-worktrees)。如果需要將 `.env` 等本機設定檔複製到新的 worktree 中,請在 hook 腳本內執行此操作。3362由於此 hook 會完全取代預設行為,因此不會處理 [`.worktreeinclude`](/docs/zh-TW/worktrees#copy-gitignored-files-into-worktrees)。如果您需要將 `.env` 等本機設定檔複製到新的 worktree,請在 hook 指令碼中完成。
3337 3363
3338hook 必須回傳所建立之 worktree 目錄的路徑。Claude Code 會將此路徑用作隔離工作階段的工作目錄。關於每種 hook 類型如何回傳路徑,請參閱 [WorktreeCreate 輸出](#worktreecreate-output)。3364此 hook 必須傳回所建立之 worktree 目錄的路徑。Claude Code 會將此路徑用作隔離工作階段的工作目錄。關於各 hook 類型如何傳回路徑,請參閱 [WorktreeCreate 輸出](#worktreecreate-output)。
3339 3365
3340Claude Code 會依據 hook 是否成功以及回傳的路徑採取行動,並捨棄 `systemMessage` 和 `continue`。3366Claude Code 會依據 hook 是否成功以及傳回的路徑採取動作,並捨棄 `systemMessage` 與 `continue`。
3341 3367
3342此範例會建立 SVN 工作副本,並印出供 Claude Code 使用的路徑。請將儲存庫 URL 替換為您自己的 URL:3368此範例會建立 SVN 工作副本,並印出路徑供 Claude Code 使用。請將儲存庫 URL 替換為您自己的:
3343 3369
3344```json theme={null}3370```json theme={null}
3345{3371{
3358}3384}
3359```3385```
3360 3386
3361此 hook 會從 stdin 上的 JSON 輸入讀取 worktree 的 `name`,將全新副本 checkout 至新目錄,並印出目錄路徑。最後一行的 `echo` 就是 Claude Code 讀取為 worktree 路徑的內容。請將其他任何輸出重新導向至 stderr,以免干擾路徑。3387此 hook 會從 stdin 上的 JSON 輸入讀取 worktree 的 `name`,將全新副本簽出到新目錄,並印出該目錄路徑。最後一行的 `echo` 就是 Claude Code 讀取為 worktree 路徑的內容。請將其他任何輸出重新導向至 stderr,以免干擾該路徑。
3362 3388
3363<h4 id="worktreecreate-input">3389<h4 id="worktreecreate-input">
3364 WorktreeCreate 輸入3390 WorktreeCreate 輸入
3365</h4>3391</h4>
3366 3392
3367除了[通用輸入欄位](#common-input-fields)之外,WorktreeCreate hook 還會收到 `name` 欄位。這是新 worktree 的 slug 識別碼,可由使用者指定或自動產生,例如 `bold-oak-a3f2`。3393除了[通用輸入欄位](#common-input-fields)之外,WorktreeCreate hook 還會收到 `name` 欄位。這是新 worktree 的 slug 識別碼,可能由使用者指定或自動產生,例如 `bold-oak-a3f2`。
3368 3394
3369```json theme={null}3395```json theme={null}
3370{3396{
3380 WorktreeCreate 輸出3406 WorktreeCreate 輸出
3381</h4>3407</h4>
3382 3408
3383WorktreeCreate hook 不使用標準的允許/封鎖決策模型,而是由 hook 的成功或失敗決定結果。hook 必須回傳所建立之 worktree 目錄的路徑:3409WorktreeCreate hook 不使用標準的允許/封鎖決策模型。取而代之的是,由 hook 的成功或失敗決定結果。此 hook 必須傳回所建立之 worktree 目錄的路徑:
3384 3410
3385* **命令 hook**(`type: "command"`):將路徑印為 stdout 的最後一個非空白行。Claude Code 在讀取該行之前會移除 ANSI 跳脫碼,因此在您的 `echo` 之前印出的 shell 啟動橫幅會被忽略。請將其他任何 hook 輸出重新導向至 stderr。3411* **命令 hook**(`type: "command"`):將路徑印為 stdout 的最後一個非空白行。Claude Code 會在讀取該行之前移除 ANSI 跳脫碼,因此在您的 `echo` 之前印出的 shell 啟動橫幅會被忽略。請將其他任何 hook 輸出重新導向至 stderr。
3386* **HTTP hook**(`type: "http"`):在回應主體中回傳 `{ "hookSpecificOutput": { "hookEventName": "WorktreeCreate", "worktreePath": "/absolute/path" } }`。3412* **HTTP hook**(`type: "http"`):在回應主體中傳回 `{ "hookSpecificOutput": { "hookEventName": "WorktreeCreate", "worktreePath": "/absolute/path" } }`。
3387 3413
3388如果 hook 失敗或未產生路徑,worktree 建立會失敗並顯示錯誤。3414如果 hook 失敗或未產生路徑,worktree 建立會以錯誤失敗。
3389 3415
3390Claude Code 會以 hook 執行時所在的目錄為基準解析相對路徑,並摺疊其中的任何 `.` 或 `..` 片段。如果解析後的路徑不是 Claude Code 可進入的目錄,工作階段會印出指出該路徑的錯誤,並以代碼 1 退出。3416Claude Code 會以 hook 執行時所在的目錄為基準解析相對路徑,並化簡其中的 `.` 或 `..` 片段。如果所得路徑不是 Claude Code 可以進入的目錄,工作階段會印出指名該路徑的錯誤,並以代碼 1 結束。
3391 3417
3392Claude Code 會拒絕包含 `.` 或 `..` 片段的絕對路徑,以及任何經過儲存庫根目錄下符號連結的路徑,因為提交至儲存庫的符號連結可能會將 worktree 重新導向至儲存庫之外。錯誤訊息會指出遭拒絕的路徑元件。請回傳未經過儲存庫內符號連結的正規化路徑。在 v2.1.216 之前,worktree 建立會直接依循 hook 的路徑,而不進行此檢查。3418Claude Code 會拒絕包含 `.` 或 `..` 片段的絕對路徑,以及任何經過儲存庫根目錄之下符號連結的路徑,因為提交到儲存庫的符號連結可能會將 worktree 重新導向到儲存庫之外。錯誤會指名被拒絕的路徑元件。請傳回一個不經過儲存庫內部符號連結的正規化路徑。在 v2.1.216 之前,worktree 建立會直接沿用 hook 的路徑,而不進行此項檢查。
3393 3419
3394<h3 id="worktreeremove">3420<h3 id="worktreeremove">
3395 WorktreeRemove3421 WorktreeRemove
3396</h3>3422</h3>
3397 3423
3398在 Claude Code 清理由您的 [`WorktreeCreate`](#worktreecreate) hook 所建立的 worktree 時執行。此事件會在下列情況觸發:3424在 Claude Code 清理由您的 [`WorktreeCreate`](#worktreecreate) hook 所建立的 worktree 時執行。此事件會在以下情況觸發:
3399 3425
3400* 您退出互動式 [worktree 工作階段](/docs/zh-TW/worktrees#start-claude-in-a-worktree),並在 Claude Code 提示時選擇移除 worktree3426* 您結束互動式 [worktree 工作階段](/docs/zh-TW/worktrees#start-claude-in-a-worktree),並在 Claude Code 提示時選擇移除 worktree
3401* 您退出尚未[命名](/docs/zh-TW/sessions#name-your-sessions)的互動式 worktree 工作階段,Claude Code 未發現任何已變更或未追蹤的檔案,並在不提示您的情況下移除 worktree3427* 您結束一個尚未[命名](/docs/zh-TW/sessions#name-your-sessions)的互動式 worktree 工作階段,Claude Code 沒有找到已變更或未追蹤的檔案,並在不提示您的情況下移除 worktree
3402* 您刪除在該 worktree 中執行的[背景工作階段](/docs/zh-TW/agent-view#what-deleting-a-session-removes)3428* 您刪除在該 worktree 中執行的[背景工作階段](/docs/zh-TW/agent-view#what-deleting-a-session-removes)
3403* 您在工作階段中要求 Claude 結束並移除 worktree,而 Claude 使用 [`ExitWorktree`](/docs/zh-TW/tools-reference) 工具將其移除3429* 您在工作階段期間要求 Claude 結束並移除 worktree,而 Claude 以 [`ExitWorktree`](/docs/zh-TW/tools-reference) 工具將其移除
3404* 由 [`claude remote-control`](/docs/zh-TW/remote-control#start-a-remote-control-session) 以 `worktree` 模式啟動的工作階段在未當機的情況下結束,且 Claude Code 在其 worktree 中未發現任何已變更或未追蹤的檔案,也沒有新的提交3430* 由 [`claude remote-control`](/docs/zh-TW/remote-control#start-a-remote-control-session) 以 `worktree` 模式啟動的工作階段在未當機的情況下結束,且 Claude Code 在其 worktree 中沒有找到已變更或未追蹤的檔案,也沒有新的提交
3405* 您在 `claude remote-control` 以 `worktree` 模式啟動的工作階段仍在執行時停止它,且 Claude Code 在其 worktree 中未發現任何已變更或未追蹤的檔案,也沒有新的提交3431* 您在 `claude remote-control` 以 `worktree` 模式啟動的工作階段仍在執行時停止它,且 Claude Code 在這些工作階段的 worktree 中沒有找到已變更或未追蹤的檔案,也沒有新的提交
3406 3432
3407當 subagent 或工作流程 agent 完成時,Claude Code 會保留您的 WorktreeCreate hook 為其建立的 worktree,且不會執行您的 WorktreeRemove hook。工作完成後,請自行移除這些 worktree。3433當 subagent 或工作流程 agent 完成時,Claude Code 會保留您的 WorktreeCreate hook 為其建立的 worktree,且不會執行您的 WorktreeRemove hook。請在工作完成後自行移除這些 worktree。
3408 3434
3409對於 `ExitWorktree` 呼叫或 `claude remote-control` 清理,Claude Code 不會在您的 hook 執行前提示您。除非呼叫傳入 [`discard_changes: true`](/docs/zh-TW/agent-sdk/typescript#exitworktree),否則 `ExitWorktree` 會拒絕移除由 hook 建立的 worktree,這使得您的 hook 成為該途徑上的最後一道檢查。3435對於 `ExitWorktree` 呼叫或 `claude remote-control` 清理,Claude Code 在您的 hook 執行前不會提示您。除非呼叫傳入 [`discard_changes: true`](/docs/zh-TW/agent-sdk/typescript#exitworktree),否則 `ExitWorktree` 會拒絕移除由 hook 建立的 worktree,這使得您的 hook 成為該途徑上的最後一道檢查。
3410 3436
3411Claude Code 使用 git 尋找已變更或未追蹤的檔案,因此在不是 git checkout 或不在 git checkout 內的 worktree 中,即使目錄包含未提交的工作,也不會找到任何檔案。請在 WorktreeRemove hook 刪除任何內容之前檢查這類工作。3437Claude Code 使用 git 尋找已變更或未追蹤的檔案,因此在不是 git 簽出(或不位於 git 簽出內)的 worktree 中,即使目錄中含有未提交的工作,它也找不到任何檔案。請在您的 WorktreeRemove hook 刪除任何內容之前檢查這類工作。
3412 3438
3413對於基於 git 的 worktree,Claude Code 會使用 `git worktree remove` 自動處理清理。如果您設定了 WorktreeCreate hook,請搭配 WorktreeRemove hook 來控制清理:3439對於以 git 為基礎的 worktree,Claude Code 會以 `git worktree remove` 自動處理清理。如果您設定了 WorktreeCreate hook,請搭配 WorktreeRemove hook 來控制清理:
3414 3440
3415* **沒有 WorktreeRemove hook**:對於結束時或透過 `ExitWorktree` 進行的移除,Claude Code 會改用 git;而在 `claude remote-control` 清理時則保留 worktree:3441* **沒有 WorktreeRemove hook**:對於結束時或透過 `ExitWorktree` 進行的移除,Claude Code 會改用 git;而在 `claude remote-control` 進行清理時則會保留 worktree:
3416 * **您結束 worktree 工作階段,或 Claude 呼叫 `ExitWorktree`**:Claude Code 會以類似 `git worktree remove --force` 的方式移除 WorktreeCreate hook 回傳的路徑,因此 git 可識別的 worktree 會被移除。git 無法識別的 worktree,例如您的 hook 使用非 git 版本控制系統建立的 worktree,會保留在磁碟上。3442 * **您結束 worktree 工作階段,或 Claude 呼叫 `ExitWorktree`**:Claude Code 會以如同 `git worktree remove --force` 的方式移除您的 WorktreeCreate hook 所傳回的路徑,因此 git 能識別的 worktree 會被移除。git 無法識別的 worktree(例如您的 hook 以非 git 版本控制系統建立的 worktree)則會保留在磁碟上。
3417 * **`claude remote-control` 清理工作階段的 worktree**:worktree 會保留在磁碟上,執行 `claude remote-control` 的終端機會顯示 `worktree removal failed, kept: <path>`。3443 * **`claude remote-control` 清理工作階段的 worktree**:worktree 會保留在磁碟上,且執行 `claude remote-control` 的終端機會顯示 `worktree removal failed, kept: <path>`。
3418 * **您刪除背景工作階段**:請參閱[刪除工作階段會移除的內容](/docs/zh-TW/agent-view#what-deleting-a-session-removes)。3444 * **您刪除背景工作階段**:請參閱[刪除工作階段會移除哪些內容](/docs/zh-TW/agent-view#what-deleting-a-session-removes)。
3419* **Hook 以 0 退出**:worktree 視為已移除。Claude Code 不會從 hook 讀取任何其他內容,因此請確保您的 hook 已刪除該目錄。3445* **Hook 以 0 結束**:worktree 會被視為已移除。Claude Code 不會從 hook 讀取其他任何內容,因此請確保您的 hook 已刪除該目錄。
3420* **Hook 以非零值退出**:如果 `worktree_path` 上的目錄在之後仍然存在,移除就會失敗,且 worktree 會留在磁碟上,不會改用 git。在以非零值退出之前已刪除目錄的 hook 視為已移除。關於失敗如何回報,請參閱 [WorktreeRemove 輸入](#worktreeremove-input)。3446* **Hook 以非零值結束**:如果 `worktree_path` 處的目錄之後仍然存在,移除即告失敗,worktree 會保留在磁碟上,且不會改用 git。在以非零值結束前已刪除目錄的 hook 會被視為已移除。關於失敗如何回報,請參閱 [WorktreeRemove 輸入](#worktreeremove-input)。
3421 3447
3422Claude Code 絕不會刪除屬於由 hook 建立之 worktree 的分支,因為它只知道您的 WorktreeCreate hook 所回傳的路徑。如果您的 WorktreeCreate hook 會建立分支,請在 WorktreeRemove hook 中刪除它。3448Claude Code 絕不會刪除屬於 hook 建立之 worktree 的分支,因為它只知道您的 WorktreeCreate hook 所傳回的路徑。如果您的 WorktreeCreate hook 會建立分支,請在您的 WorktreeRemove hook 中刪除它。
3423 3449
3424Claude Code 會捨棄 WorktreeRemove hook 的 [JSON 輸出欄位](#json-output),例如 `systemMessage` 和 `continue`。3450Claude Code 會捨棄 WorktreeRemove hook 的 [JSON 輸出欄位](#json-output),例如 `systemMessage` 與 `continue`。
3425 3451
3426對於背景工作階段的刪除,Claude Code 會在執行 hook 之前驗證儲存的 worktree 路徑,並拒絕本身是符號連結或經過儲存庫根目錄以下符號連結的路徑。在該途徑上,只有當您在 [agent view](/docs/zh-TW/agent-view#what-deleting-a-session-removes) 中確認刪除時,hook 才會針對仍含有檔案的 worktree 執行;對於這類 worktree,[`claude rm`](/docs/zh-TW/agent-view#manage-sessions-from-the-shell) 則會保留工作階段和 worktree。在 v2.1.216 之前,hook 會在不進行這些檢查的情況下對儲存的路徑執行。3452對於背景工作階段的刪除,Claude Code 會在執行 hook 前驗證所儲存的 worktree 路徑,並拒絕本身為符號連結或經過儲存庫根目錄之下符號連結的路徑。在該途徑上,只有當您在 [agent view](/docs/zh-TW/agent-view#what-deleting-a-session-removes) 中確認刪除時,hook 才會針對仍包含檔案的 worktree 執行;對於此類 worktree,[`claude rm`](/docs/zh-TW/agent-view#manage-sessions-from-the-shell) 則會保留工作階段與 worktree。在 v2.1.216 之前,hook 會在未經這些檢查的情況下針對所儲存的路徑執行。
3427 3453
3428Claude Code 會將 WorktreeCreate 回傳的路徑作為 `worktree_path` 傳入 hook 輸入。此範例會讀取該路徑並移除目錄:3454Claude Code 會將 WorktreeCreate 傳回的路徑作為 hook 輸入中的 `worktree_path` 傳入。此範例會讀取該路徑並移除目錄:
3429 3455
3430```json theme={null}3456```json theme={null}
3431{3457{
3448 WorktreeRemove 輸入3474 WorktreeRemove 輸入
3449</h4>3475</h4>
3450 3476
3451除了[通用輸入欄位](#common-input-fields)之外,WorktreeRemove hook 還會收到 `worktree_path` 欄位,這是要移除之 worktree 的絕對路徑。3477除了[通用輸入欄位](#common-input-fields)之外,WorktreeRemove hook 還會收到 `worktree_path` 欄位,也就是要移除之 worktree 的絕對路徑。
3452 3478
3453```json theme={null}3479```json theme={null}
3454{3480{
3460}3486}
3461```3487```
3462 3488
3463WorktreeRemove hook 的退出碼決定結果。當 hook 以非零值退出,且 `worktree_path` 上的目錄在之後仍然存在時,移除就會失敗:3489WorktreeRemove hook 的退出碼決定結果。當 hook 以非零值結束,且 `worktree_path` 處的目錄之後仍然存在時,移除即告失敗:
3464 3490
3465* worktree 會留在磁碟上,且 hook 的命令和 stderr 會寫入[偵錯日誌](#debug-hooks)。3491* worktree 會保留在磁碟上,hook 的命令與 stderr 會寫入[偵錯日誌](#debug-hooks)。
3466* 如果您當時正在刪除背景工作階段,該工作階段也會保留。[agent view](/docs/zh-TW/agent-view#what-deleting-a-session-removes) 中的拒絕訊息會回報 hook 的結束方式(例如 `exited 1`)、引用其 stderr 的開頭,並說明再次刪除工作階段是否仍會移除該目錄。3492* 如果您當時正在刪除背景工作階段,該工作階段也會保留。[agent view](/docs/zh-TW/agent-view#what-deleting-a-session-removes) 中的拒絕訊息會回報 hook 的結束方式(例如 `exited 1`)、引用其 stderr 的開頭,並說明再次刪除工作階段是否仍會移除該目錄。
3467* 如果 `claude remote-control` 正在清理工作階段的 worktree,執行它的終端機會顯示 `worktree removal failed, kept: <path>`。3493* 如果 `claude remote-control` 當時正在清理工作階段的 worktree,執行它的終端機會顯示 `worktree removal failed, kept: <path>`。
3468 3494
3469<h3 id="precompact">3495<h3 id="precompact">
3470 PreCompact3496 PreCompact
3471</h3>3497</h3>
3472 3498
3473在 Claude Code 即將執行壓縮操作之前執行。3499在 Claude Code 即將執行壓縮作業之前執行。
3474 3500
3475matcher 值表示壓縮是手動觸發還是自動觸發:3501matcher 值表示壓縮是手動或自動觸發的:
3476 3502
3477| Matcher | 觸發時機 |3503| Matcher | 觸發時機 |
3478| :- | :- |3504| :- | :- |
3479| `manual` | `/compact` |3505| `manual` | `/compact` |
3480| `auto` | 對話達到[自動壓縮視窗](/docs/zh-TW/model-config#set-the-auto-compact-window)時自動壓縮 |3506| `auto` | 對話達到[自動壓縮視窗](/docs/zh-TW/model-config#set-the-auto-compact-window)時的自動壓縮,以及[閒置壓縮](/docs/zh-TW/settings-reference#idlecompaction) |
3481 3507
3482以退出碼 2 退出可封鎖壓縮。對於手動 `/compact`,stderr 訊息會顯示給使用者。您也可以回傳包含 `"decision": "block"` 的 JSON 來封鎖。3508以代碼 2 結束可封鎖壓縮。對於手動的 `/compact`,stderr 訊息會顯示給使用者。您也可以傳回包含 `"decision": "block"` 的 JSON 來封鎖。
3483 3509
3484封鎖自動壓縮的效果取決於其觸發時機。如果壓縮是在達到上下文限制之前主動觸發,Claude Code 會略過壓縮,對話會在未壓縮的情況下繼續。如果壓縮是為了從 API 已回傳的上下文限制錯誤中復原而觸發,底層錯誤會浮現,目前的請求會失敗。3510封鎖自動壓縮會依觸發時機而產生不同效果。如果壓縮是在達到上下文上限之前主動觸發的,Claude Code 會略過它,對話會在未壓縮的情況下繼續。如果壓縮是為了從 API 已傳回的上下文上限錯誤中復原而觸發的,底層錯誤會浮現,且目前的請求會失敗。
3485 3511
3486Claude Code 會捨棄 PreCompact hook 的 `systemMessage` 和 `continue` 欄位。3512Claude Code 會捨棄 PreCompact hook 的 `systemMessage` 與 `continue` 欄位。
3487 3513
3488<h4 id="precompact-input">3514<h4 id="precompact-input">
3489 PreCompact 輸入3515 PreCompact 輸入
3490</h4>3516</h4>
3491 3517
3492除了[通用輸入欄位](#common-input-fields)之外,PreCompact hook 還會收到 `trigger` 和 `custom_instructions`。對於 `manual`,`custom_instructions` 包含使用者傳入 `/compact` 的內容,若未傳入任何內容則為 `null`。對於 `auto`,`custom_instructions` 為 `null`。3518除了[通用輸入欄位](#common-input-fields)之外,PreCompact hook 還會收到 `trigger` 與 `custom_instructions`。對於 `manual`,`custom_instructions` 包含使用者傳入 `/compact` 的內容,未傳入任何內容時則為 `null`。對於 `auto`,`custom_instructions` 為 `null`。
3493 3519
3494```json theme={null}3520```json theme={null}
3495{3521{
3506 PostCompact3532 PostCompact
3507</h3>3533</h3>
3508 3534
3509在 Claude Code 完成壓縮操作之後執行。使用此事件來回應壓縮後的新狀態,例如記錄所產生的摘要或更新外部狀態。Claude Code 會捨棄 PostCompact hook 的 `systemMessage` 和 `continue` 欄位。3535在 Claude Code 完成壓縮作業後執行。使用此事件對新的壓縮後狀態做出反應,例如記錄產生的摘要或更新外部狀態。Claude Code 會捨棄 PostCompact hook 的 `systemMessage` 與 `continue` 欄位。
3510 3536
3511適用與 `PreCompact` 相同的 matcher 值:3537適用與 `PreCompact` 相同的 matcher 值:
3512 3538
3513| Matcher | 觸發時機 |3539| Matcher | 觸發時機 |
3514| :- | :- |3540| :- | :- |
3515| `manual` | `/compact` 之後 |3541| `manual` | `/compact` 之後 |
3516| `auto` | 對話達到[自動壓縮視窗](/docs/zh-TW/model-config#set-the-auto-compact-window)並自動壓縮之後 |3542| `auto` | 對話達到[自動壓縮視窗](/docs/zh-TW/model-config#set-the-auto-compact-window)時的自動壓縮之後,以及[閒置壓縮](/docs/zh-TW/settings-reference#idlecompaction)之後 |
3517 3543
3518<h4 id="postcompact-input">3544<h4 id="postcompact-input">
3519 PostCompact 輸入3545 PostCompact 輸入
3520</h4>3546</h4>
3521 3547
3522除了[通用輸入欄位](#common-input-fields)之外,PostCompact hook 還會收到 `trigger` 和 `compact_summary`。`compact_summary` 欄位包含壓縮操作所產生的對話摘要。3548除了[通用輸入欄位](#common-input-fields)之外,PostCompact hook 還會收到 `trigger` 與 `compact_summary`。`compact_summary` 欄位包含壓縮作業所產生的對話摘要。
3523 3549
3524```json theme={null}3550```json theme={null}
3525{3551{
3538 PreModelSwitch3564 PreModelSwitch
3539</h3>3565</h3>
3540 3566
3541在 Claude Code 套用您或用戶端所請求的模型切換之前執行。使用它來封鎖切換、要求確認,或在切換發生前顯示切換的成本。3567在 Claude Code 套用您或用戶端所請求的模型切換之前執行。可用來封鎖切換、要求確認,或在切換發生前顯示切換的成本。
3542 3568
3543PreModelSwitch 需要 Claude Code v2.1.251 或更新版本。Claude Code 會針對下列請求執行它:3569PreModelSwitch 需要 Claude Code v2.1.251 或更新版本。Claude Code 會針對以下請求執行它:
3544 3570
3545* `/model <name>` 和 `/model` 選擇器3571* `/model <name>` 與 `/model` 選擇器
3546* `Option+P` 或 `Alt+P` 模型選擇器3572* `Option+P` 或 `Alt+P` 模型選擇器
3547* `/config` 中的 Model 設定3573* `/config` 中的 Model 設定
3548* 開啟[快速模式](/docs/zh-TW/fast-mode)且此舉會變更工作階段的模型時3574* 開啟[快速模式](/docs/zh-TW/fast-mode)且因此變更工作階段的模型時
3549* 來自 [Agent SDK](/docs/zh-TW/agent-sdk/typescript#query-object) 主機或 [Remote Control](/docs/zh-TW/remote-control) 的 `set_model` 請求,或 `apply_flag_settings` 請求中的模型變更3575* 來自 [Agent SDK](/docs/zh-TW/agent-sdk/typescript#query-object) 主機或 [Remote Control](/docs/zh-TW/remote-control) 的 `set_model` 請求,或 `apply_flag_settings` 請求中的模型變更
3550 3576
3551Claude Code 不會針對其自行進行的切換執行 PreModelSwitch hook,例如[自動模型備援](/docs/zh-TW/model-config#automatic-model-fallback)或在您恢復工作階段時還原模型。這些變更只會觸發 [PostModelSwitch](#postmodelswitch)。3577對於 Claude Code 自行進行的切換,例如[自動模型備援](/docs/zh-TW/model-config#automatic-model-fallback)或在您繼續工作階段時還原模型,Claude Code 不會執行 PreModelSwitch hook。這些變更只會觸發 [PostModelSwitch](#postmodelswitch)。
3552 3578
3553Claude Code 會將 matcher 與工作階段所要切換之模型的標準名稱進行比對,並忽略任何 `[1m]` 後綴。別名(例如 `opus`)、帶日期的模型 ID,以及供應商專屬 ID(例如 Amazon Bedrock 模型 ID)都會比對到其解析後的同一個標準名稱,因此 `claude-opus-5` 涵蓋 Opus 5 的所有寫法。3579Claude Code 會將 matcher 與工作階段要切換到的模型之標準名稱進行比對,並忽略任何 `[1m]` 後綴。像 `opus` 這樣的別名、帶日期的模型 ID,以及供應商特定的 ID(例如 Amazon Bedrock 模型 ID)都會符合它們所解析到的同一個標準名稱,因此 `claude-opus-5` 涵蓋了 Opus 5 的所有寫法。
3554 3580
3555當 Claude Code 無法判斷目標的標準名稱時,例如只有您的 [LLM 閘道](/docs/zh-TW/llm-gateway)才知道的自訂模型 ID,它會執行每一個 PreModelSwitch hook,無論 matcher 為何。因此,會封鎖切換的 hook 應檢查其輸入中的 `to_model`,而非僅依賴 matcher。3581當 Claude Code 無法判斷目標的標準名稱時(例如只有您的 [LLM 閘道](/docs/zh-TW/llm-gateway)知道的自訂模型 ID),它會不論 matcher 為何而執行每個 PreModelSwitch hook。因此,進行封鎖的 hook 應檢查其輸入中的 `to_model`,而非僅依賴 matcher。
3556 3582
3557請將 matcher 寫成確切名稱、以 `|` 分隔的清單(例如 `claude-opus-4-6|claude-opus-5`),或正規表示式(例如 `.*opus.*`)。此範例使用確切名稱 matcher,並同時檢查 hook 輸入中的 `to_model`,因此它會以退出碼 2 退出來拒絕切換至 Opus 4.6,並允許任何其他目標通過:3583請將 matcher 寫成精確名稱、以 `|` 分隔的清單(例如 `claude-opus-4-6|claude-opus-5`),或正規表示式(例如 `.*opus.*`)。此範例使用精確名稱 matcher,並同時檢查 hook 輸入中的 `to_model`,因此會以代碼 2 結束來拒絕切換到 Opus 4.6,並放行其他任何目標:
3558 3584
3559<Tabs>3585<Tabs>
3560 <Tab title="macOS/Linux">3586 <Tab title="macOS/Linux">
3561 此命令使用 `jq` 檢查 `to_model`:3587 此命令以 `jq` 檢查 `to_model`:
3562 3588
3563 ```json theme={null}3589 ```json theme={null}
3564 {3590 {
3580 </Tab>3606 </Tab>
3581 3607
3582 <Tab title="Windows (PowerShell)">3608 <Tab title="Windows (PowerShell)">
3583 註冊一個透過 PowerShell 執行腳本的命令 hook:3609 註冊一個透過 PowerShell 執行指令碼的命令 hook:
3584 3610
3585 ```json theme={null}3611 ```json theme={null}
3586 {3612 {
3607 }3633 }
3608 ```3634 ```
3609 3635
3610 將此腳本儲存至專案中的 `.claude/hooks/block-opus-46.ps1`:3636 將此指令碼儲存至專案中的 `.claude/hooks/block-opus-46.ps1`:
3611 3637
3612 ```powershell theme={null}3638 ```powershell theme={null}
3613 $hookInput = [Console]::In.ReadToEnd() | ConvertFrom-Json3639 $hookInput = [Console]::In.ReadToEnd() | ConvertFrom-Json
3620 </Tab>3646 </Tab>
3621</Tabs>3647</Tabs>
3622 3648
3623若要確認 hook 是否正常運作,請在執行其他模型的工作階段中執行 `/model claude-opus-4-6`。Claude Code 會保留目前的模型,並回報 PreModelSwitch hook 已封鎖此切換,並以您的訊息作為原因。3649若要確認 hook 是否正常運作,請在執行其他模型的工作階段中執行 `/model claude-opus-4-6`。Claude Code 會保留目前的模型,並回報 PreModelSwitch hook 封鎖了切換,並以您的訊息作為原因。
3624 3650
3625<h4 id="premodelswitch-input">3651<h4 id="premodelswitch-input">
3626 PreModelSwitch 輸入3652 PreModelSwitch 輸入
3627</h4>3653</h4>
3628 3654
3629除了[通用輸入欄位](#common-input-fields)之外,PreModelSwitch hook 還會收到此表格中的欄位。最後五個欄位描述將對話重新傳送至新模型的成本,讓 hook 可以在切換發生前顯示該數字。3655除了[通用輸入欄位](#common-input-fields)之外,PreModelSwitch hook 還會收到此表中的欄位。最後五個欄位描述將對話重新傳送給新模型的成本,讓 hook 可以在切換發生前顯示該數字。
3630 3656
3631| 欄位 | 類型 | 說明 |3657| 欄位 | 類型 | 說明 |
3632| :- | :- | :- |3658| :- | :- | :- |
3633| `from_model` | string | 切換前的模型 ID |3659| `from_model` | string | 切換前的模型 ID |
3634| `to_model` | string | 切換後的模型 ID。matcher 會與此模型的標準名稱進行比對 |3660| `to_model` | string | 切換後的模型 ID。matcher 會與此模型的標準名稱進行比對 |
3635| `requested_model` | string 或 `null` | 請求所指定的模型:別名(例如 `opus`)、完整模型 ID,或在請求預設模型時為 `null` |3661| `requested_model` | string 或 `null` | 請求所指名的模型:像 `opus` 這樣的別名、完整的模型 ID,或在請求預設模型時為 `null` |
3636| `source` | string | 請求的來源:`"command"` 表示 `/model <name>`、`/config` 中的 Model 設定或開啟快速模式;`"picker"` 表示模型選擇器;`"sdk"` 表示來自 Agent SDK 主機或 Remote Control 的 `set_model` 請求,或 `apply_flag_settings` 請求中的模型變更 |3662| `source` | string | 請求的來源:`"command"` 表示 `/model <name>`、`/config` 中的 Model 設定,或開啟快速模式;`"picker"` 表示模型選擇器;`"sdk"` 表示來自 Agent SDK 主機或 Remote Control 的 `set_model` 請求,或 `apply_flag_settings` 請求中的模型變更 |
3637| `context_tokens` | number | 下一個請求作為提示詞重新傳送的 token 數:主對話中最後一個回應的輸入、快取讀取、快取建立和輸出 token 的總和。在第一個回應之前為 `0` |3663| `context_tokens` | number | 下一個請求作為提示詞重新傳送的 token 數:主要對話中最後一個回應的輸入、快取讀取、快取建立與輸出 token 的總和。在第一個回應之前為 `0` |
3638| `prompt_cache_warm` | boolean | 目前模型的提示快取是否可能仍處於熱狀態,亦即切換會放棄該快取 |3664| `prompt_cache_warm` | boolean | 目前模型的提示快取是否可能仍處於溫熱狀態,也就是切換會使其失效 |
3639| `cache_ttl` | string | Claude Code 為此工作階段請求的[提示快取存留期](/docs/zh-TW/prompt-caching#cache-lifetime):`"5m"` 或 `"1h"` |3665| `cache_ttl` | string | Claude Code 為此工作階段請求的[提示快取存留期](/docs/zh-TW/prompt-caching#cache-lifetime):`"5m"` 或 `"1h"` |
3640| `estimated_cache_write_usd` | number | 以 `cache_ttl` 費率將 `context_tokens` 寫入 `to_model` 提示快取的預估成本(美元),不含下一個回應。伺服器可能不需要重新快取整個上下文,因此請將其視為預估值 |3666| `estimated_cache_write_usd` | number | 以 `cache_ttl` 費率在 `to_model` 上將 `context_tokens` 寫入提示快取的估計成本(美元),不包含下一個回應。伺服器可能不需要重新快取整個上下文,因此請將其視為估計值 |
3641| `pricing` | string | Claude Code 計算 `estimated_cache_write_usd` 的方式:`"configured"` 表示使用您組織已設定的自有費率,`"catalog"` 表示使用牌價,`"default"` 表示 `to_model` 沒有已知價格而 Claude Code 採用預設費率 |3667| `pricing` | string | Claude Code 為 `estimated_cache_write_usd` 計價的方式:`"configured"` 表示您的組織已設定自己的費率並依此計價,`"catalog"` 表示依牌價計價,`"default"` 表示 `to_model` 沒有已知價格,Claude Code 假設了預設費率 |
3642 3668
3643此範例顯示在執行 Sonnet 5 的工作階段中執行 `/model opus` 的輸入:3669此範例顯示在執行 Sonnet 5 的工作階段中執行 `/model opus` 時的輸入:
3644 3670
3645```json theme={null}3671```json theme={null}
3646{3672{
3666 3692
3667`PreModelSwitch` hook 可以取消切換、要求使用者確認,或讓切換繼續進行。退出碼 2 或頂層的 `decision: "block"` 會取消切換。3693`PreModelSwitch` hook 可以取消切換、要求使用者確認,或讓切換繼續進行。退出碼 2 或頂層的 `decision: "block"` 會取消切換。
3668 3694
3669若要進行更精細的控制,請在 `hookSpecificOutput` 物件中回傳 `permissionDecision` 和 `permissionDecisionReason`,與 [PreToolUse](#pretooluse-decision-control) 相同。`PreModelSwitch` 接受 `"allow"`、`"deny"` 和 `"ask"`。它不接受 `"defer"`、`updatedInput` 或 `additionalContext`。下表說明這兩個欄位:3695若要進行更精細的控制,請在 `hookSpecificOutput` 物件中傳回 `permissionDecision` 與 `permissionDecisionReason`,如同 [PreToolUse](#pretooluse-decision-control)。`PreModelSwitch` 接受 `"allow"`、`"deny"` 與 `"ask"`。它不接受 `"defer"`、`updatedInput` 或 `additionalContext`。下表說明這兩個欄位:
3670 3696
3671| 欄位 | 說明 |3697| 欄位 | 說明 |
3672| :- | :- |3698| :- | :- |
3673| `permissionDecision` | `"allow"` 會繼續進行,並略過[提示快取處於熱狀態時 Claude Code 顯示的確認](/docs/zh-TW/prompt-caching#switching-models)。`"deny"` 會取消切換。`"ask"` 會提示使用者確認 |3699| `permissionDecision` | `"allow"` 會繼續進行,並略過[提示快取溫熱時 Claude Code 顯示的確認](/docs/zh-TW/prompt-caching#switching-models)。`"deny"` 會取消切換。`"ask"` 會提示使用者確認 |
3674| `permissionDecisionReason` | 對於 `"deny"`,會作為切換遭封鎖的原因顯示給使用者,或作為 `set_model` 請求的錯誤回傳。對於 `"ask"`,會顯示在確認提示中。對於 `"allow"` 則會被忽略 |3700| `permissionDecisionReason` | 對於 `"deny"`,會作為切換遭封鎖的原因顯示給使用者,或作為 `set_model` 請求的錯誤傳回。對於 `"ask"`,會顯示在確認提示中。對於 `"allow"` 則會被忽略 |
3675 3701
3676只有互動式工作階段中的 `/model` 可以顯示 `"ask"` 提示。在其他所有使用介面上,包括使用 `-p` 旗標的非互動模式、`/config` 和 `set_model` 請求,Claude Code 都會將 `"ask"` 視為拒絕。3702只有互動式工作階段中的 `/model` 能顯示 `"ask"` 提示。在其他所有使用介面上,包括使用 `-p` 旗標的非互動模式、`/config` 以及 `set_model` 請求,Claude Code 都會將 `"ask"` 視為拒絕。
3677 3703
3678此範例會要求使用者確認,並引用 `context_tokens` 中的 token 數:3704此範例會要求使用者確認,並引用 `context_tokens` 中的 token 數:
3679 3705
3687}3713}
3688```3714```
3689 3715
3690當多個 PreModelSwitch hook 回傳不同決策時,優先順序為 `deny` > `ask` > `allow`。3716當多個 PreModelSwitch hook 傳回不同的決策時,優先順序為 `deny` > `ask` > `allow`。
3691 3717
3692無論決策為何,Claude Code 都會向使用者顯示 hook 回傳的任何 `systemMessage`,因此回報成本的 hook 可以回傳 `{"systemMessage": "..."}` 並以 0 退出。3718無論決策為何,Claude Code 都會向使用者顯示您的 hook 所傳回的任何 `systemMessage`,因此回報成本的 hook 可以傳回 `{"systemMessage": "..."}` 並以 0 結束。
3693 3719
3694在逾時之前未回應的 PreModelSwitch hook 會封鎖切換。關於逾時在其他事件上的效果,請參閱[逾時](#timeouts)。此事件的預設逾時為 30 秒。`PreModelSwitch` 只會執行 `command`、`http` 和 `mcp_tool` hook,因此 `prompt` 和 `agent` 的預設值不適用。3720未在逾時前回應的 PreModelSwitch hook 會封鎖切換。關於逾時對其他事件的影響,請參閱[逾時](#timeouts)。此事件的預設逾時為 30 秒。`PreModelSwitch` 只執行 `command`、`http` 與 `mcp_tool` hook,因此 `prompt` 與 `agent` 的預設值不適用。
3695 3721
3696以 0 或 2 以外的代碼退出且未印出 JSON 決策的 hook,屬於非封鎖錯誤,如[其他退出碼](#other-exit-codes)中所述。3722以 0 或 2 以外的代碼結束且未印出 JSON 決策的 hook 屬於非封鎖錯誤,如[其他退出碼](#other-exit-codes)中所述。
3697 3723
3698<h3 id="postmodelswitch">3724<h3 id="postmodelswitch">
3699 PostModelSwitch3725 PostModelSwitch
3700</h3>3726</h3>
3701 3727
3702在工作階段的模型變更之後執行。使用它為 Claude 提供特定模型的指引,而無需編輯每個 CLAUDE.md,例如適用於特定模型的全組織指令。3728在工作階段的模型變更後執行。可用來為 Claude 提供特定模型的指引,而無需編輯每個 CLAUDE.md,例如適用於特定模型的組織層級指令。
3703 3729
3704PostModelSwitch 需要 Claude Code v2.1.251 或更新版本。它無法封鎖,因為模型已經變更。Claude Code 會在下列任何變更之後執行 PostModelSwitch hook:3730PostModelSwitch 需要 Claude Code v2.1.251 或更新版本。由於模型已經變更,它無法進行封鎖。Claude Code 會在以下任何變更後執行 PostModelSwitch hook:
3705 3731
3706* 您或用戶端所請求的切換3732* 您或用戶端所請求的切換
3707* [自動模型備援](/docs/zh-TW/model-config#automatic-model-fallback),這會變更工作階段的模型3733* [自動模型備援](/docs/zh-TW/model-config#automatic-model-fallback),它會變更工作階段的模型
3708* [`opusplan`](/docs/zh-TW/model-config#opusplan-model-setting) 等設定進入或離開 plan mode3734* 像 [`opusplan`](/docs/zh-TW/model-config#opusplan-model-setting) 這樣的設定進入或離開 plan mode
3709* Claude Code 在您恢復工作階段時還原模型3735* Claude Code 在您繼續工作階段時還原模型
3710 3736
3711當[備援模型鏈](/docs/zh-TW/model-config#fallback-model-chains)中的模型為某個回合提供服務時,Claude Code 不會執行 PostModelSwitch hook,因為該替換僅持續一個回合,且不會變更工作階段的模型。3737當[備援模型鏈](/docs/zh-TW/model-config#fallback-model-chains)中的模型負責某個回合時,Claude Code 不會執行 PostModelSwitch hook,因為該替代只持續一個回合,且不會變更工作階段的模型。
3712 3738
3713matcher 遵循與 [PreModelSwitch](#premodelswitch) 相同的規則:Claude Code 會將其與工作階段所切換至之模型的標準名稱進行比對。3739matcher 遵循與 [PreModelSwitch](#premodelswitch) 相同的規則:Claude Code 會將其與工作階段切換到的模型之標準名稱進行比對。
3714 3740
3715此範例會在工作階段的模型變更為任何 Opus 模型時新增指引:3741此範例會在工作階段的模型變更為任何 Opus 模型時加入指引:
3716 3742
3717```json theme={null}3743```json theme={null}
3718{3744{
3732}3758}
3733```3759```
3734 3760
3735若要確認 hook 是否正常運作,請在執行其他模型的工作階段中切換至 Opus 模型,例如在 Sonnet 工作階段中執行 `/model opus`,然後詢問 Claude 關於目前模型有哪些指引。3761若要確認 hook 是否正常運作,請從執行其他模型的工作階段切換到 Opus 模型,例如在 Sonnet 工作階段中執行 `/model opus`,然後詢問 Claude 它對目前模型有什麼指引。
3736 3762
3737<h4 id="postmodelswitch-input">3763<h4 id="postmodelswitch-input">
3738 PostModelSwitch 輸入3764 PostModelSwitch 輸入
3739</h4>3765</h4>
3740 3766
3741PostModelSwitch hook 會收到與 [PreModelSwitch](#premodelswitch-input) 相同的欄位,其中 `hook_event_name` 設為 `"PostModelSwitch"`,並多了兩個 `source` 值:`"auto"` 表示自動備援或 Claude Code 自行進行的其他變更,`"resume"` 表示在您恢復工作階段時所還原的模型。3767PostModelSwitch hook 會收到與 [PreModelSwitch](#premodelswitch-input) 相同的欄位,其中 `hook_event_name` 設為 `"PostModelSwitch"`,並多了兩個 `source` 值:`"auto"` 表示自動備援或 Claude Code 自行進行的其他變更,`"resume"` 表示您繼續工作階段時所還原的模型。
3742 3768
3743當 `source` 為 `"auto"` 時,`requested_model` 為 `null`。當 `source` 為 `"resume"` 時,它是 Claude Code 所還原的已儲存模型設定。3769當 `source` 為 `"auto"` 時,`requested_model` 為 `null`。當 `source` 為 `"resume"` 時,它是 Claude Code 所還原的已儲存模型設定。
3744 3770
3746 PostModelSwitch 決策控制3772 PostModelSwitch 決策控制
3747</h4>3773</h4>
3748 3774
3749Claude Code 會在退出碼為 0 時擷取 hook 的[純文字 stdout](#exit-code-0),或擷取 JSON 輸出中的 `additionalContext`,並在切換後隨下一個請求傳遞給 Claude。除了所有 hook 都可使用的 [JSON 輸出欄位](#json-output)之外,您還可以回傳:3775Claude Code 會在以 0 結束時取得您 hook 的[純文字 stdout](#exit-code-0),或取得 JSON 輸出中的 `additionalContext`,並在切換後隨下一個請求傳遞給 Claude。除了所有 hook 皆可使用的 [JSON 輸出欄位](#json-output)之外,您還可以傳回:
3750 3776
3751| 欄位 | 說明 |3777| 欄位 | 說明 |
3752| :- | :- |3778| :- | :- |
3753| `additionalContext` | 隨下一個請求加入 Claude 上下文的字串。請參閱[為 Claude 新增上下文](#add-context-for-claude) |3779| `additionalContext` | 隨下一個請求加入 Claude 上下文的字串。請參閱[為 Claude 新增上下文](#add-context-for-claude) |
3754 3780
3755如果 hook 在您傳送下一個提示詞後五秒內尚未完成,Claude Code 會在不含該輸出的情況下傳送該請求,並改為將輸出附加至之後的請求。如果模型在下一個請求之前變更多次,Claude Code 只會傳遞最後一次切換之目標模型的輸出。3781如果在您傳送下一個提示詞後五秒內 hook 尚未完成,Claude Code 會在不含該輸出的情況下傳送該請求,並改為將其附加到再下一個請求。如果模型在下一個請求之前變更了數次,Claude Code 只會傳遞最後一次切換之目標模型的輸出。
3756 3782
3757<h3 id="sessionend">3783<h3 id="sessionend">
3758 SessionEnd3784 SessionEnd
3759</h3>3785</h3>
3760 3786
3761在 Claude Code 工作階段結束時執行。適用於清理工作、記錄工作階段3787在 Claude Code 工作階段結束時執行。適用於清理工作、記錄工作階段
3762統計資料或儲存工作階段狀態。支援使用 matcher 依退出原因篩選。3788統計資料或儲存工作階段狀態。支援以 matcher 依結束原因進行篩選。
3763 3789
3764hook 輸入中的 `reason` 欄位表示工作階段結束的原因:3790hook 輸入中的 `reason` 欄位表示工作階段結束的原因:
3765 3791
3766| 原因 | 說明 |3792| 原因 | 說明 |
3767| :- | :- |3793| :- | :- |
3768| `clear` | 使用 `/clear` 命令清除工作階段 |3794| `clear` | 以 `/clear` 命令清除工作階段 |
3769| `resume` | 透過互動式 `/resume` 切換工作階段 |3795| `resume` | 透過互動式 `/resume` 切換工作階段 |
3770| `logout` | 使用者已登出 |3796| `logout` | 使用者已登出 |
3771| `prompt_input_exit` | 使用者在提示詞輸入可見時退出 |3797| `prompt_input_exit` | 使用者在提示詞輸入可見時結束 |
3772| `other` | 其他退出原因 |3798| `other` | 其他結束原因 |
3773| `bypass_permissions_disabled` | 已於 v2.1.234 移除;Claude Code 不會傳送此值。請將其從您的 `SessionEnd` matcher 中移除 |3799| `bypass_permissions_disabled` | 已於 v2.1.234 移除;Claude Code 不會傳送此值。請將其從您的 `SessionEnd` matcher 中移除 |
3774 3800
3775<h4 id="sessionend-input">3801<h4 id="sessionend-input">
3776 SessionEnd 輸入3802 SessionEnd 輸入
3777</h4>3803</h4>
3778 3804
3779除了[通用輸入欄位](#common-input-fields)之外,SessionEnd hook 還會收到表示工作階段結束原因的 `reason` 欄位。所有值請參閱上方的[原因表格](#sessionend)。3805除了[通用輸入欄位](#common-input-fields)之外,SessionEnd hook 還會收到表示工作階段結束原因的 `reason` 欄位。所有值請參閱上方的[原因表](#sessionend)。
3780 3806
3781```json theme={null}3807```json theme={null}
3782{3808{
3788}3814}
3789```3815```
3790 3816
3791SessionEnd hook 沒有決策控制。它們無法封鎖工作階段終止,但可以執行清理工作。Claude Code 會捨棄其 [JSON 輸出欄位](#json-output),例如 `systemMessage`。3817SessionEnd hook 沒有決策控制。它們無法阻止工作階段終止,但可以執行清理工作。Claude Code 會捨棄其 [JSON 輸出欄位](#json-output),例如 `systemMessage`。
3792 3818
3793SessionEnd hook 的預設逾時為 1.5 秒。此逾時適用於您退出、執行 `/clear` 或透過互動式 `/resume` 切換工作階段時。您可以透過兩種方式給予 hook 更多時間:3819SessionEnd hook 的預設逾時為 1.5 秒。它適用於您結束、執行 `/clear`,或以互動式 `/resume` 切換工作階段時。您可以透過兩種方式給予 hook 更多時間:
3794 3820
3795* **個別 hook 的 `timeout`**:在該 hook 的設定中設定 `timeout`。整體預算會自動提高,以符合設定檔中最高的個別 hook `timeout`,上限為 60 秒。如果您以此方式提高預算,沒有自己 `timeout` 的 hook 仍會保留預設值。在外掛程式提供的 hook 上設定的逾時不會提高預算。3821* **個別 hook 的 `timeout`**:在該 hook 的設定中設定 `timeout`。整體預算會自動提高,以符合您設定檔中最高的個別 hook `timeout`,最多 60 秒。如果您以此方式提高預算,沒有自己 `timeout` 的 hook 仍會保留預設值。在外掛程式提供的 hook 上設定的逾時不會提高預算。
3796* **`CLAUDE_CODE_SESSIONEND_HOOKS_TIMEOUT_MS`**:以毫秒為單位設定此環境變數,以明確覆寫預算。您設定的值也會成為每個沒有自己 `timeout` 之 hook 的逾時。3822* **`CLAUDE_CODE_SESSIONEND_HOOKS_TIMEOUT_MS`**:以毫秒為單位設定此環境變數,以明確覆寫預算。您設定的值也會成為每個沒有自己 `timeout` 之 hook 的逾時。
3797 3823
3798此範例將預算設為 5 秒:3824此範例將預算設為 5 秒:
3807 Elicitation3833 Elicitation
3808</h3>3834</h3>
3809 3835
3810在 MCP 伺服器於任務進行中請求使用者輸入時執行。預設情況下,Claude Code 會顯示互動式對話方塊供使用者回應。hook 可以攔截此請求並以程式方式回應,完全略過對話方塊。3836在 MCP 伺服器於工作進行中請求使用者輸入時執行。根據預設,Claude Code 會顯示互動式對話方塊讓使用者回應。hook 可以攔截此請求並以程式方式回應,完全略過對話方塊。
3811 3837
3812關於包含設定項目和腳本的完整 hook,請參閱[從腳本回答表單請求](#answer-a-form-request-from-a-script)。3838關於包含設定項目與指令碼的完整 hook,請參閱[從指令碼回答表單請求](#answer-a-form-request-from-a-script)。
3813 3839
3814matcher 欄位會與 MCP 伺服器名稱進行比對。3840matcher 欄位會與 MCP 伺服器名稱進行比對。
3815 3841
3817 Elicitation 輸入3843 Elicitation 輸入
3818</h4>3844</h4>
3819 3845
3820除了[通用輸入欄位](#common-input-fields)之外,Elicitation hook 還會收到 `mcp_server_name`、`message`,以及選用的 `mode`、`url`、`elicitation_id` 和 `requested_schema` 欄位。3846除了[通用輸入欄位](#common-input-fields)之外,Elicitation hook 還會收到 `mcp_server_name`、`message`,以及選用的 `mode`、`url`、`elicitation_id` 與 `requested_schema` 欄位。
3821 3847
3822對於表單模式的 elicitation(最常見的情況):3848表單模式的 elicitation,也就是最常見的情況:
3823 3849
3824```json theme={null}3850```json theme={null}
3825{3851{
3839}3865}
3840```3866```
3841 3867
3842對於用於瀏覽器型身分驗證的 URL 模式 elicitation:3868URL 模式的 elicitation,用於以瀏覽器為基礎的身分驗證:
3843 3869
3844```json theme={null}3870```json theme={null}
3845{3871{
3858 Elicitation 輸出3884 Elicitation 輸出
3859</h4>3885</h4>
3860 3886
3861Elicitation hook 可以代替使用者回答請求、拒絕或取消請求,或將其交由對話方塊處理。若要回答、拒絕或取消,請以 0 退出並印出包含 `action` 的 `hookSpecificOutput` 物件。伺服器會收到您的回答,且不會出現對話方塊。此表格的每一列顯示針對某一結果應回傳的內容,以及 MCP 伺服器所收到的內容:3887Elicitation hook 可以代替使用者回答請求、拒絕或取消請求,或將其留給對話方塊處理。若要回答、拒絕或取消,請以 0 結束並印出含有 `action` 的 `hookSpecificOutput` 物件。伺服器會收到您的答覆,且不會出現對話方塊。此表的每一列都顯示針對某個結果應傳回的內容,以及 MCP 伺服器會收到的內容:
3862 3888
3863| 目的 | 回傳 | 伺服器收到 |3889| 目的 | 傳回 | 伺服器收到 |
3864| :- | :- | :- |3890| :- | :- | :- |
3865| 代替使用者回答 | `"action": "accept"`,並在 `content` 中提供表單欄位值 | `accept` 以及您的 `content` |3891| 代替使用者回答 | `"action": "accept"`,並在 `content` 中提供表單欄位值 | `accept` 以及您的 `content` |
3866| 拒絕請求 | `"action": "decline"` | `decline` |3892| 拒絕請求 | `"action": "decline"` | `decline` |
3867| 取消請求 | `"action": "cancel"` | `cancel` |3893| 取消請求 | `"action": "cancel"` | `cancel` |
3868| 將請求交由使用者處理 | 不輸出任何內容,並以退出碼 0 退出 | 使用者從[對話方塊](/docs/zh-TW/mcp#respond-to-mcp-elicitation-requests)提供的回答 |3894| 將請求留給使用者 | 無輸出,退出碼為 0 | 使用者在[對話方塊](/docs/zh-TW/mcp#respond-to-mcp-elicitation-requests)中的答覆 |
3869 3895
3870此輸出會回答 [Elicitation 輸入](#elicitation-input)中所示的表單模式請求。`content` 中的鍵是該請求 `requested_schema` 中的屬性名稱:3896此輸出會回答 [Elicitation 輸入](#elicitation-input)中所示的表單模式請求。`content` 中的鍵是該請求之 `requested_schema` 中的屬性名稱:
3871 3897
3872```json theme={null}3898```json theme={null}
3873{3899{
3892}3918}
3893```3919```
3894 3920
3895在對話方塊中,選取 **Decline** 會傳送 `decline`,按下 `Esc` 則會傳送 `cancel`,因此請回傳您希望伺服器看到的那一個。3921在對話方塊中,選取 **Decline** 會傳送 `decline`,按下 `Esc` 則會傳送 `cancel`,因此請傳回您希望伺服器看到的那一個。
3896 3922
3897對於 URL 模式的請求,回傳 `accept` 的 hook 會略過對話方塊,因此 URL 永遠不會開啟。3923對於 URL 模式的請求,傳回 `accept` 的 hook 會略過對話方塊,因此 URL 永遠不會開啟。
3898 3924
3899無論您回傳哪一個 `action`,Claude Code 都會捨棄 Elicitation hook JSON 輸出中的 `reason`、`systemMessage` 和 `continue`。3925無論您傳回哪個 `action`,Claude Code 都會捨棄 Elicitation hook JSON 輸出中的 `reason`、`systemMessage` 與 `continue`。
3900 3926
3901<h4 id="other-ways-to-decline-an-elicitation">3927<h4 id="other-ways-to-decline-an-elicitation">
3902 拒絕 elicitation 的其他方式3928 拒絕 elicitation 的其他方式
3903</h4>3929</h4>
3904 3930
3905您的 hook 也可以透過下列方式拒絕。伺服器收到的 `decline` 與 `"action": "decline"` 相同:3931您的 hook 也可以透過以下方式拒絕。伺服器會收到與 `"action": "decline"` 相同的 `decline`:
3906 3932
3907* **以代碼 2 退出**:Claude Code 會忽略同一個 hook 所印出的 `hookSpecificOutput`3933* **以代碼 2 結束**:Claude Code 會忽略同一個 hook 所印出的 `hookSpecificOutput`
3908* **印出頂層的 `"decision": "block"`**:此封鎖會覆寫同一輸出中的 `action`3934* **印出頂層的 `"decision": "block"`**:封鎖會覆寫同一輸出中的 `action`
3909 3935
3910當多個 hook 比對到同一個請求時,其中一個 hook 的拒絕會覆寫另一個 hook 的 `accept` 或 `cancel`。3936當多個 hook 符合同一個請求時,其中一個的拒絕會覆寫另一個的 `accept` 或 `cancel`。
3911 3937
3912此腳本會拒絕 URL 模式的請求,並將表單請求交由對話方塊處理:3938此指令碼會拒絕 URL 模式的請求,並將表單請求留給對話方塊處理:
3913 3939
3914```bash theme={null}3940```bash theme={null}
3915#!/bin/bash3941#!/bin/bash
3918fi3944fi
3919```3945```
3920 3946
3921使用者和伺服器都不會看到您的 hook 拒絕的原因,因為 Claude Code 不會顯示您的 stderr 或 `reason`。3947使用者和伺服器都看不到您的 hook 拒絕的原因,因為 Claude Code 不會顯示您的 stderr 或您的 `reason`。
3922 3948
3923從 v2.1.105 起直到 v2.1.284 修正之前,Claude Code 會忽略 `Elicitation` 和 `ElicitationResult` hook 的頂層 `decision`。3949從 v2.1.105 起直到 v2.1.284 修正為止,Claude Code 會忽略 `Elicitation` 與 `ElicitationResult` hook 的頂層 `decision`。
3924 3950
3925<h4 id="answer-a-form-request-from-a-script">3951<h4 id="answer-a-form-request-from-a-script">
3926 從腳本回答表單請求3952 從指令碼回答表單請求
3927</h4>3953</h4>
3928 3954
3929此範例會代替使用者回答一個重複出現的問題。名為 `issue-tracker` 的 MCP 伺服器在表單中詢問專案代碼,而 hook 會填入 `DOCS`。當 `project_key` 是表單唯一的欄位時,腳本會接受請求。對於任何其他請求,它不會印出任何內容,因此會出現對話方塊。3955此範例會代替使用者回答一個反覆出現的問題。名為 `issue-tracker` 的 MCP 伺服器會在表單中要求專案鍵,而 hook 會填入 `DOCS`。當 `project_key` 是表單唯一的欄位時,指令碼會接受。對於其他任何請求,它不會印出任何內容,因此會出現對話方塊。
3930 3956
3931<Tabs>3957<Tabs>
3932 <Tab title="macOS/Linux">3958 <Tab title="macOS/Linux">
3933 在設定檔中為此事件註冊命令 hook,並以伺服器名稱作為 matcher:3959 在您的設定檔中為此事件註冊命令 hook,並以伺服器名稱作為 matcher:
3934 3960
3935 ```json theme={null}3961 ```json theme={null}
3936 {3962 {
3951 }3977 }
3952 ```3978 ```
3953 3979
3954 將此腳本儲存至專案中的 `.claude/hooks/answer-project-key.sh`,並使用 `chmod +x` 使其可執行:3980 將此指令碼儲存至專案中的 `.claude/hooks/answer-project-key.sh`,並以 `chmod +x` 設為可執行:
3955 3981
3956 ```bash theme={null}3982 ```bash theme={null}
3957 #!/bin/bash3983 #!/bin/bash
3965 </Tab>3991 </Tab>
3966 3992
3967 <Tab title="Windows (PowerShell)">3993 <Tab title="Windows (PowerShell)">
3968 註冊一個透過 PowerShell 執行腳本的命令 hook,並以伺服器名稱作為 matcher:3994 註冊一個透過 PowerShell 執行指令碼的命令 hook,並以伺服器名稱作為 matcher:
3969 3995
3970 ```json theme={null}3996 ```json theme={null}
3971 {3997 {
3992 }4018 }
3993 ```4019 ```
3994 4020
3995 將此腳本儲存至專案中的 `.claude/hooks/answer-project-key.ps1`:4021 將此指令碼儲存至專案中的 `.claude/hooks/answer-project-key.ps1`:
3996 4022
3997 ```powershell theme={null}4023 ```powershell theme={null}
3998 $request = [Console]::In.ReadToEnd() | ConvertFrom-Json4024 $request = [Console]::In.ReadToEnd() | ConvertFrom-Json
4011 </Tab>4037 </Tab>
4012</Tabs>4038</Tabs>
4013 4039
4014若要確認 hook 是否正常運作,請使用 `claude --debug` 啟動 Claude Code,並給 Claude 一個會讓伺服器詢問專案代碼的任務。不會出現對話方塊,且[偵錯日誌](#debug-hooks)中會有一行以 `Elicitation resolved by hook: {"action":"accept","content":{"project_key":"DOCS"}}` 結尾。4040若要確認 hook 是否正常運作,請以 `claude --debug` 啟動 Claude Code,並給 Claude 一項會讓伺服器要求專案鍵的工作。不會出現對話方塊,且[偵錯日誌](#debug-hooks)中會有一行以 `Elicitation resolved by hook: {"action":"accept","content":{"project_key":"DOCS"}}` 結尾。
4015 4041
4016<h3 id="elicitationresult">4042<h3 id="elicitationresult">
4017 ElicitationResult4043 ElicitationResult
4018</h3>4044</h3>
4019 4045
4020在使用者回應 MCP elicitation 之後執行。hook 可以在回應傳回 MCP 伺服器之前觀察、修改或封鎖該回應。4046在使用者回應 MCP elicitation 後執行。hook 可以在回應傳回 MCP 伺服器之前觀察、修改或封鎖該回應。
4021 4047
4022當 [Elicitation](#elicitation) hook 回答了請求時,Claude Code 會將該回答傳送至伺服器,而不執行 ElicitationResult hook。4048當 [Elicitation](#elicitation) hook 回答了請求時,Claude Code 會將該答覆傳送給伺服器,而不執行 ElicitationResult hook。
4023 4049
4024matcher 欄位會與 MCP 伺服器名稱進行比對。4050matcher 欄位會與 MCP 伺服器名稱進行比對。
4025 4051
4027 ElicitationResult 輸入4053 ElicitationResult 輸入
4028</h4>4054</h4>
4029 4055
4030除了[通用輸入欄位](#common-input-fields)之外,ElicitationResult hook 還會收到 `mcp_server_name`、`action`,以及選用的 `mode`、`elicitation_id` 和 `content` 欄位。4056除了[通用輸入欄位](#common-input-fields)之外,ElicitationResult hook 還會收到 `mcp_server_name`、`action`,以及選用的 `mode`、`elicitation_id` 與 `content` 欄位。
4031 4057
4032```json theme={null}4058```json theme={null}
4033{4059{
4046 ElicitationResult 輸出4072 ElicitationResult 輸出
4047</h4>4073</h4>
4048 4074
4049ElicitationResult hook 可以讓使用者的回應通過、變更其值,或封鎖它。若要變更或封鎖回應,請以 0 退出並印出包含 `action` 的 `hookSpecificOutput` 物件。此表格的每一列顯示針對某一結果應回傳的內容,以及 MCP 伺服器所收到的內容:4075ElicitationResult hook 可以讓使用者的回應通過、變更其值,或封鎖它。若要變更或封鎖回應,請以 0 結束並印出含有 `action` 的 `hookSpecificOutput` 物件。此表的每一列都顯示針對某個結果應傳回的內容,以及 MCP 伺服器會收到的內容:
4050 4076
4051| 目的 | 回傳 | 伺服器收到 |4077| 目的 | 傳回 | 伺服器收到 |
4052| :- | :- | :- |4078| :- | :- | :- |
4053| 讓回應通過 | 不輸出任何內容,並以退出碼 0 退出 | 使用者的回應,未經變更 |4079| 讓回應通過 | 無輸出,退出碼為 0 | 使用者的回應,未經變更 |
4054| 變更提交的值 | `"action": "accept"`,並在 `content` 中提供新值 | `accept` 以及您的 `content`,取代使用者的值 |4080| 變更提交的值 | `"action": "accept"`,並在 `content` 中提供新值 | `accept` 以及您的 `content`,取代使用者的值 |
4055| 封鎖回應 | `"action": "decline"` | `decline`,不含使用者的值 |4081| 封鎖回應 | `"action": "decline"` | `decline`,不含使用者的值 |
4056| 取消請求 | `"action": "cancel"` | `cancel`,以及使用者提交的值。若要保留這些值不傳送,請回傳 `"decline"` |4082| 取消請求 | `"action": "cancel"` | `cancel`,以及使用者提交的值。若要保留不送出這些值,請傳回 `"decline"` |
4057 4083
4058此輸出會變更 [ElicitationResult 輸入](#elicitationresult-input)中所示的回應,因此在使用者提交 `alice` 之處,伺服器會收到 `alice@example.com`:4084此輸出會變更 [ElicitationResult 輸入](#elicitationresult-input)中所示的回應,使伺服器在使用者提交 `alice` 之處收到 `alice@example.com`:
4059 4085
4060```json theme={null}4086```json theme={null}
4061{4087{
4069}4095}
4070```4096```
4071 4097
4072您的 `content` 會取代使用者的整個 `content` 物件,因此請包含您未變更的欄位。請同時回傳 `action`,因為 Claude Code 會忽略沒有 `action` 的 `hookSpecificOutput`。4098您的 `content` 會取代使用者的整個 `content` 物件,因此請包含您未變更的欄位。請一併傳回 `action`,因為 Claude Code 會忽略沒有 `action` 的 `hookSpecificOutput`。
4073 4099
4074ElicitationResult hook 也會在使用者拒絕或取消時執行,且您的 `action` 會取代使用者的選擇。請在傳回 `accept` 之前檢查輸入的 `action` 是否為 `accept`,否則您的 hook 會將已拒絕的請求變成已接受。此指令碼會在使用者接受時進行相同的變更,保留其他欄位,否則不印出任何內容:4100ElicitationResult hook 在使用者拒絕或取消時也會執行,而您的 `action` 會取代使用者的 `action`。在傳回 `accept` 之前,請檢查輸入的 `action` 是否為 `accept`,否則您的 hook 會將已拒絕的請求變成已接受的請求。此指令碼會在使用者接受時進行相同的變更、保留其他欄位,否則不印出任何內容:
4075 4101
4076```bash theme={null}4102```bash theme={null}
4077#!/bin/bash4103#!/bin/bash
4093}4119}
4094```4120```
4095 4121
4096退出碼 2 和頂層的 `"decision": "block"` 也會封鎖回應。[拒絕 elicitation 的其他方式](#other-ways-to-decline-an-elicitation)說明了當 hook 組合使用這些方式時哪一個會生效、使用者會看到什麼,以及哪些版本會忽略 `decision`。4122退出碼 2 與頂層的 `"decision": "block"` 也會封鎖回應。[拒絕 elicitation 的其他方式](#other-ways-to-decline-an-elicitation)說明了當 hook 同時使用多種方式時哪一種會生效、使用者會看到什麼,以及哪些版本會忽略 `decision`。
4097 4123
4098無論您回傳哪一個 `action`,Claude Code 都會捨棄 ElicitationResult hook JSON 輸出中的 `reason`、`systemMessage` 和 `continue`。4124無論您傳回哪個 `action`,Claude Code 都會捨棄 ElicitationResult hook JSON 輸出中的 `reason`、`systemMessage` 與 `continue`。
4099 4125
4100<h2 id="prompt-based-hooks">4126<h2 id="prompt-based-hooks">
4101 基於提示的 hooks4127 基於提示的 hooks
4350* **單獨輸出至 stdout**:當回應是 stdout 上唯一的文字時,它可以跨越多行,例如經過美化排版的 `jq` 輸出。跨越多行需要 Claude Code v2.1.295 或更新版本。4376* **單獨輸出至 stdout**:當回應是 stdout 上唯一的文字時,它可以跨越多行,例如經過美化排版的 `jq` 輸出。跨越多行需要 Claude Code v2.1.295 或更新版本。
4351* **單獨佔一行**:當回應本身可容納於一行時,非同步 hook 可以將其他文字列印到 stdout,例如使用 `jq -c`。4377* **單獨佔一行**:當回應本身可容納於一行時,非同步 hook 可以將其他文字列印到 stdout,例如使用 `jq -c`。
4352 4378
4353Claude Code 驗證該 JSON 回應是否符合與同步 hooks 相同的[輸出結構](#json-output),並捨棄任何值類型錯誤的欄位,例如不是字串的 `systemMessage`,而不是傳遞它。使用 `--debug` 執行以查看命名每個捨棄欄位的警告。在 v2.1.202 之前,來自非同步 hook 的格式不正確的 JSON 輸出可能會導致工作階段崩潰,每次恢復工作階段時都會重複發生崩潰。4379Claude Code 驗證該 JSON 回應是否符合與同步 hook 相同的[輸出 schema](#json-output),並捨棄任何值類型錯誤的欄位,例如不是字串的 `systemMessage`,而不是傳遞它。使用 `--debug` 執行以查看命名每個捨棄欄位的警告。
4354 4380
4355非同步 hook 完成通知預設被抑制。要查看它們,請使用 `Ctrl+O` 啟用詳細模式或使用 `--verbose` 啟動 Claude Code。4381非同步 hook 完成通知預設被抑制。要查看它們,請使用 `Ctrl+O` 啟用詳細模式或使用 `--verbose` 啟動 Claude Code。
4356 4382