10 如需快速入門指南和範例,請參閱 [使用 hooks 自動化工作流程](/docs/zh-TW/hooks-guide)。10 如需快速入門指南和範例,請參閱 [使用 hooks 自動化工作流程](/docs/zh-TW/hooks-guide)。
11</Tip>11</Tip>
12 12
13Hooks 是使用者定義的 shell 命令、HTTP 端點或 LLM 提示,在 Claude Code 生命週期的特定時間點自動執行。使用此參考來查詢事件架構、配置選項、JSON 輸入/輸出格式,以及非同步 hooks、HTTP hooks 和 MCP 工具 hooks 等進階功能。如果您是第一次設定 hooks,請改為從 [指南](/docs/zh-TW/hooks-guide) 開始。13Hooks 是使用者定義的 shell 命令、HTTP 端點、MCP 工具呼叫、LLM 提示或子代理,在 Claude Code 生命週期的特定時間點自動執行。Claude Code 在任何地方執行時都會觸發相同的 hook 事件:終端機中的工作階段、IDE 擴充功能、[桌面應用程式](/docs/zh-TW/desktop-quickstart) 和 [Claude Code 網頁版](/docs/zh-TW/claude-code-on-the-web)。使用此參考來查詢事件架構、配置選項、JSON 輸入/輸出格式,以及非同步 hooks、HTTP hooks 和 MCP 工具 hooks 等進階功能。
14 14
15<h2 id="hook-lifecycle">15<h2 id="hook-lifecycle">
16 Hook 生命週期16 Hook 生命週期
17</h2>17</h2>
18 18
19Hooks 在 Claude Code 工作階段期間的特定時間點觸發。當事件觸發且匹配器匹配時,Claude Code 會將有關該事件的 JSON 上下文傳遞給您的 hook 處理程式。對於命令 hooks,輸入會到達 stdin。對於 HTTP hooks,它會作為 POST 請求正文到達。您的處理程式可以檢查輸入、採取行動,並可選擇性地返回決定。19Claude Code 在工作階段期間的特定時間點執行 hooks。當事件觸發且匹配器符合時,Claude Code 會將有關該事件的 JSON 上下文傳遞給您的 hook 處理程式。對於命令 hooks,輸入會到達 stdin。對於 HTTP hooks,它會作為 POST 請求正文到達。您的處理程式可以檢查輸入、採取行動,並可選擇性地返回決定。
20 20
21事件分為三種節奏:21事件分為三種節奏:
22 22
23* 每個工作階段一次:`SessionStart` 和 `SessionEnd`23* 每個工作階段一次:`SessionStart` 和 `SessionEnd`
24* 每個轉向一次:`UserPromptSubmit`、`Stop` 和 `StopFailure`24* 每個轉向一次:`UserPromptSubmit`、`Stop` 和 `StopFailure`
25* 代理迴圈內每個工具呼叫:`PreToolUse` 和 `PostToolUse`25* 在代理迴圈內每個工具呼叫上:`PreToolUse` 和 `PostToolUse`,除了 [`EndConversation`](/docs/zh-TW/tools-reference#endconversation-tool-behavior) 呼叫外,兩者都會跳過
26 26
27<div style={{maxWidth: "500px", margin: "0 auto"}}>27<div style={{maxWidth: "500px", margin: "0 auto"}}>
28 <Frame>28 <Frame>
29 <img src="https://mintcdn.com/claude-code/x7pO8l4XcvAXCoVc/images/hooks-lifecycle.svg?fit=max&auto=format&n=x7pO8l4XcvAXCoVc&q=85&s=81b9256c1bbe8832553485f5d9e9c746" alt="Hook 生命週期圖表,顯示可選的 Setup 進入 SessionStart,然後是每個轉向的迴圈,包含 UserPromptSubmit、用於 slash commands 的 UserPromptExpansion、嵌套的代理迴圈(PreToolUse、PermissionRequest、PostToolUse、PostToolUseFailure、PostToolBatch、SubagentStart/Stop、TaskCreated、TaskCompleted)和 Stop 或 StopFailure,接著是 TeammateIdle、PreCompact、PostCompact 和 SessionEnd,Elicitation 和 ElicitationResult 嵌套在 MCP 工具執行內,PermissionDenied 作為 PermissionRequest 的側分支用於自動模式拒絕,WorktreeCreate、WorktreeRemove、Notification、ConfigChange、InstructionsLoaded、CwdChanged 和 FileChanged 作為獨立非同步事件,以及 MessageDisplay 作為顯示專用事件,在助手訊息文字串流時執行" width="520" height="1336" data-path="images/hooks-lifecycle.svg" />29 <img src="https://mintcdn.com/claude-code/x7pO8l4XcvAXCoVc/images/hooks-lifecycle.svg?fit=max&auto=format&n=x7pO8l4XcvAXCoVc&q=85&s=81b9256c1bbe8832553485f5d9e9c746" className="dark:hidden" alt="Hook 生命週期圖表,顯示可選的 Setup 進入 SessionStart,然後是每個轉向的迴圈,包含 UserPromptSubmit、用於 slash commands 的 UserPromptExpansion、嵌套的代理迴圈(PreToolUse、PermissionRequest、PostToolUse、PostToolUseFailure、PostToolBatch、SubagentStart/Stop、TaskCreated、TaskCompleted)和 Stop 或 StopFailure,接著是 TeammateIdle、PreCompact、PostCompact 和 SessionEnd,Elicitation 和 ElicitationResult 嵌套在 MCP 工具執行內,PermissionDenied 作為 PermissionRequest 的側分支用於自動模式拒絕,WorktreeCreate、WorktreeRemove、Notification、ConfigChange、InstructionsLoaded、CwdChanged、FileChanged 和 DirectoryAdded 作為獨立非同步事件,PreModelSwitch 作為獨立順序事件,在請求的模型切換之前執行,PostModelSwitch 作為獨立非同步事件,在工作階段的模型變更後執行,以及 MessageDisplay 作為顯示專用事件,在助手訊息文字串流時執行" width="520" height="1336" data-path="images/hooks-lifecycle.svg" />
30
31 <img src="https://mintcdn.com/claude-code/x7pO8l4XcvAXCoVc/images/hooks-lifecycle-dark.svg?fit=max&auto=format&n=x7pO8l4XcvAXCoVc&q=85&s=c9b3d88487335f58cce0b52e2f9e7531" className="hidden dark:block" alt="Hook 生命週期圖表,顯示可選的 Setup 進入 SessionStart,然後是每個轉向的迴圈,包含 UserPromptSubmit、用於 slash commands 的 UserPromptExpansion、嵌套的代理迴圈(PreToolUse、PermissionRequest、PostToolUse、PostToolUseFailure、PostToolBatch、SubagentStart/Stop、TaskCreated、TaskCompleted)和 Stop 或 StopFailure,接著是 TeammateIdle、PreCompact、PostCompact 和 SessionEnd,Elicitation 和 ElicitationResult 嵌套在 MCP 工具執行內,PermissionDenied 作為 PermissionRequest 的側分支用於自動模式拒絕,WorktreeCreate、WorktreeRemove、Notification、ConfigChange、InstructionsLoaded、CwdChanged、FileChanged 和 DirectoryAdded 作為獨立非同步事件,PreModelSwitch 作為獨立順序事件,在請求的模型切換之前執行,PostModelSwitch 作為獨立非同步事件,在工作階段的模型變更後執行,以及 MessageDisplay 作為顯示專用事件,在助手訊息文字串流時執行" width="520" height="1336" data-path="images/hooks-lifecycle-dark.svg" />
30 </Frame>32 </Frame>
31</div>33</div>
32 34
33下表總結了每個事件何時觸發。[Hook 事件](#hook-events)部分記錄了每個事件的完整輸入架構和決定控制選項。35下表總結了每個事件何時觸發。[Hook 事件](#hook-events)部分記錄了每個事件的完整輸入架構和決定控制選項。
34 36
35| Event | When it fires |37| 事件 | 何時觸發 |
36| :-------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |38| :-------------------- | :-------------------------------------------------------------------------------------------------------------------- |
37| `SessionStart` | When a session begins or resumes |39| `SessionStart` | 當工作階段開始或繼續時 |
38| `Setup` | When you start Claude Code with `--init-only`, or with `--init` or `--maintenance` in `-p` mode. For one-time preparation in CI or scripts |40| `Setup` | 當您使用 `--init-only` 啟動 Claude Code,或在 `-p` 模式中使用 `--init` 或 `--maintenance` 時。用於 CI 或指令碼中的一次性準備 |
39| `UserPromptSubmit` | When you submit a prompt, before Claude processes it |41| `UserPromptSubmit` | 當您提交提示詞時,在 Claude 處理之前 |
40| `UserPromptExpansion` | When a user-typed command expands into a prompt, before it reaches Claude. Can block the expansion |42| `UserPromptExpansion` | 當使用者輸入的命令擴展為提示詞時,在到達 Claude 之前。可以阻止擴展 |
41| `PreToolUse` | Before a tool call executes. Can block it |43| `PreToolUse` | 在工具呼叫執行之前。可以阻止它 |
42| `PermissionRequest` | When a tool call needs a permission decision |44| `PermissionRequest` | 當工具呼叫需要權限決定時 |
43| `PermissionDenied` | When auto mode denies a tool call, including denials without a classifier verdict. Use JSON `hookSpecificOutput.retry: true` to tell the model it may retry the denied tool call. Claude Code ignores `retry` when the classifier produced no verdict |45| `PermissionDenied` | 當自動模式拒絕工具呼叫時,包括沒有分類器判決的拒絕。使用 JSON `hookSpecificOutput.retry: true` 告訴模型它可能重試被拒絕的工具呼叫。Claude Code 在分類器未產生判決時忽略 `retry` |
44| `PostToolUse` | After a tool call succeeds |46| `PostToolUse` | 在工具呼叫成功後 |
45| `PostToolUseFailure` | After a tool call fails |47| `PostToolUseFailure` | 在工具呼叫失敗後 |
46| `PostToolBatch` | After a full batch of parallel tool calls resolves, before the next model call |48| `PostToolBatch` | 在完整的平行工具呼叫批次解決後,在下一個模型呼叫之前 |
47| `Notification` | When Claude Code sends a notification |49| `Notification` | 當 Claude Code 傳送通知時 |
48| `MessageDisplay` | While assistant message text is displayed |50| `MessageDisplay` | 在助手訊息文字顯示時 |
49| `SubagentStart` | When a subagent is spawned |51| `SubagentStart` | 當子代理被生成時 |
50| `SubagentStop` | When a subagent finishes |52| `SubagentStop` | 當子代理完成時 |
51| `TaskCreated` | When a task is being created via `TaskCreate` |53| `TaskCreated` | 當透過 `TaskCreate` 建立任務時 |
52| `TaskCompleted` | When a task is being marked as completed |54| `TaskCompleted` | 當任務被標記為已完成時 |
53| `Stop` | When Claude finishes responding |55| `Stop` | 當 Claude 完成回應時 |
54| `StopFailure` | When the turn ends due to an API error |56| `StopFailure` | 當回合因 API 錯誤而結束時 |
55| `TeammateIdle` | When an [agent team](/docs/en/agent-teams) teammate is about to go idle |57| `TeammateIdle` | 當[代理團隊](/docs/zh-TW/agent-teams)隊友即將閒置時 |
56| `InstructionsLoaded` | When a CLAUDE.md or `.claude/rules/*.md` file is loaded into context. Fires at session start and when files are lazily loaded during a session |58| `InstructionsLoaded` | 當 CLAUDE.md 或 `.claude/rules/*.md` 檔案被載入到上下文時。在工作階段開始時以及在工作階段期間延遲載入檔案時觸發 |
57| `ConfigChange` | When a configuration file changes during a session |59| `ConfigChange` | 當設定檔在工作階段期間變更時 |
58| `CwdChanged` | When the working directory changes, for example when Claude executes a `cd` command. Useful for reactive environment management with tools like direnv |60| `CwdChanged` | 當工作目錄變更時,例如當 Claude 執行 `cd` 命令時。適用於使用 direnv 等工具進行反應式環境管理 |
59| `DirectoryAdded` | When a working directory is added mid-session via `/add-dir` or the SDK `register_repo_root` control request |61| `DirectoryAdded` | 當工作目錄在工作階段中期透過 `/add-dir` 或 SDK `register_repo_root` 控制請求新增時 |
60| `FileChanged` | When a watched file changes on disk. The `matcher` field specifies which filenames to watch |62| `FileChanged` | 當監視的檔案在磁碟上變更時。`matcher` 欄位指定要監視的檔案名稱 |
61| `WorktreeCreate` | When a worktree is being created via `--worktree`, `isolation: "worktree"`, or for a background session. Replaces default git behavior |63| `WorktreeCreate` | 當透過 `--worktree`、`isolation: "worktree"` 建立 worktree 時,或用於背景工作階段時。取代預設的 git 行為 |
62| `WorktreeRemove` | When a worktree is being removed at session exit, when a subagent finishes, or when you delete a background session |64| `WorktreeRemove` | 當在工作階段結束時、子代理完成時或您刪除背景工作階段時移除 worktree 時 |
63| `PreCompact` | Before context compaction |65| `PreCompact` | 在上下文壓縮之前 |
64| `PostCompact` | After context compaction completes |66| `PostCompact` | 在上下文壓縮完成後 |
65| `PreModelSwitch` | Before Claude Code applies a model switch that you or a client requested. Can block the switch |67| `PreModelSwitch` | 在 Claude Code 應用您或用戶端要求的模型切換之前。可以阻止切換 |
66| `PostModelSwitch` | After the session's model changes, including changes Claude Code makes on its own, such as restoring the model when you resume a session |68| `PostModelSwitch` | 在工作階段的模型變更後,包括 Claude Code 自行進行的變更,例如當您繼續工作階段時恢復模型 |
67| `Elicitation` | When an MCP server requests user input during a tool call |69| `Elicitation` | 當 MCP 伺服器在工具呼叫期間要求使用者輸入時 |
68| `ElicitationResult` | After a user responds to an MCP elicitation, before the response is sent back to the server |70| `ElicitationResult` | 在使用者回應 MCP 引出後,在回應傳送回伺服器之前 |
69| `SessionEnd` | When a session terminates |71| `SessionEnd` | 當工作階段終止時 |
70 72
71<h3 id="how-a-hook-resolves">73<h3 id="how-a-hook-resolves">
72 Hook 如何解析74 Hook 如何解析
73</h3>75</h3>
74 76
75為了了解這些部分如何組合在一起,請考慮此 `PreToolUse` hook,它會阻止破壞性 shell 命令。`matcher` 縮小到 Bash 工具呼叫,`if` 條件進一步縮小到符合 `rm *` 的 Bash 子命令,因此 `block-rm.sh` 僅在兩個篩選器都匹配時才生成:77為了了解事件、匹配器和處理程式如何組合在一起,請考慮此 `PreToolUse` hook,它會阻止破壞性 shell 命令。
76 78
77```json theme={null}79<Tabs>
78{80 <Tab title="macOS/Linux">
81 `matcher` 縮小到 Bash 工具呼叫,`if` 條件進一步縮小到符合 `rm *` 的 Bash 子命令,因此 `block-rm.sh` 僅在兩個篩選器都符合時才生成:
82
83 ```json theme={null}
84 {
79 "hooks": {85 "hooks": {
80 "PreToolUse": [86 "PreToolUse": [
81 {87 {
91 }97 }
92 ]98 ]
93 }99 }
94}100 }
95```101 ```
96 102
97該指令碼從 stdin 讀取 JSON 輸入,提取命令,如果包含 `rm -rf`,則返回 `permissionDecision` 為 `"deny"`:103 該指令碼從 stdin 讀取 JSON 輸入,提取命令,如果包含 `rm -rf`,則返回 `permissionDecision` 為 `"deny"`。將其儲存到您的專案中的 `.claude/hooks/block-rm.sh`,並使用 `chmod +x .claude/hooks/block-rm.sh` 使其可執行,以便 Claude Code 可以執行它:
98 104
99```bash theme={null}105 ```bash theme={null}
100#!/bin/bash106 #!/bin/bash
101# .claude/hooks/block-rm.sh107 # .claude/hooks/block-rm.sh
102COMMAND=$(jq -r '.tool_input.command')108 COMMAND=$(jq -r '.tool_input.command')
103 109
104if echo "$COMMAND" | grep -q 'rm -rf'; then110 if echo "$COMMAND" | grep -q 'rm -rf'; then
105 jq -n '{111 jq -n '{
106 hookSpecificOutput: {112 hookSpecificOutput: {
107 hookEventName: "PreToolUse",113 hookEventName: "PreToolUse",
109 permissionDecisionReason: "Destructive command blocked by hook"115 permissionDecisionReason: "Destructive command blocked by hook"
110 }116 }
111 }'117 }'
112else118 else
113 exit 0 # no decision; normal permission flow applies119 exit 0 # no decision; normal permission flow applies
114fi120 fi
115```121 ```
122
123 此指令碼,如同本頁面上解析 JSON 輸入的其他 Bash 範例,使用 `jq`,因此在嘗試之前請安裝 `jq` 並確保它在您的 `PATH` 上。
124 </Tab>
125
126 <Tab title="Windows (PowerShell)">
127 匹配器 `Bash|PowerShell` 涵蓋 [PowerShell 工具](#powershell)以及 Bash。單一 `if` 規則只符合一個工具的呼叫,因此每個工具都有自己的處理程式:第一個縮小到符合 `rm *` 的 Bash 子命令,第二個縮小到符合 `Remove-Item *` 的 PowerShell 命令。兩者都透過 `powershell.exe` 執行相同的指令碼:
128
129 ```json theme={null}
130 {
131 "hooks": {
132 "PreToolUse": [
133 {
134 "matcher": "Bash|PowerShell",
135 "hooks": [
136 {
137 "type": "command",
138 "if": "Bash(rm *)",
139 "command": "powershell.exe",
140 "args": [
141 "-NoProfile",
142 "-ExecutionPolicy",
143 "Bypass",
144 "-File",
145 "${CLAUDE_PROJECT_DIR}/.claude/hooks/block-rm.ps1"
146 ]
147 },
148 {
149 "type": "command",
150 "if": "PowerShell(Remove-Item *)",
151 "command": "powershell.exe",
152 "args": [
153 "-NoProfile",
154 "-ExecutionPolicy",
155 "Bypass",
156 "-File",
157 "${CLAUDE_PROJECT_DIR}/.claude/hooks/block-rm.ps1"
158 ]
159 }
160 ]
161 }
162 ]
163 }
164 }
165 ```
166
167 `-NoProfile` 旗標會跳過載入您的 PowerShell 設定檔,以便 hook 快速啟動,而 `-ExecutionPolicy Bypass` 讓 PowerShell 執行本機指令碼檔案。
116 168
117現在假設 Claude Code 決定執行 `Bash "rm -rf /tmp/build"`。以下是發生的情況:169 該指令碼從 stdin 讀取 JSON 輸入,提取命令,如果包含 `rm -rf` 或 `Remove-Item` 後跟 `-Recurse`,則返回 `permissionDecision` 為 `"deny"`。將其儲存到您的專案中的 `.claude/hooks/block-rm.ps1`:
170
171 ```powershell theme={null}
172 # .claude/hooks/block-rm.ps1
173 $callInput = [Console]::In.ReadToEnd() | ConvertFrom-Json
174 $command = $callInput.tool_input.command
175
176 if ($command -match 'rm -rf|Remove-Item.*-Recurse') {
177 @{
178 hookSpecificOutput = @{
179 hookEventName = "PreToolUse"
180 permissionDecision = "deny"
181 permissionDecisionReason = "Destructive command blocked by hook"
182 }
183 } | ConvertTo-Json
184 } else {
185 exit 0 # no decision; normal permission flow applies
186 }
187 ```
188 </Tab>
189</Tabs>
190
191現在假設 Claude Code 決定針對 macOS/Linux 設定執行 `Bash "rm -rf /tmp/build"`。以下是發生的情況:
118 192
119<Frame>193<Frame>
120 <img src="https://mintcdn.com/claude-code/ikqp3_70mqIahteV/images/hook-resolution.svg?fit=max&auto=format&n=ikqp3_70mqIahteV&q=85&s=be0bf3053550c26de5f54cd64674c197" alt="Hook 解析流程:PreToolUse 事件觸發,匹配器檢查 Bash 匹配,if 條件檢查 Bash(rm *) 匹配。如果兩者都匹配,hook 命令執行並返回 permissionDecision deny,因此工具呼叫被阻止,Claude Code 繼續。如果任一檢查未能匹配,hook 被跳過,工具呼叫允許繼續進行。" width="930" height="270" data-path="images/hook-resolution.svg" />194 <img src="https://mintcdn.com/claude-code/ikqp3_70mqIahteV/images/hook-resolution.svg?fit=max&auto=format&n=ikqp3_70mqIahteV&q=85&s=be0bf3053550c26de5f54cd64674c197" className="dark:hidden" alt="Hook 解析圖表:PreToolUse 觸發,匹配器檢查 Bash 符合,然後 if 條件檢查 Bash(rm *) 符合。如果兩者都符合,hook 命令執行並返回 permissionDecision deny,因此工具呼叫被阻止,Claude Code 繼續。如果任一檢查未能符合,hook 被跳過,工具呼叫允許繼續進行。" width="930" height="270" data-path="images/hook-resolution.svg" />
195
196 <img src="https://mintcdn.com/claude-code/_xqph1dUOslCOwsj/images/hook-resolution-dark.svg?fit=max&auto=format&n=_xqph1dUOslCOwsj&q=85&s=e80af91f8507cee6bd51ac3c2dd92f63" className="hidden dark:block" alt="Hook 解析圖表:PreToolUse 觸發,匹配器檢查 Bash 符合,然後 if 條件檢查 Bash(rm *) 符合。如果兩者都符合,hook 命令執行並返回 permissionDecision deny,因此工具呼叫被阻止,Claude Code 繼續。如果任一檢查未能符合,hook 被跳過,工具呼叫允許繼續進行。" width="930" height="270" data-path="images/hook-resolution-dark.svg" />
121</Frame>197</Frame>
122 198
123<Steps>199<Steps>
130 </Step>206 </Step>
131 207
132 <Step title="匹配器檢查">208 <Step title="匹配器檢查">
133 匹配器 `"Bash"` 與工具名稱匹配,因此此 hook 群組啟動。如果您省略匹配器或使用 `"*"`,群組在事件的每次出現時啟動。209 匹配器 `"Bash"` 符合工具名稱,因此此 hook 群組啟動。如果您省略匹配器或使用 `"*"`,群組在事件的每次出現時啟動。
134 </Step>210 </Step>
135 211
136 <Step title="If 條件檢查">212 <Step title="If 條件檢查">
137 `if` 條件 `"Bash(rm *)"` 匹配,因為 `rm -rf /tmp/build` 是符合 `rm *` 的子命令,因此此處理程式生成。如果命令是 `npm test`,`if` 檢查會失敗,`block-rm.sh` 永遠不會執行,避免程序生成開銷。`if` 欄位是可選的;沒有它,匹配群組中的每個處理程式都執行。213 `if` 條件 `"Bash(rm *)"` 符合,因為 `rm -rf /tmp/build` 是符合 `rm *` 的子命令,因此此處理程式生成。如果命令是 `npm test`,`if` 檢查會失敗,`block-rm.sh` 永遠不會執行,避免程序生成開銷。`if` 欄位是可選的;沒有它,符合群組中的每個處理程式都執行。
138 </Step>214 </Step>
139 215
140 <Step title="Hook 處理程式執行">216 <Step title="Hook 處理程式執行">
158 </Step>234 </Step>
159</Steps>235</Steps>
160 236
161下面的[配置](#configuration)部分記錄了完整架構,每個 [hook 事件](#hook-events)部分記錄了您的命令接收的輸入以及它可以返回的輸出。237下面的[設定](#configuration)部分記錄了完整架構,每個 [hook 事件](#hook-events)部分記錄了您的命令接收的輸入以及它可以返回的輸出。
162 238
163<h2 id="configuration">239<h2 id="configuration">
164 配置240 配置
183您定義 hook 的位置決定了其範圍:259您定義 hook 的位置決定了其範圍:
184 260
185| 位置 | 範圍 | 可共享 |261| 位置 | 範圍 | 可共享 |
186| :-------------------------------------------------------------- | :-------- | :----------- |262| :------------------------------------------ | :------------------------------------------------------------------------ | :------------------------------------ |
187| `~/.claude/settings.json` | 您的所有專案 | 否,本機限定 |263| `~/.claude/settings.json` | 您的所有專案 | 否,本機限定 |
188| `.claude/settings.json` | 單一專案 | 是,可提交到儲存庫 |264| `.claude/settings.json` | 單一專案 | 是,可提交到儲存庫 |
189| `.claude/settings.local.json` | 單一專案 | 否,gitignored |265| `.claude/settings.local.json` | 單一專案 | 否,gitignored(當 Claude Code 將設定儲存到其中時) |
190| 受管理的原則設定 | 組織範圍 | 是,由管理員控制 |266| 受管理的原則設定 | 組織範圍 | 是,由管理員控制 |
191| [Plugin](/docs/zh-TW/plugins) `hooks/hooks.json` | 啟用外掛程式時 | 是,與外掛程式一起打包 |267| [Plugin](/docs/zh-TW/plugins) `hooks/hooks.json` | 啟用外掛程式時 | 是,與外掛程式一起打包 |
192| [Skill](/docs/zh-TW/skills) 或 [agent](/docs/zh-TW/sub-agents) frontmatter | 元件處於活動狀態時 | 是,在元件檔案中定義 |268| [Skill](/docs/zh-TW/skills) frontmatter | 叫用 skill 後的工作階段其餘部分。請參閱 [Skills 和代理中的 Hooks](#hooks-in-skills-and-agents) | 是,在 skill 檔案中定義 |
269| [Subagent](/docs/zh-TW/sub-agents) frontmatter | 該 subagent 執行時 | 是,在 subagent 檔案中定義 |
270
271[Claude Code on the web](/docs/zh-TW/claude-code-on-the-web) 上的雲端工作階段不會讀取您的本機 `~/.claude/settings.json`;那裡的 hooks 來自儲存庫和您組織的伺服器管理設定。在 [自託管環境](/docs/zh-TW/self-hosted-environments-configuration#permissions-and-tool-approval) 中,Claude Code 也執行操作員從執行器主機的 `~/.claude/` 中植入的 hooks,並在該檔案位於 [Claude Code 應用的受管理來源](/docs/zh-TW/managed-settings#how-claude-code-combines-managed-sources) 中時執行執行器映像的受管理設定檔中的 hooks,預設情況下僅當伺服器管理設定或 MDM 傳遞的 Claude Code 原則都不提供受管理層級時。請參閱 [您的設定中哪些內容會轉移到雲端工作階段](/docs/zh-TW/cloud-environments#what-carries-over-from-your-setup) 以了解哪些檔案到達雲端工作階段。
193 272
194有關設定檔解析的詳細資訊,請參閱 [settings](/docs/zh-TW/settings)。企業管理員可以使用 `allowManagedHooksOnly` 來阻止使用者、專案和外掛程式 hooks。在受管理的設定 `enabledPlugins` 中強制啟用的外掛程式的 Hooks 是例外,因此管理員可以通過組織市場分發經過驗證的 hooks。請參閱 [Hook 配置](/docs/zh-TW/settings#hook-configuration)。273有關設定檔解析的詳細資訊,請參閱 [settings](/docs/zh-TW/settings)。
274
275來自設定檔、受管理的原則設定和外掛程式的 Hooks 也在 [subagents](/docs/zh-TW/sub-agents) 內執行。當 subagent 呼叫工具時,工具事件(例如 `PreToolUse` 和 `PostToolUse`)會觸發與主要對話中相同的已配置 hooks,輸入會攜帶 `agent_id` 和 `agent_type` [通用輸入欄位](#common-input-fields) 以識別 subagent。
276
277企業管理員可以使用 `allowManagedHooksOnly` 來限制哪些 hooks 執行:
278
279* 您的使用者、專案、本機和外掛程式 hooks 被阻止。在受管理設定 `enabledPlugins` 中強制啟用的外掛程式的 Hooks 是例外
280* Claude Code 也將您的 [`statusLine`](/docs/zh-TW/statusline)、[`fileSuggestion`](/docs/zh-TW/settings-reference#filesuggestion) 和 [`subagentStatusLine`](/docs/zh-TW/statusline#subagent-status-lines) 設定縮小到受管理設定
281* Claude Code 也停用具有 [`command` 來源](/docs/zh-TW/plugin-marketplaces#command-sources) 的外掛程式,包括在受管理設定 `enabledPlugins` 中強制啟用的外掛程式,除非 [`disableCommandPluginSources`](/docs/zh-TW/settings-reference#disablecommandpluginsources) 明確設定為 `false`。`command` 來源需要 Claude Code v2.1.229 或更新版本
282* Claude Code 也阻止市場 [`headersHelper` 命令](/docs/zh-TW/plugin-marketplaces#authenticate-archive-downloads),除非 [`disableCommandPluginSources`](/docs/zh-TW/settings-reference#disablecommandpluginsources) 明確設定為 `false`,除了受管理設定本身宣告的市場
283
284請參閱 [在 `allowManagedHooksOnly` 下執行的內容](/docs/zh-TW/settings-reference#what-runs-under-allowmanagedhooksonly)。
285
286Hook 項目在設定層級之間合併而不是相互替換:使用者、專案和本機設定新增自己的 hooks 而不移除受管理的 hooks,[`disableAllHooks`](#disable-or-remove-hooks) 設定無法停用來自受管理設定外部的受管理 hooks。
287
288[HTTP hook 允許清單](/docs/zh-TW/settings-reference#hook-and-skill-settings) 適用於來自每個來源的 hooks,包括受管理的原則設定:
289
290* `allowedHttpHookUrls`:在任何設定層級定義時,Claude Code 僅在其 URL 與合併的允許清單相符時執行 HTTP hook 處理程式
291* `httpHookAllowedEnvVars`:定義時,Claude Code 僅將該清單上的環境變數插值到 hook 標頭中
195 292
196<h3 id="matcher-patterns">293<h3 id="matcher-patterns">
197 匹配器模式294 匹配器模式
218每個事件類型在不同的欄位上匹配:315每個事件類型在不同的欄位上匹配:
219 316
220| 事件 | 匹配器篩選的內容 | 範例匹配器值 |317| 事件 | 匹配器篩選的內容 | 範例匹配器值 |
221| :---------------------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |318| :---------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
222| `PreToolUse`、`PostToolUse`、`PostToolUseFailure`、`PermissionRequest`、`PermissionDenied` | 工具名稱 | `Bash`、`Edit\|Write`、`mcp__.*` |319| `PreToolUse`、`PostToolUse`、`PostToolUseFailure`、`PermissionRequest`、`PermissionDenied` | 工具名稱 | `Bash`、`Edit\|Write`、`mcp__.*` |
223| `SessionStart` | 工作階段如何開始 | `startup`、`resume`、`clear`、`compact` |320| `SessionStart` | 工作階段如何開始 | `startup`、`resume`、`clear`、`compact`、`fork` |
224| `Setup` | 哪個 CLI 旗標觸發設定 | `init`、`maintenance` |321| `Setup` | 哪個 CLI 旗標觸發設定 | `init`、`maintenance` |
225| `SessionEnd` | 工作階段為何結束 | `clear`、`resume`、`logout`、`prompt_input_exit`、`bypass_permissions_disabled`、`other` |322| `SessionEnd` | 工作階段為何結束 | `clear`、`resume`、`logout`、`prompt_input_exit`、`other` |
226| `Notification` | 通知類型 | `permission_prompt`、`idle_prompt`、`auth_success`、`elicitation_dialog`、`elicitation_complete`、`elicitation_response`、`agent_needs_input`、`agent_completed` |323| `Notification` | 通知類型 | `permission_prompt`、`idle_prompt`、`auth_success`、`elicitation_dialog`、`elicitation_url_dialog`、`elicitation_complete`、`elicitation_response`、`agent_needs_input`、`agent_completed`、`quota_auto_resume_fired`、`quota_auto_resume_stale`、`quota_auto_resume_disabled` |
227| `SubagentStart` | 代理類型 | `general-purpose`、`Explore`、`Plan`、自訂代理名稱或外掛程式範圍名稱,如 `^my-plugin:reviewer$` |324| `SubagentStart` | 代理類型 | `general-purpose`、`Explore`、`Plan`、自訂代理名稱或外掛程式範圍名稱,如 `^my-plugin:reviewer$` |
228| `PreCompact`、`PostCompact` | 觸發壓縮的原因 | `manual`、`auto` |325| `PreCompact`、`PostCompact` | 觸發壓縮的原因 | `manual`、`auto` |
326| `PreModelSwitch`、`PostModelSwitch` | 工作階段切換到的模型的規範名稱,如 [PreModelSwitch](#premodelswitch) 下所述 | `claude-opus-5`、`claude-opus-4-6\|claude-opus-5`、`.*opus.*` |
229| `SubagentStop` | 代理類型 | 與 `SubagentStart` 相同的值 |327| `SubagentStop` | 代理類型 | 與 `SubagentStart` 相同的值 |
230| `ConfigChange` | 配置來源 | `user_settings`、`project_settings`、`local_settings`、`policy_settings`、`skills` |328| `ConfigChange` | 配置來源 | `user_settings`、`project_settings`、`local_settings`、`policy_settings`、`skills` |
231| `CwdChanged` | 不支援匹配器 | 總是在每次目錄變更時觸發 |329| `CwdChanged` | 不支援匹配器 | 總是在每次出現時觸發 |
232| `FileChanged` | 要監視的檔案名稱(請參閱 [FileChanged](#filechanged)) | `.envrc\|.env` |330| `DirectoryAdded` | 目錄如何被新增 | `slash_command`、`register_repo_root` |
233| `StopFailure` | 錯誤類型 | `rate_limit`、`overloaded`、`authentication_failed`、`oauth_org_not_allowed`、`billing_error`、`invalid_request`、`model_not_found`、`server_error`、`max_output_tokens`、`unknown` |331| `FileChanged` | 要監視的字面檔案名稱(請參閱 [FileChanged](#filechanged)) | `.envrc\|.env` |
332| `StopFailure` | 錯誤類型 | `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` |
234| `InstructionsLoaded` | 載入原因 | `session_start`、`nested_traversal`、`path_glob_match`、`include`、`compact` |333| `InstructionsLoaded` | 載入原因 | `session_start`、`nested_traversal`、`path_glob_match`、`include`、`compact` |
235| `UserPromptExpansion` | 命令名稱 | 您的 skill 或命令名稱 |334| `UserPromptExpansion` | 命令名稱 | 您的 skill 或命令名稱 |
236| `Elicitation` | MCP 伺服器名稱 | 您配置的 MCP 伺服器名稱 |335| `Elicitation` | MCP 伺服器名稱 | 您配置的 MCP 伺服器名稱 |
237| `ElicitationResult` | MCP 伺服器名稱 | 與 `Elicitation` 相同的值 |336| `ElicitationResult` | MCP 伺服器名稱 | 與 `Elicitation` 相同的值 |
238| `UserPromptSubmit`、`PostToolBatch`、`Stop`、`TeammateIdle`、`TaskCreated`、`TaskCompleted`、`WorktreeCreate`、`WorktreeRemove`、`MessageDisplay` | 不支援匹配器 | 總是在每次出現時觸發 |337| `UserPromptSubmit`、`PostToolBatch`、`Stop`、`TeammateIdle`、`TaskCreated`、`TaskCompleted`、`WorktreeCreate`、`WorktreeRemove`、`MessageDisplay` | 不支援匹配器 | 總是在每次出現時觸發 |
239 338
240匹配器針對 Claude Code 在 stdin 上發送給您的 hook 的 [JSON 輸入](#hook-input-and-output) 中的欄位執行。對於工具事件,該欄位是 `tool_name`。每個 [hook 事件](#hook-events) 部分列出了該事件的完整匹配器值集和輸入架構。339在 `cloud_credential_error` 上匹配 `StopFailure` 需要 Claude Code v2.1.267 或更新版本,這是第一個在該值下報告認證載入失敗而不是 `server_error` 或 `unknown` 的版本。
340
341對於大多數事件,Claude Code 針對它在 stdin 上發送給您的 hook 的 [JSON 輸入](#hook-input-and-output) 中的欄位評估匹配器。對於工具事件,該欄位是 `tool_name`。對於 `PreModelSwitch` 和 `PostModelSwitch`,Claude Code 針對它從 `to_model` 衍生的規範名稱評估匹配器,如 [PreModelSwitch](#premodelswitch) 下所述。每個 [hook 事件](#hook-events) 部分列出了該事件的完整匹配器值集和輸入架構。
241 342
242此範例僅在 Claude 寫入或編輯檔案時執行 linting 指令碼:343此範例僅在 Claude 寫入或編輯檔案時執行 linting 指令碼:
243 344
259}360}
260```361```
261 362
262`UserPromptSubmit`、`PostToolBatch`、`Stop`、`TeammateIdle`、`TaskCreated`、`TaskCompleted`、`WorktreeCreate`、`WorktreeRemove`、`MessageDisplay` 和 `CwdChanged` 不支援匹配器,總是在每次出現時觸發。如果您將 `matcher` 欄位新增到這些事件,它會被無聲地忽略。363如果您將 `matcher` 欄位新增到不支援匹配器的事件,它會被無聲地忽略。
263 364
264對於工具事件,您可以通過在個別 hook 處理程式上設定 [`if` 欄位](#common-fields) 來更狹隘地篩選。`if` 使用 [權限規則語法](/docs/zh-TW/permissions) 來匹配工具名稱和參數,因此 `"Bash(git *)"` 僅在任何 Bash 輸入的子命令匹配 `git *` 時執行,`"Edit(*.ts)"` 僅針對 TypeScript 檔案執行。365對於工具事件,您可以通過在個別 hook 處理程式上設定 [`if` 欄位](#common-fields) 來更狹隘地篩選。`if` 使用 [權限規則語法](/docs/zh-TW/permissions) 來匹配工具名稱和參數,因此 `"Bash(git *)"` 僅在任何 Bash 輸入的子命令匹配 `git *` 時執行,`"Edit(*.ts)"` 僅針對 TypeScript 檔案執行。
265 366
323* **[命令 hooks](#command-hook-fields)**(`type: "command"`):執行 shell 命令。您的指令碼在 stdin 上接收事件的 [JSON 輸入](#hook-input-and-output),並通過退出代碼和 stdout 傳回結果。424* **[命令 hooks](#command-hook-fields)**(`type: "command"`):執行 shell 命令。您的指令碼在 stdin 上接收事件的 [JSON 輸入](#hook-input-and-output),並通過退出代碼和 stdout 傳回結果。
324* **[HTTP hooks](#http-hook-fields)**(`type: "http"`):將事件的 JSON 輸入作為 HTTP POST 請求發送到 URL。端點通過使用與命令 hooks 相同的 [JSON 輸出格式](#json-output) 的回應正文傳回結果。425* **[HTTP hooks](#http-hook-fields)**(`type: "http"`):將事件的 JSON 輸入作為 HTTP POST 請求發送到 URL。端點通過使用與命令 hooks 相同的 [JSON 輸出格式](#json-output) 的回應正文傳回結果。
325* **[MCP 工具 hooks](#mcp-tool-hook-fields)**(`type: "mcp_tool"`):在已連接的 [MCP 伺服器](/docs/zh-TW/mcp) 上呼叫工具。工具的文字輸出被視為類似命令 hook stdout。426* **[MCP 工具 hooks](#mcp-tool-hook-fields)**(`type: "mcp_tool"`):在已連接的 [MCP 伺服器](/docs/zh-TW/mcp) 上呼叫工具。工具的文字輸出被視為類似命令 hook stdout。
326* **[提示 hooks](#prompt-and-agent-hook-fields)**(`type: "prompt"`):將提示發送到 Claude 模型進行單輪評估。模型以 JSON 形式返回是/否決定。請參閱 [基於提示的 hooks](#prompt-based-hooks)。427* **[提示 hooks](#prompt-and-agent-hook-fields)**(`type: "prompt"`):將提示發送到 Claude 模型進行單輪評估。模型以 JSON 形式返回決定。請參閱 [基於提示的 hooks](#prompt-based-hooks)。
327* **[代理 hooks](#prompt-and-agent-hook-fields)**(`type: "agent"`):生成一個可以使用 Read、Grep 和 Glob 等工具來驗證條件的 subagent,然後返回決定。代理 hooks 是實驗性的,可能會變更。請參閱 [基於代理的 hooks](#agent-based-hooks)。428* **[代理 hooks](#prompt-and-agent-hook-fields)**(`type: "agent"`):生成一個可以使用 Read、Grep 和 Glob 等工具來驗證條件的 subagent,然後返回決定。代理 hooks 是實驗性的,可能會變更。請參閱 [基於代理的 hooks](#agent-based-hooks)。
328 429
329所有匹配的 hooks 並行執行,相同的處理程式會自動去重。命令 hooks 按命令字串和 `args` 去重,HTTP hooks 按 URL 去重。430所有匹配的 hooks 並行執行。如果您在多個設定檔中定義相同的處理程式,它執行一次。外掛程式或 skill 的相同處理程式副本保持分開。
330 431
331處理程式在目前目錄中執行,使用 Claude Code 的環境。在遠端網路環境中,`$CLAUDE_CODE_REMOTE` 環境變數設定為 `"true"`,在本機 CLI 中未設定。自 v2.1.199 起,[`$CLAUDE_CODE_BRIDGE_SESSION_ID`](/docs/zh-TW/env-vars) 設定為 [Remote Control](/docs/zh-TW/remote-control) 工作階段 ID,而本機工作階段具有活動的 Remote Control 連接。432處理程式在目前目錄中執行,使用 Claude Code 的環境。如果目前目錄不再存在,例如另一個 shell 在工作階段中途刪除的 worktree 或臨時目錄,Claude Code 從以下第一個仍然存在的目錄執行命令 hooks:工作階段開始的目錄、專案根目錄、您的主目錄或系統臨時目錄。Claude Code 在 [debug log](#debug-hooks) 中記錄一個警告,命名回退目錄。
433
434`$CLAUDE_CODE_REMOTE` 環境變數在遠端網路環境中為 `"true"`,在本機 CLI 中未設定。Claude Code v2.1.199 及更新版本在本機工作階段具有活動的 Remote Control 連接時將 [`$CLAUDE_CODE_BRIDGE_SESSION_ID`](/docs/zh-TW/env-vars) 設定為 [Remote Control](/docs/zh-TW/remote-control) 工作階段 ID。
332 435
333<h4 id="common-fields">436<h4 id="common-fields">
334 通用欄位437 通用欄位
337這些欄位適用於所有 hook 類型:440這些欄位適用於所有 hook 類型:
338 441
339| 欄位 | 必需 | 描述 |442| 欄位 | 必需 | 描述 |
340| :-------------- | :- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |443| :-------------- | :- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
341| `type` | 是 | `"command"`、`"http"`、`"mcp_tool"`、`"prompt"` 或 `"agent"` |444| `type` | 是 | `"command"`、`"http"`、`"mcp_tool"`、`"prompt"` 或 `"agent"` |
342| `if` | 否 | 權限規則語法以篩選此 hook 何時執行,例如 `"Bash(git *)"` 或 `"Edit(*.ts)"`。Hook 命令僅在工具呼叫匹配模式時執行。請參閱下面的 [Bash 匹配表](#bash-if-matching) 以了解 Bash 模式如何針對子命令、`$()` 和反引號進行評估。僅在工具事件上評估:`PreToolUse`、`PostToolUse`、`PostToolUseFailure`、`PermissionRequest` 和 `PermissionDenied`。在其他事件上,設定 `if` 的 hook 永遠不會執行。使用與 [權限規則](/docs/zh-TW/permissions) 相同的語法 |445| `if` | 否 | 權限規則語法以篩選此 hook 何時執行,例如 `"Bash(git *)"` 或 `"Edit(*.ts)"`。Hook 命令僅在工具呼叫匹配模式時執行。請參閱下面的 [Bash 匹配表](#bash-if-matching) 以了解 Bash 模式如何針對子命令、`$()` 和反引號進行評估。僅在工具事件上評估:`PreToolUse`、`PostToolUse`、`PostToolUseFailure`、`PermissionRequest` 和 `PermissionDenied`。在其他事件上,設定 `if` 的 hook 永遠不會執行。使用與 [權限規則](/docs/zh-TW/permissions) 相同的語法 |
343| `timeout` | 否 | 取消前的秒數。預設值:`command`、`http` 和 `mcp_tool` 為 600;`prompt` 為 30;`agent` 為 60。[`UserPromptSubmit`](#userpromptsubmit) 將 `command`、`http` 和 `mcp_tool` 的預設值降低到 30,[`MessageDisplay`](#messagedisplay) 將其降低到 10 |446| `timeout` | 否 | 取消前的秒數。Claude Code 不會在您使用 [`async: true`](#run-hooks-in-the-background) 執行的命令 hook 上強制執行。預設值:`command`、`http` 和 `mcp_tool` 為 600;`prompt` 為 30;`agent` 為 60。Claude Code 在 [`UserPromptSubmit`](#userpromptsubmit)、[`PreModelSwitch`](#premodelswitch) 和 [`PostModelSwitch`](#postmodelswitch) 上將 `command`、`http` 和 `mcp_tool` 的預設值降低到 30,在 [`MessageDisplay`](#messagedisplay) 上降低到 10。[`SessionEnd`](#sessionend) hooks 共享 1.5 秒的預算;如果您的設定設定了更長的每個 hook `timeout`,Claude Code 會提高預算以匹配,最多 60 秒 |
344| `statusMessage` | 否 | hook 執行時顯示的自訂微調訊息 |447| `statusMessage` | 否 | hook 執行時顯示的自訂微調訊息 |
345| `once` | 否 | 如果為 `true`,每個工作階段只執行一次,然後被移除。僅在 [skill frontmatter](#hooks-in-skills-and-agents) 中受尊重;在設定檔和代理 frontmatter 中被忽略 |448| `once` | 否 | 如果為 `true`,Claude Code 在第一次成功執行後移除 hook。執行失敗、以退出代碼 2 阻止或逾時的執行會將 hook 保留在原位,因此它在下一個匹配事件上再次執行。僅在 [skill frontmatter](#hooks-in-skills-and-agents) 中受尊重;在設定檔和代理 frontmatter 中被忽略 |
346 449
347`if` 欄位恰好包含一個權限規則。沒有 `&&`、`||` 或清單語法來組合規則;要應用多個條件,請為每個條件定義一個單獨的 hook 處理程式。450`if` 欄位恰好包含一個權限規則。沒有 `&&`、`||` 或清單語法來組合規則;要應用多個條件,請為每個條件定義一個單獨的 hook 處理程式。
348 451
452在檔案工具的 `if` 條件中,單一段目錄模式如 `"Edit(src/**)"` 僅匹配工作目錄中的 `src` 目錄及其下的檔案。要匹配任何深度的名為 `src` 的目錄,請寫 `"Edit(**/src/**)"`。在 v2.1.214 之前,`"Edit(src/**)"` 匹配工作目錄下任何深度的名為 `src` 的目錄。
453
349<span id="bash-if-matching" />對於 Bash 模式,您的 hook 命令是否執行取決於模式的形狀和 Claude 正在呼叫的 Bash 命令。前導 `VAR=value` 指派在匹配前被移除。454<span id="bash-if-matching" />對於 Bash 模式,您的 hook 命令是否執行取決於模式的形狀和 Claude 正在呼叫的 Bash 命令。前導 `VAR=value` 指派在匹配前被移除。
350 455
351| `if` 模式 | Bash 命令 | Hook 執行? | 原因 |456| `if` 模式 | Bash 命令 | Hook 執行? | 原因 |
352| :----------------- | :--------------------- | :------- | :-------------------------------------- |457| :----------------- | :-------------------------- | :------- | :----------------------------------------- |
353| `Bash(git *)` | `FOO=bar git push` | 是 | 前導指派被移除;`git push` 匹配 |458| `Bash(git *)` | `FOO=bar git push` | 是 | 前導指派被移除;`git push` 匹配 |
354| `Bash(git *)` | `npm test && git push` | 是 | 每個子命令都被檢查;`git push` 匹配 |459| `Bash(git *)` | `npm test && git push` | 是 | 每個子命令都被檢查;`git push` 匹配 |
355| `Bash(rm *)` | `echo $(rm -rf /)` | 是 | `$()` 和反引號內的命令被檢查;`rm -rf /` 匹配 |460| `Bash(rm *)` | `echo $(rm -rf /)` | 是 | `$()` 和反引號內的命令被檢查;`rm -rf /` 匹配 |
356| `Bash(rm *)` | `echo $(date)` | 否 | 沒有子命令匹配 `rm *` |461| `Bash(rm *)` | `echo $(date)` | 否 | 沒有子命令匹配 `rm *` |
462| `Bash(cat *)` | `echo before $(date) after` | 否 | 替換可以位於任何參數位置,因此檢查完整命令和 `date`;都不匹配 `cat *` |
463| `Bash(git *)` | `$TOOL git push` | 是 | Claude Code 無法判斷命令名稱展開為什麼,因此它執行 hook |
357| `Bash(git push *)` | `echo $(date)` | 是 | 指定超過命令名稱的模式在 `$()`、反引號或 `$VAR` 上執行 hook |464| `Bash(git push *)` | `echo $(date)` | 是 | 指定超過命令名稱的模式在 `$()`、反引號或 `$VAR` 上執行 hook |
358 465
359當 Bash 命令無法解析時,篩選器也會失敗開放,無論如何執行您的 hook。因為 `if` 篩選器是盡力而為的,請使用 [權限系統](/docs/zh-TW/permissions) 而不是 hook 來強制執行硬允許或拒絕。466當 Claude Code 無法確定 Bash 輸入執行哪些命令時,它無論如何都會執行您的 hook。因為 `if` 篩選器是盡力而為的,請使用 [權限系統](/docs/zh-TW/permissions) 而不是 hook 來強制執行硬允許或拒絕。
360 467
361<h4 id="command-hook-fields">468<h4 id="command-hook-fields">
362 命令 hook 欄位469 命令 hook 欄位
369| `command` | 是 | 要執行的 shell 命令。使用 `args` 時,要直接生成的可執行檔。請參閱 [Exec 形式和 shell 形式](#exec-form-and-shell-form) |476| `command` | 是 | 要執行的 shell 命令。使用 `args` 時,要直接生成的可執行檔。請參閱 [Exec 形式和 shell 形式](#exec-form-and-shell-form) |
370| `args` | 否 | 參數清單。存在時,`command` 被解析為可執行檔並直接使用 `args` 作為參數向量生成,不涉及 shell。請參閱 [Exec 形式和 shell 形式](#exec-form-and-shell-form) |477| `args` | 否 | 參數清單。存在時,`command` 被解析為可執行檔並直接使用 `args` 作為參數向量生成,不涉及 shell。請參閱 [Exec 形式和 shell 形式](#exec-form-and-shell-form) |
371| `async` | 否 | 如果為 `true`,在背景執行而不阻止。請參閱 [在背景執行 hooks](#run-hooks-in-the-background) |478| `async` | 否 | 如果為 `true`,在背景執行而不阻止。請參閱 [在背景執行 hooks](#run-hooks-in-the-background) |
372| `asyncRewake` | 否 | 如果為 `true`,在背景執行並在退出代碼 2 時喚醒 Claude。暗示 `async`。Hook 的 stderr,或如果 stderr 為空則為 stdout,作為系統提醒顯示給 Claude,以便它可以對長時間執行的背景失敗做出反應 |479| `asyncRewake` | 否 | 如果為 `true`,在背景執行並在退出代碼 2 時喚醒 Claude。Hook 的 stderr,或如果 stderr 為空則為 stdout,作為系統提醒顯示給 Claude,以便它可以對長時間執行的背景失敗做出反應 |
373| `shell` | 否 | 用於此 hook 的 shell。接受 `"bash"` 或 `"powershell"`。預設為 `"bash"`,或在未安裝 Git Bash 時在 Windows 上預設為 `"powershell"`。設定 `"powershell"` 在 Windows 上通過 PowerShell 執行命令。不需要 `CLAUDE_CODE_USE_POWERSHELL_TOOL`,因為 hooks 直接生成 PowerShell。設定 `args` 時被忽略 |480| `shell` | 否 | 用於此 hook 的 shell。接受 `"bash"` 或 `"powershell"`。預設為 `"bash"`,或在未安裝 Git Bash 時在 Windows 上預設為 `"powershell"`。設定 `"powershell"` 在 Windows 上通過 PowerShell 執行命令。不需要 `CLAUDE_CODE_USE_POWERSHELL_TOOL`,因為 hooks 直接生成 PowerShell。設定 `args` 時被忽略 |
374 481
375<a id="exec-form-and-shell-form" />482<a id="exec-form-and-shell-form" />
431 538
432Claude Code 將 hook 的 [JSON 輸入](#hook-input-and-output) 作為 POST 請求正文發送,`Content-Type: application/json`。回應正文使用與命令 hooks 相同的 [JSON 輸出格式](#json-output)。539Claude Code 將 hook 的 [JSON 輸入](#hook-input-and-output) 作為 POST 請求正文發送,`Content-Type: application/json`。回應正文使用與命令 hooks 相同的 [JSON 輸出格式](#json-output)。
433 540
434錯誤處理與命令 hooks 不同:非 2xx 回應、連線失敗和逾時都會產生非阻止性錯誤,允許執行繼續。要阻止工具呼叫或拒絕權限,請返回 2xx 回應,其 JSON 正文包含 `decision: "block"` 或 `hookSpecificOutput` 與 `permissionDecision: "deny"`。541錯誤處理與命令 hooks 不同;請參閱 [HTTP 回應處理](#http-response-handling)。
435 542
436此範例將 `PreToolUse` 事件發送到本機驗證服務,使用來自 `MY_TOKEN` 環境變數的令牌進行驗證:543此範例將 `PreToolUse` 事件發送到本機驗證服務,使用來自 `MY_TOKEN` 環境變數的令牌進行驗證:
437 544
470| `tool` | 是 | 該伺服器上要呼叫的工具名稱 |577| `tool` | 是 | 該伺服器上要呼叫的工具名稱 |
471| `input` | 否 | 傳遞給工具的參數。字串值支援來自 hook 的 [JSON 輸入](#hook-input-and-output) 的 `${path}` 替換,例如 `"${tool_input.file_path}"` |578| `input` | 否 | 傳遞給工具的參數。字串值支援來自 hook 的 [JSON 輸入](#hook-input-and-output) 的 `${path}` 替換,例如 `"${tool_input.file_path}"` |
472 579
473工具的文字內容被視為類似命令 hook stdout:如果它解析為有效的 [JSON 輸出](#json-output),它會被處理為決定,否則它會顯示為純文字。如果命名的伺服器未連接,或工具返回 `isError: true`,hook 會產生非阻止性錯誤,執行繼續。580Claude Code 讀取工具的文字內容的方式與讀取命令 hook stdout 相同,遵循 [退出代碼 0 下的解析規則](#exit-code-0)。如果命名的伺服器未連接,或工具返回 `isError: true`,hook 會產生非阻止性錯誤,執行繼續。
474
475MCP 工具 hooks 在 Claude Code 連接到您的 MCP 伺服器後在每個 hook 事件上都可用。`SessionStart` 和 `Setup` 通常在伺服器完成連接之前觸發,因此這些事件上的 hooks 應該預期首次執行時出現「未連接」錯誤。
476 581
477此範例在每個 `Write` 或 `Edit` 後在 `my_server` MCP 伺服器上呼叫 `security_scan` 工具,傳遞編輯檔案的路徑:582此範例在每個 `Write` 或 `Edit` 後在 `my_server` MCP 伺服器上呼叫 `security_scan` 工具,傳遞編輯檔案的路徑:
478 583
496}601}
497```602```
498 603
604MCP 工具 hook 只能在 Claude Code 將工作階段的 MCP 伺服器提供給 hooks 後執行。`SessionStart` 和 `Setup` 可能在該點之前觸發:
605
606* **在啟動時**:`SessionStart` 在伺服器可用之前觸發,包括當您使用 `--continue` 或 `--resume` 啟動時。Claude Code 跳過事件的 `mcp_tool` hooks 而不呼叫其工具,[debug log](#debug-hooks) 記錄 `mcp_tool hooks are not available for the 'SessionStart' hook event (no MCP client context)`。
607* **稍後在執行中的工作階段**:在 `/clear` 或壓縮後,`SessionStart` 再次觸發,伺服器已可用,其 `mcp_tool` hooks 執行。
608* **在 `Setup` 上**:`Setup` 總是在伺服器可用之前觸發,因此 Claude Code 每次都跳過其 `mcp_tool` hooks 並記錄相同的訊息,命名 `Setup`。
609
610例如,此配置在 `SessionStart` hook 上呼叫 `my_server` MCP 伺服器上的 `load_context` 工具,沒有匹配器,因此它適用於每個 `SessionStart` 來源:
611
612```json theme={null}
613{
614 "hooks": {
615 "SessionStart": [
616 {
617 "hooks": [
618 {
619 "type": "mcp_tool",
620 "server": "my_server",
621 "tool": "load_context"
622 }
623 ]
624 }
625 ]
626 }
627}
628```
629
630當您執行 `claude` 時,Claude Code 跳過此 hook,永遠不呼叫 `load_context`,並將 `no MCP client context` 訊息寫入 debug log。在該相同工作階段中執行 `/clear`,hook 執行並呼叫 `load_context`。`type: "command"` hook 在 `SessionStart` 上執行,因此對於工作階段從其第一個轉向需要的任何內容,請使用一個。
631
499<h4 id="prompt-and-agent-hook-fields">632<h4 id="prompt-and-agent-hook-fields">
500 提示和代理 hook 欄位633 提示和代理 hook 欄位
501</h4>634</h4>
513 646
514使用這些佔位符按相對於專案或外掛程式根目錄的路徑參考 hook 指令碼,無論 hook 執行時的工作目錄如何:647使用這些佔位符按相對於專案或外掛程式根目錄的路徑參考 hook 指令碼,無論 hook 執行時的工作目錄如何:
515 648
516* `${CLAUDE_PROJECT_DIR}`:專案根目錄。Claude Code 也在 [stdio MCP 伺服器](/docs/zh-TW/mcp#option-3-add-a-local-stdio-server) 和外掛程式 LSP 伺服器的環境中設定此變數。649* `${CLAUDE_PROJECT_DIR}`:工作階段開始的專案根目錄。Claude Code 也在 [stdio MCP 伺服器](/docs/zh-TW/mcp#option-3-add-a-local-stdio-server) 和外掛程式 LSP 伺服器的環境中設定此變數。
517* `${CLAUDE_PLUGIN_ROOT}`:外掛程式的安裝目錄,用於與 [plugin](/docs/zh-TW/plugins) 一起打包的指令碼。在每次外掛程式更新時變更。650* `${CLAUDE_PLUGIN_ROOT}`:外掛程式的安裝目錄,用於與 [plugin](/docs/zh-TW/plugins) 一起打包的指令碼。請參閱 [外掛程式環境變數](/docs/zh-TW/plugins-reference#environment-variables) 以了解路徑在更新中的行為。
518* `${CLAUDE_PLUGIN_DATA}`:外掛程式的 [持久資料目錄](/docs/zh-TW/plugins-reference#persistent-data-directory),用於應該在外掛程式更新後保留的依賴項和狀態。651* `${CLAUDE_PLUGIN_DATA}`:外掛程式的 [持久資料目錄](/docs/zh-TW/plugins-reference#persistent-data-directory),用於應該在外掛程式更新後保留的依賴項和狀態。
519 652
520對於任何參考路徑佔位符的 hook,優先使用 [exec 形式](#exec-form-and-shell-form)。Exec 形式將每個 `args` 元素作為一個參數傳遞,不進行 shell 標記化,因此包含空格或特殊字元的路徑不需要引用。在 shell 形式中,用雙引號括起每個佔位符。653<Note>
654 **Worktrees 不同。** 如果 Claude 在工作階段期間進入 [worktree](/docs/zh-TW/worktrees),Claude Code 將 `${CLAUDE_PROJECT_DIR}` 保留在原位,並以不同的方式將 worktree 路徑傳遞給您的 hooks:
655
656 * **`${CLAUDE_PROJECT_DIR}` 保持不變**:它仍然指向工作階段開始的專案根目錄,因此像 `${CLAUDE_PROJECT_DIR}/.claude/hooks/check-style.sh` 這樣的命令仍然在主簽出中執行指令碼。
657 * **`cwd` 跟隨 Claude**:hook 的 [輸入 JSON](#common-input-fields) 中的 `cwd` 欄位在 Claude 進入 worktree 後是 worktree 根目錄,在 Claude 執行 `cd` 後是新目錄。當 hook 需要知道 Claude 正在哪個目錄中工作時,讀取它。
658</Note>
659
660對於任何參考路徑佔位符的 hook,優先使用 [exec 形式](#exec-form-and-shell-form)。在 shell 形式中,用雙引號括起每個佔位符。
521 661
522<Tabs>662<Tabs>
523 <Tab title="專案指令碼">663 <Tab title="專案指令碼">
577 Skills 和代理中的 Hooks717 Skills 和代理中的 Hooks
578</h3>718</h3>
579 719
580除了設定檔和外掛程式外,hooks 還可以使用 frontmatter 直接在 [skills](/docs/zh-TW/skills) 和 [subagents](/docs/zh-TW/sub-agents) 中定義。這些 hooks 的範圍限於元件的生命週期,只有在該元件處於活動狀態時才執行。720除了設定檔和外掛程式外,hooks 還可以使用 frontmatter 直接在 [skills](/docs/zh-TW/skills) 和 [subagents](/docs/zh-TW/sub-agents) 中定義,使用與基於設定的 hooks 相同的配置格式。Claude Code 保持它們註冊的時間取決於元件:
581
582支援所有 hook 事件。對於 subagents,`Stop` hooks 會自動轉換為 `SubagentStop`,因為這是 subagent 完成時觸發的事件。
583 721
584Hooks 使用與基於設定的 hooks 相同的配置格式,但範圍限於元件的生命週期,並在完成時清理。722* **Subagent hooks**:Claude Code 僅在該 subagent 執行時執行它們,並在其完成時移除它們。Claude Code 在此處將 `Stop` hook 轉換為 `SubagentStop`,這是 subagent 完成時觸發的事件。
723* **Skill hooks**:Claude Code 在您或 Claude 叫用 skill 時註冊它們,並在工作階段的其餘部分保持執行它們,在 skill 自己的轉向之後的轉向上也是如此。要讓 Claude Code 在第一次成功執行後移除 hook,請在其上設定 [`once: true`](#common-fields)。
585 724
586此 skill 定義了一個 `PreToolUse` hook,在每個 `Bash` 命令之前執行安全驗證指令碼:725此 skill 定義了一個 `PreToolUse` hook,在每個 `Bash` 命令之前執行安全驗證指令碼:
587 726
598---737---
599```738```
600 739
601代理在其 YAML frontmatter 中使用相同的格式。740Subagents 在其 YAML frontmatter 中使用相同的格式。
741
742專案 skill 中的 Frontmatter hooks 遵循與設定檔中 hooks 相同的 [工作區信任規則](#workspace-trust)。Claude Code 在您或 Claude 叫用 skill 時註冊它們,包括在您未信任的資料夾中的 `-p` 執行。
743
744專案 subagent 中的 Frontmatter hooks 僅在您接受代理檔案來自的資料夾的 [工作區信任對話](/docs/zh-TW/permissions#project-allow-rules-and-workspace-trust) 後執行。`-p` 工作階段不計為接受它。[在您信任資料夾之前執行的內容](/docs/zh-TW/permissions#what-runs-before-you-trust-a-folder) 將此與設定檔規則進行比較,subagents 頁面列出 [哪些範圍是豁免的](/docs/zh-TW/sub-agents#hooks-in-subagent-frontmatter)。在 v2.1.218 之前,這些 hooks 可以從您未信任的資料夾執行。
602 745
603<h3 id="the-/hooks-menu">746<h3 id="the-/hooks-menu">
604 `/hooks` 選單747 `/hooks` 選單
608 751
609選單顯示所有五種 hook 類型:`command`、`prompt`、`agent`、`http` 和 `mcp_tool`。每個 hook 都標有 `[type]` 前綴和指示其定義位置的來源:752選單顯示所有五種 hook 類型:`command`、`prompt`、`agent`、`http` 和 `mcp_tool`。每個 hook 都標有 `[type]` 前綴和指示其定義位置的來源:
610 753
611* `User`:來自 `~/.claude/settings.json`754* `User Settings`:來自 `~/.claude/settings.json`
612* `Project`:來自 `.claude/settings.json`755* `Project Settings`:來自 `.claude/settings.json`
613* `Local`:來自 `.claude/settings.local.json`756* `Local Settings`:來自 `.claude/settings.local.json`
614* `Plugin`:來自外掛程式的 `hooks/hooks.json`757* `Plugin Hooks`:來自外掛程式的 `hooks/hooks.json`
615* `Session`:在目前工作階段中記錄在記憶體中758* `Session Hooks`:在目前工作階段中記錄在記憶體中
616* `Built-in`:由 Claude Code 內部註冊
617 759
618選擇 hook 會開啟詳細檢視,顯示其事件、匹配器、類型、來源檔案和完整命令、提示或 URL。選單是唯讀的:要新增、修改或移除 hooks,請直接編輯設定 JSON 或要求 Claude 進行變更。760選擇 hook 會開啟詳細檢視,顯示其事件、匹配器、類型、來源檔案和完整命令、提示或 URL。選單是唯讀的:要新增、修改或移除 hooks,請直接編輯設定 JSON 或要求 Claude 進行變更。
619 761
623 765
624要移除 hook,請從設定 JSON 檔案中刪除其項目。766要移除 hook,請從設定 JSON 檔案中刪除其項目。
625 767
626要暫時停用所有 hooks 而不移除它們,請在設定檔中設定 `"disableAllHooks": true`。沒有辦法在保留 hook 在配置中的同時停用單個 hook。768要暫時停用所有 hooks 而不移除它們,請在設定檔中設定 `"disableAllHooks": true`。Claude Code 讀取 [設定優先順序](/docs/zh-TW/settings#settings-precedence) 應用後剩下的值,因此專案的 `.claude/settings.json` 中的 `"disableAllHooks": false` 會覆蓋您的使用者設定中的 `true`。要根據專案的設定關閉一次執行的 hooks,請傳遞 `--settings '{"disableAllHooks": true}'`,這優先於專案和本機設定。沒有辦法在保留 hook 在配置中的同時停用單個 hook。
627 769
628`disableAllHooks` 設定遵循受管理的設定階層。如果管理員已通過受管理的原則設定配置了 hooks,則在使用者、專案或本機設定中設定的 `disableAllHooks` 無法停用這些受管理的 hooks。只有在受管理的設定層級設定的 `disableAllHooks` 才能停用受管理的 hooks。770`disableAllHooks` 設定遵循受管理的設定階層。如果管理員已通過受管理的原則設定配置了 hooks,則在使用者、專案或本機設定中設定的 `disableAllHooks` 無法停用這些受管理的 hooks。只有在受管理的設定層級設定的 `disableAllHooks` 才能停用受管理的 hooks。有關每個層級的完整範圍,請參閱 [`disableAllHooks`](/docs/zh-TW/settings-reference#disableallhooks)。
629 771
630對設定檔中 hooks 的直接編輯通常由檔案監視程式自動拾取。772對設定檔中 hooks 的直接編輯通常由檔案監視程式自動拾取。
631 773
635 777
636命令 hooks 通過 stdin 接收 JSON 資料,並通過退出代碼、stdout 和 stderr 傳回結果。HTTP hooks 接收相同的 JSON 作為 POST 請求正文,並通過 HTTP 回應正文傳回結果。本部分涵蓋所有事件通用的欄位和行為。每個事件在 [Hook 事件](#hook-events) 下的部分包括其特定的輸入架構和決定控制選項。778命令 hooks 通過 stdin 接收 JSON 資料,並通過退出代碼、stdout 和 stderr 傳回結果。HTTP hooks 接收相同的 JSON 作為 POST 請求正文,並通過 HTTP 回應正文傳回結果。本部分涵蓋所有事件通用的欄位和行為。每個事件在 [Hook 事件](#hook-events) 下的部分包括其特定的輸入架構和決定控制選項。
637 779
638在 macOS 和 Linux 上,自 v2.1.139 起,命令 hooks 在沒有控制終端的自己的工作階段中執行。Hook 程序和任何子程序無法開啟 `/dev/tty` 或直接向 Claude Code 介面發送逃逸序列。Windows 沒有 `/dev/tty`。要在任何平台上向使用者顯示訊息,請在 JSON 輸出中返回 [`systemMessage`](#json-output)。要觸發桌面通知、設定視窗標題或響鈴,請改為返回 [`terminalSequence`](#emit-terminal-notifications)。780在 macOS 和 Linux 上,命令 hooks 在沒有控制終端的自己的工作階段中執行。Hook 程序和任何子程序無法開啟 `/dev/tty` 或直接向 Claude Code 介面發送逃逸序列。Windows 沒有 `/dev/tty`。
781
782要在任何平台上向使用者顯示訊息,請在 JSON 輸出中返回 [`systemMessage`](#json-output)。某些事件會捨棄它或將其傳遞到其他地方,每個 [事件的部分](#hook-events) 都會說明。要觸發桌面通知、設定視窗標題或響鈴,請改為返回 [`terminalSequence`](#emit-terminal-notifications)。
639 783
640<h3 id="common-input-fields">784<h3 id="common-input-fields">
641 通用輸入欄位785 通用輸入欄位
644Hook 事件接收這些欄位作為 JSON,除了每個 [hook 事件](#hook-events) 部分中記錄的事件特定欄位。對於命令 hooks,此 JSON 通過 stdin 到達。對於 HTTP hooks,它作為 POST 請求正文到達。788Hook 事件接收這些欄位作為 JSON,除了每個 [hook 事件](#hook-events) 部分中記錄的事件特定欄位。對於命令 hooks,此 JSON 通過 stdin 到達。對於 HTTP hooks,它作為 POST 請求正文到達。
645 789
646| 欄位 | 描述 |790| 欄位 | 描述 |
647| :---------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |791| :---------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
648| `session_id` | 目前工作階段識別碼 |792| `session_id` | 目前工作階段識別碼 |
649| `prompt_id` | UUID 識別目前正在處理的使用者提示。與 [OpenTelemetry 事件上的 `prompt.id` 屬性](/docs/zh-TW/monitoring-usage#event-correlation-attributes) 相符,因此您可以將 hook 輸出與單一提示的遙測相關聯。在第一個使用者輸入之前不存在。需要 Claude Code v2.1.196 或更新版本 |793| `prompt_id` | UUID 識別目前正在處理的使用者提示。與 [OpenTelemetry 事件上的 `prompt.id` 屬性](/docs/zh-TW/monitoring-usage#event-correlation-attributes) 相符,因此您可以將 hook 輸出與單一提示的遙測相關聯。在第一個使用者輸入之前不存在。需要 Claude Code v2.1.196 或更新版本 |
650| `transcript_path` | 對話 JSON 的路徑。成績單檔案以非同步方式寫入,可能滯後於記憶體中的對話,因此當 hook 觸發時,它可能尚未包含目前回合的最新訊息。需要目前回合最後助手文字的 Hooks 應在 [Stop](#stop) 和 [SubagentStop](#subagentstop) 上使用 `last_assistant_message`,而不是讀取成績單 |794| `transcript_path` | 對話 JSON 的路徑。成績單檔案以非同步方式寫入,可能滯後於記憶體中的對話,因此當 hook 觸發時,它可能尚未包含目前回合的最新訊息。需要目前回合最後助手文字的 Hooks 應在 [Stop](#stop) 和 [SubagentStop](#subagentstop) 上使用 `last_assistant_message`,而不是讀取成績單 |
651| `cwd` | 叫用 hook 時的目前工作目錄 |795| `cwd` | 叫用 hook 時的目前工作目錄 |
796| `scratchpad_dir` | 工作階段的暫存目錄的路徑,Claude 在其中保存臨時工作檔案。當工作階段沒有暫存或臨時目錄不可用時不存在。需要 Claude Code v2.1.257 或更新版本 |
652| `permission_mode` | 目前 [權限模式](/docs/zh-TW/permissions#permission-modes):`"default"`、`"plan"`、`"acceptEdits"`、`"auto"`、`"dontAsk"` 或 `"bypassPermissions"`。標記為**手動**的模式以 `"default"` 到達,永遠不會以 `"manual"` 到達,因此匹配 `"default"` 的指令碼繼續工作。並非所有事件都接收此欄位。檢查每個 [hook 事件](#hook-events) 部分中的 JSON 範例 |797| `permission_mode` | 目前 [權限模式](/docs/zh-TW/permissions#permission-modes):`"default"`、`"plan"`、`"acceptEdits"`、`"auto"`、`"dontAsk"` 或 `"bypassPermissions"`。標記為**手動**的模式以 `"default"` 到達,永遠不會以 `"manual"` 到達,因此匹配 `"default"` 的指令碼繼續工作。並非所有事件都接收此欄位。檢查每個 [hook 事件](#hook-events) 部分中的 JSON 範例 |
653| `effort` | 物件,其 `level` 欄位保存該回合的活躍 [努力等級](/docs/zh-TW/model-config#adjust-effort-level):`"low"`、`"medium"`、`"high"`、`"xhigh"` 或 `"max"`。如果請求的模型努力等級超過目前模型支援的等級,這是模型實際使用的降級等級。Ultracode 不是一個不同的等級,報告為 `"xhigh"`。該物件與 [狀態行](/docs/zh-TW/statusline#available-data) `effort` 欄位相符。存在於在工具使用上下文中觸發的事件,例如 `PreToolUse`、`PostToolUse`、`Stop` 和 `SubagentStop`,當目前模型支援努力參數時。該等級也可作為 `$CLAUDE_EFFORT` 環境變數提供給 hook 命令和 Bash 工具。 |798| `effort` | 物件,其 `level` 欄位保存執行 hook 時生效的 [努力等級](/docs/zh-TW/model-config#adjust-effort-level):`"low"`、`"medium"`、`"high"`、`"xhigh"` 或 `"max"`。如果您設定的等級是活躍模型不支援的,`level` 會報告 Claude Code 實際執行的等級;[調整努力等級](/docs/zh-TW/model-config#adjust-effort-level) 說明它如何選擇該等級。Ultracode 不是一個不同的等級,報告為 `"xhigh"`。該物件與 [狀態行](/docs/zh-TW/statusline#available-data) `effort` 欄位相符。存在於在工具使用上下文中觸發的事件,例如 `PreToolUse`、`PostToolUse`、`Stop` 和 `SubagentStop`,當目前模型支援努力參數時。該等級也可作為 `$CLAUDE_EFFORT` 環境變數提供給 hook 命令和 Bash 工具。 |
654| `hook_event_name` | 觸發的事件名稱 |799| `hook_event_name` | 觸發的事件名稱 |
655 800
656使用 `--agent` 執行或在 subagent 內執行時,包括兩個額外欄位:801使用 `--agent` 執行或在 subagent 內執行時,包括兩個額外欄位:
657 802
658| 欄位 | 描述 |803| 欄位 | 描述 |
659| :----------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |804| :----------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
660| `agent_id` | Subagent 的唯一識別碼。僅當 hook 在 subagent 呼叫內觸發時出現。使用此項來區分 subagent hook 呼叫與主執行緒呼叫。 |805| `agent_id` | Subagent 的唯一識別碼。僅當 hook 在 subagent 呼叫內觸發時出現。使用此項來區分 subagent hook 呼叫與主執行緒呼叫。 |
661| `agent_type` | 代理名稱(例如 `"Explore"` 或 `"security-reviewer"`)。當工作階段使用 `--agent` 或 hook 在 subagent 內觸發時出現。對於 subagents,subagent 的類型優先於工作階段的 `--agent` 值。對於 [自訂 subagents](/docs/zh-TW/sub-agents),這是代理 frontmatter 中的 `name` 欄位,而不是檔案名稱。對於由 [plugin](/docs/zh-TW/plugins) 提供的 subagents,這是外掛範圍識別碼,例如 `my-plugin:reviewer`,而不是裸 frontmatter 名稱。請參閱 [SubagentStart](#subagentstart) 以了解如何針對外掛範圍名稱編寫匹配器。 |806| `agent_type` | 代理名稱(例如 `"Explore"` 或 `"security-reviewer"`)。當工作階段使用 `--agent` 或 hook 在 subagent 內觸發時出現。對於 subagents,subagent 的類型優先於工作階段的 `--agent` 值。請參閱 [SubagentStart](#subagentstart) 以了解自訂和 plugin subagents 報告的值,以及如何針對 plugin 範圍名稱編寫匹配器。 |
807
808只有 [`SessionStart`](#sessionstart) hooks 可以接收 `model` 欄位,且 Claude Code 不一定包含它。[`PreModelSwitch`](#premodelswitch) 和 [`PostModelSwitch`](#postmodelswitch) hooks 接收 `from_model` 和 `to_model` 代替,因此使用 PostModelSwitch hook 來追蹤模型在工作階段期間的變化。
809
810沒有 `$CLAUDE_MODEL` 環境變數。如果您在 shell 中設定它,hook 可以讀取 `$ANTHROPIC_MODEL`,但當您在工作階段期間使用 `/model` 切換模型時,該值不會改變。
662 811
663只有 [`SessionStart`](#sessionstart) hooks 可以接收 `model` 欄位,且不保證存在。沒有 `$CLAUDE_MODEL` 環境變數。Hook 程序繼承父環境,因此如果您在 shell 中設定它,它可以讀取 `$ANTHROPIC_MODEL`,但當您在工作階段期間使用 `/model` 切換模型時,該值不會改變。一組變數不被繼承:Claude Code [從它產生的每個子程序中移除 `OTEL_*` 匯出器變數](/docs/zh-TW/monitoring-usage#administrator-configuration),包括 hooks。812Hook 程序繼承父環境,除了 Claude Code [從它產生的每個子程序中移除](/docs/zh-TW/monitoring-usage#administrator-configuration) 的 `OTEL_*` 匯出器變數,以及當 [`CLAUDE_CODE_SUBPROCESS_ENV_SCRUB`](/docs/zh-TW/env-vars#variables) 設定為 `1` 時,它剝離的變數。
664 813
665例如,Bash 命令的 `PreToolUse` hook 在 stdin 上接收此內容:814例如,Bash 命令的 `PreToolUse` hook 在 stdin 上接收此內容:
666 815
670 "prompt_id": "550e8400-e29b-41d4-a716-446655440000",819 "prompt_id": "550e8400-e29b-41d4-a716-446655440000",
671 "transcript_path": "/home/user/.claude/projects/.../transcript.jsonl",820 "transcript_path": "/home/user/.claude/projects/.../transcript.jsonl",
672 "cwd": "/home/user/my-project",821 "cwd": "/home/user/my-project",
822 "scratchpad_dir": "/tmp/claude-1000/-home-user-my-project/abc123/scratchpad",
673 "permission_mode": "default",823 "permission_mode": "default",
674 "hook_event_name": "PreToolUse",824 "hook_event_name": "PreToolUse",
675 "tool_name": "Bash",825 "tool_name": "Bash",
676 "tool_input": {826 "tool_input": {
677 "command": "npm test"827 "command": "npm test",
678 }828 "description": "Run test suite",
829 "timeout": 120000,
830 "run_in_background": false
831 },
832 "tool_use_id": "toolu_01ABC123..."
679}833}
680```834```
681 835
682`tool_name` 和 `tool_input` 欄位是事件特定的。每個 [hook 事件](#hook-events) 部分記錄了該事件的額外欄位。836`tool_name`、`tool_input` 和 `tool_use_id` 欄位是事件特定的。每個 [hook 事件](#hook-events) 部分記錄了該事件的額外欄位。
683 837
684<h3 id="exit-code-output">838<h3 id="exit-code-output">
685 退出代碼輸出839 退出代碼輸出
686</h3>840</h3>
687 841
688來自您的 hook 命令的退出代碼告訴 Claude Code 該操作是應該進行、被阻止還是被忽略。842來自您的 hook 命令的退出代碼告訴 Claude Code 該操作是應該進行、被阻止還是被忽略。退出代碼不單獨起作用。Claude Code 在每個退出代碼上從 stdout 讀取 [JSON 輸出欄位](#json-output),而不僅僅是 0,對於使用標準決定模型的事件,通過架構驗證的已解析物件與代碼一起生效。Exit 2 的阻止是 JSON 無法覆蓋的唯一結果。
689 843
690**退出 0** 表示成功。Claude Code 解析 stdout 以查找 [JSON 輸出欄位](#json-output)。JSON 輸出僅在退出 0 時處理。對於大多數事件,stdout 被寫入詳細日誌,但不在成績單中顯示。例外是 `UserPromptSubmit`、`UserPromptExpansion` 和 `SessionStart`,其中 stdout 被新增為 Claude 可以看到和作用的上下文。844兩個表格擁有每個事件的例外:[每個事件的退出代碼 2 行為](#exit-code-2-behavior-per-event) 說明每個事件的退出代碼做什麼,[決定控制](#decision-control) 說明每個事件接受哪些決定欄位。通用欄位(如 `systemMessage`)在大多數事件中工作,並列在 [JSON 輸出](#json-output) 表格中。
691 845
692**退出 2** 表示阻止性錯誤。Claude Code 忽略 stdout 和其中的任何 JSON。相反,stderr 文字被反饋給 Claude 作為錯誤訊息。效果取決於事件:`PreToolUse` 阻止工具呼叫,`UserPromptSubmit` 拒絕提示,等等。有關完整清單,請參閱 [退出代碼 2 行為](#exit-code-2-behavior-per-event)。846<h4 id="exit-code-0">
847 退出代碼 0
848</h4>
849
850退出 0 表示成功,是當您列印 JSON 進行結構化控制時的預期退出代碼。
851
852對於大多數事件,Claude Code 將 stdout 寫入詳細日誌,不在成績單中顯示。例外是 `UserPromptSubmit`、`UserPromptExpansion`、`SessionStart` 和 `PostModelSwitch`,其中 Claude Code 將純文字 stdout 新增為 Claude 可以看到和作用的上下文。
853
854Claude Code 是否將您的 stdout 讀取為 [JSON 輸出](#json-output) 或純文字取決於它如何開始和結束,忽略周圍的空白:
693 855
694**任何其他退出代碼** 是大多數 hook 事件的非阻止性錯誤。成績單顯示 `<hook name> hook error` 通知,後跟 stderr 的第一行,因此您可以識別原因而無需 `--debug`。執行繼續,完整的 stderr 被寫入詳細日誌。856* **以 `{` 開始並以 `}` 結束**:Claude Code 將其解析為 JSON。當輸出是兩行或更多行,每行本身都解析為 JSON,且沒有行是設定欄位的 [JSON 輸出](#json-output) 物件時,Claude Code 將整個輸出視為純文字。當其中一行確實設定欄位時,整個輸出是解析失敗,如下所述。
857* **以 `{` 開始但不以 `}` 結束**:Claude Code 將其視為純文字。
858* **以其他任何內容開始**:Claude Code 將其視為純文字、JSON 陣列或包含的引用 JSON 字串。
695 859
696例如,一個 hook 命令指令碼,阻止危險的 Bash 命令:860對於使用標準決定模型的事件,以已解析物件退出 0 但未通過架構驗證是非阻止性錯誤:操作進行,成績單顯示 `<hook name> hook error` 通知,帶有驗證訊息。在任何退出代碼上都會發生相同情況,除了 2,而 [exit 2 仍然阻止](#exit-code-2)。
861
862對於使用標準決定模型的事件,當 Claude Code 嘗試將您的 stdout 解析為 JSON 且無法時,它在除 2 以外的每個退出代碼上報告非阻止性錯誤。成績單顯示 `<hook name> hook error` 通知,帶有解析訊息。在新增純文字 stdout 作為上下文的事件上,Claude Code 不新增文字。在 v2.1.248 之前,Claude Code 將該 stdout 視為純文字。
863
864來自以 0 退出的 hook 的 Stderr 僅進入詳細日誌,永遠不進入成績單,Claude 永遠看不到它。要自己讀取它,請啟用 [詳細日誌](#debug-hooks)。要從 `PostToolUse` 或 `PostToolUseFailure` hook 向 Claude 顯示警告,請改為退出 2,以便 [Claude 看到 stderr](#exit-code-2-behavior-per-event),儘管工具已執行。
865
866<h4 id="exit-code-2">
867 退出代碼 2
868</h4>
869
870退出 2 表示阻止性錯誤。在 [可以阻止的事件](#exit-code-2-behavior-per-event) 上,退出 2 無論您是否列印 JSON 都會阻止:即使 JSON `permissionDecision` 為 `"allow"` 也無法覆蓋它。Claude Code 仍然在 stdout 上讀取任何有效的 [JSON 輸出](#json-output)。在 `Elicitation` 和 `ElicitationResult` 上,exit-2 hook 的 `hookSpecificOutput` 被忽略。
871
872阻止訊息是您的 JSON 的阻止決定的原因(當它做出決定時),否則是您的 stderr 文字。阻止做什麼因事件而異:`PreToolUse` 阻止工具呼叫,`UserPromptSubmit` 拒絕提示,等等。[每個事件的退出代碼 2 行為](#exit-code-2-behavior-per-event) 列出每個事件的效果,每個事件的部分說明訊息去哪裡。
873
874在列印未通過 [JSON 輸出](#json-output) 架構驗證的 JSON 時退出 2 的 hook 仍然阻止:Claude Code 使用 stderr 作為阻止原因,並在詳細日誌中記錄驗證失敗。在 v2.1.214 之前,Claude Code 將該組合視為非阻止性錯誤,操作進行。
875
876此指令碼通過退出 2 阻止 `rm` 命令,並將每個其他命令留給正常權限流程:
697 877
698```bash theme={null}878```bash theme={null}
699#!/bin/bash879#!/bin/bash
700# 從 stdin 讀取 JSON 輸入,檢查命令880# 從 stdin 讀取 JSON 輸入,檢查命令
701command=$(jq -r '.tool_input.command' < /dev/stdin)881input=$(cat)
882command=$(jq -r '.tool_input.command' <<<"$input")
702 883
703if [[ "$command" == rm* ]]; then884if [[ "$command" == rm* ]]; then
704 echo "Blocked: rm commands are not allowed" >&2885 echo "Blocked: rm commands are not allowed" >&2
708exit 0 # 無決定:正常權限流程適用889exit 0 # 無決定:正常權限流程適用
709```890```
710 891
892<h4 id="other-exit-codes">
893 其他退出代碼
894</h4>
895
896任何其他退出代碼對於大多數 hook 事件本身不會阻止。發生的情況取決於您的 stdout:
897
898* 使用通過架構驗證的已解析物件,對於使用標準決定模型的事件,Claude Code 忽略退出代碼,JSON 單獨決定結果:
899 * 事件支援的每個欄位都被接受,包括 `permissionDecision`、`additionalContext`、`updatedInput` 和 `systemMessage`,hook 不被報告為錯誤。
900 * [決定控制](#decision-control) 列出每個事件的決定欄位;通用欄位如 `systemMessage` 遵循 [JSON 輸出](#json-output) 表格。
901* 使用未通過架構驗證的已解析物件,對於使用標準決定模型的事件,它與 [exit 0 上](#exit-code-0) 相同的非阻止性錯誤:操作進行,`<hook name> hook error` 通知帶有驗證訊息。
902* 使用 Claude Code [嘗試解析為 JSON](#exit-code-0) 且無法的 stdout,Claude Code 對於使用標準決定模型的事件報告與 exit 0 上相同的非阻止性錯誤。操作進行,通知帶有解析訊息。
903* 使用 Claude Code [視為純文字](#exit-code-0) 的 stdout,或使用空 stdout,對於大多數 hook 事件是非阻止性錯誤:操作進行,成績單顯示 `<hook name> hook error` 通知,後跟 stderr 的第一行,前綴為 `Failed with non-blocking status code:`。要捕獲完整 stderr,請啟用 [詳細日誌](#debug-hooks)。
904
905標準決定模型之外的事件在 [每個事件表](#exit-code-2-behavior-per-event) 中保持自己的行:`WorktreeCreate` 在任何非零退出時失敗建立,無論您的 JSON 說什麼,事件完全捨棄 hook 輸出(如 `StopFailure`)除了副作用欄位(如 `terminalSequence`)在每個退出代碼上忽略您的 JSON,除了副作用欄位(如 `terminalSequence`),它仍然觸發。
906
907無法啟動的 hook 落入相同的非阻止性桶。當指令碼路徑不存在或不可執行時,shell 以代碼(如 127)退出,您看到相同的通知,帶有解釋器的訊息,例如 `Failed with non-blocking status code: /bin/sh: /path/to/hook.sh: No such file or directory`。對於大多數 hook 事件,操作進行。當您設定原則 hook 時,在其第一次執行時監視此通知:`settings.json` 中的拼寫錯誤路徑使閘門無聲地禁用。
908
711<Warning>909<Warning>
712 對於大多數 hook 事件,只有退出代碼 2 會阻止操作。Claude Code 將退出代碼 1 視為非阻止性錯誤並繼續操作,儘管 1 是傳統的 Unix 失敗代碼。如果您的 hook 旨在強制執行原則,請使用 `exit 2`。例外是 `WorktreeCreate`,其中任何非零退出代碼都會中止 worktree 建立。910 對於大多數 hook 事件,退出代碼 2 是唯一通過代碼單獨阻止的退出代碼。沒有 stdout 上的有效 JSON,Claude Code 將退出代碼 1 視為非阻止性錯誤並繼續操作,儘管 1 是傳統的 Unix 失敗代碼。如果您的 hook 旨在強制執行原則,請使用 `exit 2`。Worktree 事件不同:來自 `WorktreeCreate` 的任何非零退出代碼都會中止 worktree 建立,來自 `WorktreeRemove` 的任何非零退出代碼會在目錄仍然存在後使 worktree 移除失敗。
713</Warning>911</Warning>
714 912
913<h4 id="timeouts">
914 逾時
915</h4>
916
917除了您使用 [`async: true`](#run-hooks-in-the-background) 執行的命令 hook,Claude Code 取消達到其 [`timeout`](#common-fields) 的 `command`、`http` 或 `mcp_tool` hook,捨棄 hook 的輸出,因此在大多數事件上,逾時的 hook 不呈現決定。
918
919在 [`PreModelSwitch`](#premodelswitch) 上,在其逾時時取消的 hook 阻止模型切換。在 `PreToolUse` 上,兩個 hook 系列不同:
920
921* 逾時的 `command`、`http` 或 `mcp_tool` hook 不阻止工具呼叫。呼叫通過正常 [權限流程](/docs/zh-TW/permissions) 繼續,因此不要指望停滯的 hook 充當閘門。
922* 超過其逾時的 [Agent SDK 回調 hook](/docs/zh-TW/agent-sdk/hooks) [阻止工具呼叫](#pretooluse)。
923
715<h4 id="exit-code-2-behavior-per-event">924<h4 id="exit-code-2-behavior-per-event">
716 每個事件的退出代碼 2 行為925 每個事件的退出代碼 2 行為
717</h4>926</h4>
719退出代碼 2 是 hook 發出「停止,不要這樣做」的方式。效果取決於事件,因為某些事件代表可以被阻止的操作(例如尚未發生的工具呼叫),而其他事件代表已經發生或無法防止的事情。928退出代碼 2 是 hook 發出「停止,不要這樣做」的方式。效果取決於事件,因為某些事件代表可以被阻止的操作(例如尚未發生的工具呼叫),而其他事件代表已經發生或無法防止的事情。
720 929
721| Hook 事件 | 可以阻止? | 退出 2 時發生的情況 |930| Hook 事件 | 可以阻止? | 退出 2 時發生的情況 |
722| :-------------------- | :---- | :-------------------------------------------------------------------------- |931| :-------------------- | :---- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
723| `PreToolUse` | 是 | 阻止工具呼叫 |932| `PreToolUse` | 是 | 阻止工具呼叫 |
724| `PermissionRequest` | 是 | 拒絕權限 |933| `PermissionRequest` | 否 | 此事件不接受退出代碼 2,權限流程保持不變。改為通過 [`decision` 物件](#permissionrequest-decision-control) 拒絕 |
725| `UserPromptSubmit` | 是 | 阻止提示處理並清除提示 |934| `UserPromptSubmit` | 是 | 阻止提示處理並清除提示 |
726| `UserPromptExpansion` | 是 | 阻止擴展 |935| `UserPromptExpansion` | 是 | 阻止擴展 |
727| `Stop` | 是 | 防止 Claude 停止,繼續對話 |936| `Stop` | 是 | 防止 Claude 停止,繼續對話 |
730| `TaskCreated` | 是 | 回滾任務建立 |939| `TaskCreated` | 是 | 回滾任務建立 |
731| `TaskCompleted` | 是 | 防止任務被標記為已完成 |940| `TaskCompleted` | 是 | 防止任務被標記為已完成 |
732| `ConfigChange` | 是 | 阻止配置變更生效(除了 `policy_settings`) |941| `ConfigChange` | 是 | 阻止配置變更生效(除了 `policy_settings`) |
733| `StopFailure` | 否 | 輸出和退出代碼被忽略 |942| `StopFailure` | 否 | 輸出和退出代碼被忽略,除了 `terminalSequence` |
734| `PostToolUse` | 否 | 向 Claude 顯示 stderr;工具已執行 |943| `PostToolUse` | 否 | 向 Claude 顯示 stderr;工具已執行 |
735| `PostToolUseFailure` | 否 | 向 Claude 顯示 stderr;工具已失敗 |944| `PostToolUseFailure` | 否 | 向 Claude 顯示 stderr;工具已失敗 |
736| `PostToolBatch` | 是 | 在下一個模型呼叫之前停止代理迴圈 |945| `PostToolBatch` | 是 | 在下一個模型呼叫之前停止代理迴圈 |
737| `PermissionDenied` | 否 | 退出代碼和 stderr 被忽略,因為拒絕已發生。使用 JSON `hookSpecificOutput.retry: true` 告訴模型它可能重試 |946| `PermissionDenied` | 否 | 退出代碼和 stderr 被忽略,因為拒絕已發生。使用 JSON `hookSpecificOutput.retry: true` 告訴模型它可能重試;Claude Code 忽略 [no-verdict denials](#permissiondenied-decision-control) 的 `retry: true` |
738| `Notification` | 否 | 僅向使用者顯示 stderr |947| `Notification` | 否 | 退出代碼和 stderr 被忽略 |
739| `SubagentStart` | 否 | 僅向使用者顯示 stderr |948| `SubagentStart` | 否 | 僅向使用者顯示 stderr |
740| `SessionStart` | 否 | 僅向使用者顯示 stderr |949| `SessionStart` | 否 | 僅向使用者顯示 stderr |
741| `Setup` | 否 | 僅向使用者顯示 stderr |950| `Setup` | 否 | 退出代碼和 stderr 被忽略 |
742| `SessionEnd` | 否 | 僅向使用者顯示 stderr |951| `SessionEnd` | 否 | 僅向使用者顯示 stderr |
743| `CwdChanged` | 否 | 僅向使用者顯示 stderr |952| `CwdChanged` | 否 | 僅向使用者顯示 stderr |
953| `DirectoryAdded` | 否 | Stderr 進入詳細日誌;目錄已新增 |
744| `FileChanged` | 否 | 僅向使用者顯示 stderr |954| `FileChanged` | 否 | 僅向使用者顯示 stderr |
745| `PreCompact` | 是 | 阻止壓縮 |955| `PreCompact` | 是 | 阻止壓縮 |
746| `PostCompact` | 否 | 僅向使用者顯示 stderr |956| `PostCompact` | 否 | 僅向使用者顯示 stderr |
957| `PreModelSwitch` | 是 | 阻止模型切換並向使用者顯示 stderr |
958| `PostModelSwitch` | 否 | 僅向使用者顯示 stderr;模型已切換 |
747| `Elicitation` | 是 | 拒絕徵詢 |959| `Elicitation` | 是 | 拒絕徵詢 |
748| `ElicitationResult` | 是 | 阻止回應(操作變為拒絕) |960| `ElicitationResult` | 是 | 阻止回應(操作變為拒絕) |
749| `WorktreeCreate` | 是 | 任何非零退出代碼都會導致 worktree 建立失敗 |961| `WorktreeCreate` | 是 | 任何非零退出代碼都會導致 worktree 建立失敗 |
750| `WorktreeRemove` | 否 | 失敗僅在偵錯模式中記錄 |962| `WorktreeRemove` | 是 | 任何非零退出代碼會在目錄仍然存在後使 worktree 移除失敗。請參閱 [WorktreeRemove](#worktreeremove) 以了解目錄發生的情況 |
751| `InstructionsLoaded` | 否 | 退出代碼被忽略 |963| `InstructionsLoaded` | 否 | 退出代碼被忽略 |
752| `MessageDisplay` | 否 | 原始文字被顯示 |964| `MessageDisplay` | 否 | 原始文字被顯示 |
753 965
754對於 `SessionStart`、`Setup` 和 `SubagentStart`,退出代碼 2 stderr 在成績單中呈現為 `<hook name> hook error` 通知,與 [非阻止性錯誤](#exit-code-output) 相同的方式。Claude 看不到它,工作階段或 subagent 繼續進行。對於 `SubagentStart`,通知出現在 subagent 自己的成績單中,而不是在父對話中。966對於 `SessionStart`、`SubagentStart` 和 `PostModelSwitch`,Claude Code 在成績單中呈現退出代碼 2 stderr 作為 `<hook name> hook error` 通知,與 [非阻止性錯誤](#exit-code-output) 相同的方式。Claude 看不到它,工作階段或 subagent 繼續進行。對於 `SubagentStart`,通知出現在 subagent 自己的成績單中,而不是在父對話中。
755
756自 Claude Code v2.1.199 起,`SessionStart`、`Setup` 和 `SubagentStart` 在成績單中顯示退出代碼 2 stderr。較早的版本僅將其寫入詳細日誌。
757 967
758<h3 id="http-response-handling">968<h3 id="http-response-handling">
759 HTTP 回應處理969 HTTP 回應處理
760</h3>970</h3>
761 971
762HTTP hooks 使用 HTTP 狀態代碼和回應正文,而不是退出代碼和 stdout:972HTTP hooks 使用 HTTP 狀態代碼和回應正文,而不是退出代碼和 stdout。下面的結果適用於大多數事件;在 [每個事件表](#exit-code-2-behavior-per-event) 中有自己的失敗合約的事件(如 `WorktreeCreate`)將該合約應用於失敗的 HTTP hook:
763 973
764* **2xx 且正文為空**:成功,等同於退出代碼 0 且無輸出974* **2xx 且正文為空**:成功,等同於退出代碼 0 且無輸出
765* **2xx 且正文為純文字**:成功,文字被新增為上下文975* **2xx 且 JSON 物件正文**:使用與命令 hooks 相同的 [JSON 輸出](#json-output) 架構進行解析。未通過架構驗證的正文是非阻止性錯誤
766* **2xx 且正文為 JSON**:成功,使用與命令 hooks 相同的 [JSON 輸出](#json-output) 架構進行解析976* **2xx 且任何其他正文,如純文字**:非阻止性錯誤,處理方式與非 2xx 狀態相同。Claude Code 不將文字新增到 Claude 的上下文
767* **非 2xx 狀態**:非阻止性錯誤,執行繼續977* **非 2xx 狀態**:非阻止性錯誤,執行繼續
768* **連線失敗或逾時**:非阻止性錯誤,執行繼續978* **連線失敗**:非阻止性錯誤,執行繼續
979* **逾時**:hook 被取消,如 [逾時](#timeouts) 下所述
769 980
770與命令 hooks 不同,HTTP hooks 無法僅通過狀態代碼發出阻止性錯誤信號。要阻止工具呼叫或拒絕權限,請返回 2xx 回應,其 JSON 正文包含適當的決定欄位。981與命令 hooks 不同,HTTP hooks 無法僅通過狀態代碼發出阻止性錯誤信號。要阻止工具呼叫或拒絕權限,請返回 2xx 回應,其 JSON 正文包含適當的決定欄位。
771 982
773 JSON 輸出984 JSON 輸出
774</h3>985</h3>
775 986
776退出代碼讓您允許或阻止,但 JSON 輸出提供更細粒度的控制。與其以代碼 2 退出來阻止,不如以 0 退出並將 JSON 物件列印到 stdout。Claude Code 從該 JSON 讀取特定欄位以控制行為,包括 [決定控制](#decision-control) 以阻止、允許或升級給使用者。987退出代碼只讓您阻止或保持沉默,但 JSON 輸出提供更細粒度的控制。與其以代碼 2 退出來阻止,不如退出 0 並將 JSON 物件列印到 stdout。Claude Code 從該 JSON 讀取特定欄位以控制行為,包括 [決定控制](#decision-control) 以阻止、允許或升級給使用者。
777 988
778<Note>989<Note>
779 您必須為每個 hook 選擇一種方法,而不是兩種:要麼單獨使用退出代碼進行信號傳遞,要麼以 0 退出並列印 JSON 以進行結構化控制。Claude Code 僅在退出 0 時處理 JSON。如果您退出 2,任何 JSON 都會被忽略。990 為每個 hook 選擇一種方法:要麼單獨使用退出代碼進行信號傳遞,要麼退出 0 並列印 JSON 進行結構化控制。如果您混合它們,退出 2 保持其 [阻止效果](#exit-code-2-behavior-per-event),Claude Code 仍然讀取 JSON 欄位,除了 [Exit code 2](#exit-code-2) 下記錄的一個徵詢例外。
780</Note>991</Note>
781 992
782您的 hook 的 stdout 必須僅包含 JSON 物件。如果您的 shell 設定檔在啟動時列印文字,它可能會干擾 JSON 解析。請參閱故障排除指南中的 [JSON 驗證失敗](/docs/zh-TW/hooks-guide#json-validation-failed)。993您的 hook 的 stdout 必須僅包含 JSON 物件。如果您的 shell 設定檔在啟動時列印文字,它可能會干擾 JSON 解析。請參閱故障排除指南中的 [Hook JSON 無效](/docs/zh-TW/hooks-guide#hook-json-has-no-effect)。
783 994
784Hook 輸出字串,包括 `additionalContext`、`systemMessage` 和純 stdout,上限為 10,000 個字元。超過此限制的輸出會儲存到檔案並替換為預覽和檔案路徑,與大型工具結果的處理方式相同。995Hook 的 `additionalContext`、`systemMessage` 和 `initialUserMessage` 字串,以及其純 stdout,上限為 10,000 個字元:
996
997* **範圍**:Claude Code 分別測量每個字串,即使多個 hooks 為同一事件執行。對於 JSON 輸出,每個欄位分別測量;純 stdout 整體測量。
998* **超過限制**:Claude Code 將輸出儲存到工作階段目錄中的檔案,並將其替換為檔案路徑和最多前 2,000 個字元的預覽。大型有效 Bash 結果的處理方式相同,如 [輸出限制](/docs/zh-TW/tools-reference#output-limits) 下所述。與該 Bash 上限不同,此上限沒有設定或環境變數來提高它。
999* **讀取檔案**:Claude Code 不要求 Claude 讀取檔案,因此將 Claude 必須始終看到的任何內容保持在上限內。
785 1000
786JSON 物件支援三種欄位:1001JSON 物件支援三種欄位:
787 1002
788* **通用欄位**,如 `continue`,在所有事件中工作。這些列在下表中。1003* **通用欄位**,如 `continue`,列在下表中。每個事件都接受它們,但某些事件捨棄它們或將 `systemMessage` 傳遞到成績單以外的地方。每個事件的部分都說明。`terminalSequence` 在這些事件上也工作,除了 [發出終端通知](#emit-terminal-notifications) 下列出的例外。
789* **頂層 `decision` 和 `reason`** 由某些事件用來阻止或提供反饋。1004* **頂層 `decision` 和 `reason`** 由某些事件用來阻止或提供反饋。
790* **`hookSpecificOutput`** 是一個嵌套物件,用於需要更豐富控制的事件。它需要一個設定為事件名稱的 `hookEventName` 欄位。1005* **`hookSpecificOutput`** 是一個嵌套物件,用於需要更豐富控制的事件。它需要一個設定為事件名稱的 `hookEventName` 欄位。
791 1006
792| 欄位 | 預設 | 描述 |1007| 欄位 | 預設 | 描述 |
793| :----------------- | :------ | :------------------------------------------------------------------------------------------------------------------------------------------ |1008| :----------------- | :------ | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
794| `continue` | `true` | 如果為 `false`,Claude 在 hook 執行後完全停止處理。優先於任何事件特定的決定欄位 |1009| `continue` | `true` | 如果為 `false`,Claude 在 hook 執行後完全停止處理。優先於任何事件特定的決定欄位 |
795| `stopReason` | 無 | 當 `continue` 為 `false` 時向使用者顯示的訊息。不向 Claude 顯示 |1010| `stopReason` | 無 | 當 `continue` 為 `false` 時向使用者顯示的訊息。它停留在對話中,因此如果對話繼續,Claude 會看到它 |
796| `suppressOutput` | `false` | 如果為 `true`,隱藏詳細日誌中的 hook stdout |1011| `suppressOutput` | `false` | 無效果:Claude Code 接受欄位但不作用。成功的 hook 的 stdout 永遠不在成績單中顯示,並在詳細日誌中記錄 |
797| `systemMessage` | 無 | 向使用者顯示的警告訊息 |1012| `systemMessage` | 無 | 向使用者顯示的警告訊息。在 [Agent SDK](/docs/zh-TW/agent-sdk/overview) 和 [`--output-format stream-json`](/docs/zh-TW/headless) 輸出中,它可以作為 [`SDKInformationalMessage`](/docs/zh-TW/agent-sdk/typescript#sdkinformationalmessage) 到達 |
798| `terminalSequence` | 無 | Claude Code 代表您發出的終端逃逸序列,例如桌面通知、視窗標題或響鈴。限制為 OSC `0`/`1`/`2`/`9`/`99`/`777` 和 BEL。如果值包含允許清單外的任何內容,該欄位將被忽略。使用此項而不是寫入 `/dev/tty`,後者對 hooks 不可用 |1013| `terminalSequence` | 無 | Claude Code 代表您發出的終端逃逸序列,例如桌面通知、視窗標題或響鈴。限制為 OSC `0`/`1`/`2`/`9`/`99`/`777` 和 BEL。如果值包含允許清單外的任何內容,該欄位將被忽略。使用此項而不是寫入 `/dev/tty`,後者對 hooks 不可用 |
799 1014
800要無論事件類型如何都完全停止 Claude:1015要完全停止 Claude:
801 1016
802```json theme={null}1017```json theme={null}
803{ "continue": false, "stopReason": "Build failed, fix errors before continuing" }1018{ "continue": false, "stopReason": "Build failed, fix errors before continuing" }
804```1019```
805 1020
1021對於 `PreToolUse` 和 `PostToolUse` hooks,停止適用,即使工具呼叫失敗或在 Claude 仍在串流回應時完成。
1022
806<h4 id="emit-terminal-notifications">1023<h4 id="emit-terminal-notifications">
807 發出終端通知1024 發出終端通知
808</h4>1025</h4>
809 1026
810`terminalSequence` 欄位需要 Claude Code v2.1.141 或更新版本。
811
812Hooks 在沒有控制終端的情況下執行,因此直接寫入逃逸序列到 `/dev/tty` 會失敗。相反,在 `terminalSequence` 欄位中返回逃逸序列,Claude Code 通過其自己的終端寫入路徑為您發出它。這是無競爭的,在 tmux 和 GNU screen 內工作,並在沒有 `/dev/tty` 的 Windows 上工作。1027Hooks 在沒有控制終端的情況下執行,因此直接寫入逃逸序列到 `/dev/tty` 會失敗。相反,在 `terminalSequence` 欄位中返回逃逸序列,Claude Code 通過其自己的終端寫入路徑為您發出它。這是無競爭的,在 tmux 和 GNU screen 內工作,並在沒有 `/dev/tty` 的 Windows 上工作。
813 1028
814該欄位接受一個或多個允許清單逃逸序列的字串:1029該欄位接受一個或多個允許清單逃逸序列的字串:
821 1036
822序列可以用 BEL 或 ST 終止。允許清單外的任何內容,包括 CSI 游標和顏色序列、OSC 調色板序列、OSC 8 超連結、OSC 52 剪貼簿寫入和 OSC 1337,都會被拒絕,該欄位將被忽略。1037序列可以用 BEL 或 ST 終止。允許清單外的任何內容,包括 CSI 游標和顏色序列、OSC 調色板序列、OSC 8 超連結、OSC 52 剪貼簿寫入和 OSC 1337,都會被拒絕,該欄位將被忽略。
823 1038
1039Claude Code 在處理您的 hook 輸出時寫入序列本身,因此該欄位在捨棄 `systemMessage` 和 `continue` 的事件上工作,例如 `Notification` 和 `StopFailure`。它有兩個限制:
1040
1041* Claude Code 僅在互動式工作階段中寫入序列,且僅在其介面在螢幕上時。在使用 `-p` 旗標的非互動式模式和 Agent SDK 中,它忽略該欄位。
1042* `WorktreeCreate` 命令 hook 無法返回 JSON,因為 Claude Code 將其 stdout 讀取為 worktree 路徑。HTTP `WorktreeCreate` hook 返回 JSON 並可以包含該欄位。
1043
824下面的範例從 `Notification` hook 觸發桌面通知。逃逸序列使用 `printf` 八進位逃逸構建,因此控制位元組永遠不會出現在 shell 命令行上,`jq -n --arg` 構建 JSON 輸出,因此通知訊息中的引號、反斜線和換行符被正確逃逸:1044下面的範例從 `Notification` hook 觸發桌面通知。逃逸序列使用 `printf` 八進位逃逸構建,因此控制位元組永遠不會出現在 shell 命令行上,`jq -n --arg` 構建 JSON 輸出,因此通知訊息中的引號、反斜線和換行符被正確逃逸:
825 1045
826```bash theme={null}1046```bash theme={null}
827#!/bin/bash1047#!/bin/bash
828# Notification hook:當 Claude Code 需要注意時 ping 桌面。1048# Notification hook:當 Claude Code 需要注意時 ping 桌面。
829input=$(cat)1049input=$(cat)
830title="Claude Code'1050title="Claude Code"
831body=$(jq -r '.message // 'Needs your attention"' <<<"$input")1051body=$(jq -r '.message // "Needs your attention"' <<<"$input")
832seq=$(printf '\033]777;notify;%s;%s\007' "$title" "$body")1052seq=$(printf '\033]777;notify;%s;%s\007' "$title" "$body")
833jq -nc --arg seq "$seq" '{terminalSequence: $seq}'1053jq -nc --arg seq "$seq" '{terminalSequence: $seq}'
834```1054```
835 1055
836`{ "terminalSequence": "..." }` 形狀在任何 shell 或語言中都相同。在 Windows 上,在 PowerShell 或指令碼中構建逃逸字串並發出相同的 JSON 物件。1056`{ "terminalSequence": "..." }` 形狀在任何 shell 或語言中都相同。
837
838<Note>
839 `terminalSequence` 是之前直接寫入逃逸序列到 `/dev/tty` 的 hooks 的支援替代品。允許清單限制為無法移動游標或改變顏色的序列,因此 hook 永遠無法損壞螢幕上的提示。
840</Note>
841 1057
842<h4 id="add-context-for-claude">1058<h4 id="add-context-for-claude">
843 為 Claude 新增上下文1059 為 Claude 新增上下文
858 1074
859提醒出現的位置取決於事件:1075提醒出現的位置取決於事件:
860 1076
861* [SessionStart](#sessionstart)、[Setup](#setup) 和 [SubagentStart](#subagentstart):在對話開始,在第一個提示之前1077* [SessionStart](#sessionstart) 和 [SubagentStart](#subagentstart):在對話開始,在第一個提示之前
862* [UserPromptSubmit](#userpromptsubmit) 和 [UserPromptExpansion](#userpromptexpansion):與提交的提示一起1078* [UserPromptSubmit](#userpromptsubmit) 和 [UserPromptExpansion](#userpromptexpansion):與提交的提示一起
863* [PreToolUse](#pretooluse)、[PostToolUse](#posttooluse)、[PostToolUseFailure](#posttoolusefailure) 和 [PostToolBatch](#posttoolbatch):在工具結果旁邊1079* [PreToolUse](#pretooluse)、[PostToolUse](#posttooluse)、[PostToolUseFailure](#posttoolusefailure) 和 [PostToolBatch](#posttoolbatch):在工具結果旁邊
864* [Stop](#stop) 和 [SubagentStop](#subagentstop):在回合結束。對話繼續,以便 Claude 可以對反饋採取行動。請參閱 [Stop 決定控制](#stop-decision-control)1080* [Stop](#stop) 和 [SubagentStop](#subagentstop):在回合結束。對話繼續,以便 Claude 可以對反饋採取行動。請參閱 [Stop 決定控制](#stop-decision-control)
1081* [PostModelSwitch](#postmodelswitch):與切換後的下一個請求一起。請參閱 [PostModelSwitch 決定控制](#postmodelswitch-decision-control) 以了解時機
1082
1083當多個 hooks 為同一事件返回 `additionalContext` 時,Claude 接收所有值。
865 1084
866當多個 hooks 為同一事件返回 `additionalContext` 時,Claude 接收所有值。如果值超過 10,000 個字元,Claude Code 會將完整文字寫入工作階段目錄中的檔案,並將檔案路徑與簡短預覽傳遞給 Claude。1085如果值超過 10,000 個字元,Claude Code 會將文字寫入工作階段目錄中的檔案,並將檔案路徑與最多前 2,000 個字元的預覽傳遞給 Claude。Claude 可以讀取檔案,但 Claude Code 不要求它。
867 1086
868使用 `additionalContext` 來提供 Claude 應該知道的有關您環境目前狀態或剛剛執行的操作的資訊:1087使用 `additionalContext` 來提供 Claude 應該知道的有關您環境目前狀態或剛剛執行的操作的資訊:
869 1088
875 1094
876將文字寫成事實陳述,而不是命令式系統指示。「部署目標是生產」或「此儲存庫使用 `bun test`」之類的措辭讀起來像專案資訊。框架為帶外系統命令的文字可能會觸發 Claude 的提示注入防禦,這會導致 Claude 將文字呈現給您,而不是將其視為上下文。1095將文字寫成事實陳述,而不是命令式系統指示。「部署目標是生產」或「此儲存庫使用 `bun test`」之類的措辭讀起來像專案資訊。框架為帶外系統命令的文字可能會觸發 Claude 的提示注入防禦,這會導致 Claude 將文字呈現給您,而不是將其視為上下文。
877 1096
878注入後,文字會儲存在工作階段成績單中。對於 `PostToolUse` 或 `UserPromptSubmit` 等中期事件,使用 `--continue` 或 `--resume` 繼續會重播儲存的文字,而不是為過去的回合重新執行 hook,因此時間戳或提交 SHA 等值在繼續時變得陳舊。`SessionStart` hooks 在使用 `source` 設定為 `"resume"` 的 `--resume` 時再次執行,因此它們可以刷新其上下文。1097Claude Code 在工作階段成績單中儲存注入的文字。對於 `PostToolUse` 或 `UserPromptSubmit` 等中期事件,當您使用 `--continue` 或 `--resume` 繼續時,Claude Code 重播儲存的文字,而不是為過去的回合重新執行 hook,因此時間戳或提交 SHA 等值變得陳舊。`SessionStart` hooks 在使用 `source` 設定為 `"resume"` 的 `--resume` 時再次執行,或如果您新增了 `--fork-session` 則為 `"fork"`,因此它們可以刷新其上下文。
879 1098
880<h4 id="decision-control">1099<h4 id="decision-control">
881 決定控制1100 決定控制
884並非每個事件都支援阻止或通過 JSON 控制行為。支援的事件各自使用不同的欄位集來表達該決定。在編寫 hook 之前,使用此表作為快速參考:1103並非每個事件都支援阻止或通過 JSON 控制行為。支援的事件各自使用不同的欄位集來表達該決定。在編寫 hook 之前,使用此表作為快速參考:
885 1104
886| 事件 | 決定模式 | 關鍵欄位 |1105| 事件 | 決定模式 | 關鍵欄位 |
887| :-------------------------------------------------------------------------------------------------------------------------- | :---------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |1106| :-------------------------------------------------------------------------------------------------------------------------- | :---------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
888| UserPromptSubmit、UserPromptExpansion、PostToolUse、PostToolUseFailure、PostToolBatch、Stop、SubagentStop、ConfigChange、PreCompact | 頂層 `decision` | `decision: "block"`、`reason`。Stop 和 SubagentStop 也接受 `hookSpecificOutput.additionalContext` 用於 [繼續對話的非錯誤反饋](#stop-decision-control) |1107| UserPromptSubmit、UserPromptExpansion、PostToolUse、PostToolUseFailure、PostToolBatch、Stop、SubagentStop、ConfigChange、PreCompact | 頂層 `decision` | `decision: "block"`、`reason`。Stop 和 SubagentStop 也接受 `hookSpecificOutput.additionalContext` 用於 [繼續對話的非錯誤反饋](#stop-decision-control) |
889| TeammateIdle、TaskCreated、TaskCompleted | 退出代碼或 `continue: false` | 退出代碼 2 使用 stderr 反饋阻止操作。JSON `{"continue": false, "stopReason": "..."}` 也會完全停止隊友,匹配 `Stop` hook 行為 |1108| TeammateIdle、TaskCompleted | 退出代碼或 `continue: false` | 退出代碼 2 使用 stderr 反饋阻止操作。JSON `{"continue": false, "stopReason": "..."}` 也會完全停止隊友,匹配 `Stop` hook 行為;[TaskCompleted 在 `TaskUpdate` 工具觸發事件時忽略它](#taskcompleted-decision-control) |
1109| TaskCreated | 退出代碼或頂層 `decision` | 退出代碼 2 或 `decision: "block"` [取消任務](#taskcreated-decision-control) 並將訊息返回給 Claude。`continue: false` 被忽略 |
890| PreToolUse | `hookSpecificOutput` | `permissionDecision`(allow/deny/ask/defer)、`permissionDecisionReason` |1110| PreToolUse | `hookSpecificOutput` | `permissionDecision`(allow/deny/ask/defer)、`permissionDecisionReason` |
1111| PreModelSwitch | `hookSpecificOutput` 或頂層 `decision` | `permissionDecision`(allow/deny/ask)、`permissionDecisionReason`。`decision: "block"` 也 [取消切換](#premodelswitch-decision-control) |
891| PermissionRequest | `hookSpecificOutput` | `decision.behavior`(allow/deny) |1112| PermissionRequest | `hookSpecificOutput` | `decision.behavior`(allow/deny) |
892| PermissionDenied | `hookSpecificOutput` | `retry: true` 告訴模型它可能重試被拒絕的工具呼叫 |1113| PermissionDenied | `hookSpecificOutput` | `retry: true` 告訴模型它可能重試被拒絕的工具呼叫;Claude Code 忽略 [no-verdict denials](#permissiondenied-decision-control) 的 `retry: true` |
893| WorktreeCreate | 路徑返回 | 命令 hook 在 stdout 上列印路徑;HTTP hook 通過 `hookSpecificOutput.worktreePath` 返回。Hook 失敗或缺少路徑會導致建立失敗 |1114| WorktreeCreate | 路徑返回 | 命令 hook 在 stdout 上列印路徑;HTTP hook 通過 `hookSpecificOutput.worktreePath` 返回。Hook 失敗或缺少路徑會導致建立失敗 |
1115| WorktreeRemove | 退出代碼 | 任何非零退出代碼會在目錄仍然存在後使移除失敗。JSON 輸出被捨棄 |
894| Elicitation | `hookSpecificOutput` | `action`(accept/decline/cancel)、`content`(accept 的表單欄位值) |1116| Elicitation | `hookSpecificOutput` | `action`(accept/decline/cancel)、`content`(accept 的表單欄位值) |
895| ElicitationResult | `hookSpecificOutput` | `action`(accept/decline/cancel)、`content`(覆蓋表單欄位值) |1117| ElicitationResult | `hookSpecificOutput` | `action`(accept/decline/cancel)、`content`(覆蓋表單欄位值) |
896| MessageDisplay | `hookSpecificOutput` | `displayContent` 替換螢幕上顯示的文字。僅顯示:成績單和 Claude 看到的內容保持原始 |1118| MessageDisplay | `hookSpecificOutput` | `displayContent` 替換螢幕上顯示的文字。僅顯示:成績單和 Claude 看到的內容保持原始 |
897| SessionStart、Setup、SubagentStart | 僅上下文 | `hookSpecificOutput.additionalContext` 為 Claude 新增上下文。SessionStart 也接受 [`initialUserMessage`、`watchPaths`、`sessionTitle` 和 `reloadSkills`](#sessionstart-decision-control)。無阻止或決定控制 |1119| SessionStart、SubagentStart、PostModelSwitch | 僅上下文 | `hookSpecificOutput.additionalContext` 為 Claude 新增上下文。SessionStart 也接受 [`initialUserMessage`、`watchPaths`、`sessionTitle` 和 `reloadSkills`](#sessionstart-decision-control)。無阻止或決定控制 |
898| WorktreeRemove、Notification、SessionEnd、PostCompact、InstructionsLoaded、StopFailure、CwdChanged、FileChanged | 無 | 無決定控制。用於副作用,如記錄或清理 |1120| Setup、Notification、SessionEnd、PostCompact、InstructionsLoaded、StopFailure、CwdChanged、DirectoryAdded、FileChanged | 無 | 無決定控制。用於副作用,如記錄或清理 |
899 1121
900一些事件也可以重寫內容,而不僅僅是允許或阻止它:1122一些事件也可以重寫內容,而不僅僅是允許或阻止它:
901 1123
910 1132
911<Tabs>1133<Tabs>
912 <Tab title="頂層決定">1134 <Tab title="頂層決定">
913 由 `UserPromptSubmit`、`UserPromptExpansion`、`PostToolUse`、`PostToolUseFailure`、`PostToolBatch`、`Stop`、`SubagentStop`、`ConfigChange` 和 `PreCompact` 使用。唯一的值是 `"block"`。要允許操作進行,請從 JSON 中省略 `decision`,或以 0 退出而不帶任何 JSON:1135 `decision` 的唯一值是 `"block"`。要允許操作進行,請從 JSON 中省略 `decision`,或以 0 退出而不帶任何 JSON:
914 1136
915 ```json theme={null}1137 ```json theme={null}
916 {1138 {
959 Hook 事件1181 Hook 事件
960</h2>1182</h2>
961 1183
962每個事件對應於 Claude Code 生命週期中 hooks 可以執行的一個點。下面的部分按順序排列以匹配生命週期:從工作階段設定通過代理迴圈到工作階段結束。每個部分描述事件何時觸發、它支援什麼匹配器、它接收的 JSON 輸入,以及如何通過輸出控制行為。1184每個事件對應於 Claude Code 生命週期中的一個點,hooks 可以在該點執行。下面的章節按照生命週期排序:從工作階段設定到代理迴圈再到工作階段結束。每個章節描述事件何時觸發、支援的匹配器、接收的 JSON 輸入,以及如何透過輸出控制行為。
963 1185
964<h3 id="sessionstart">1186<h3 id="sessionstart">
965 SessionStart1187 SessionStart
966</h3>1188</h3>
967 1189
968在 Claude Code 啟動新工作階段或恢復現有工作階段時執行。適用於載入開發上下文,例如現有問題或程式碼庫的最近變更,或設定環境變數。對於不需要指令碼的靜態上下文,請改用 [CLAUDE.md](/docs/zh-TW/memory)。1190在 Claude Code 啟動新工作階段或恢復現有工作階段時執行。適用於載入開發環境背景資訊,例如現有問題或程式碼庫的最近變更,或設定環境變數。對於不需要指令碼的靜態背景資訊,請改用 [CLAUDE.md](/docs/zh-TW/memory)。
969 1191
970SessionStart 在每個工作階段執行,因此請保持這些 hooks 快速。僅支援 `type: "command"` 和 `type: "mcp_tool"` hooks。1192SessionStart 在每個工作階段執行,因此請保持這些 hooks 快速。僅支援 `type: "command"` 和 `type: "mcp_tool"` hooks。請參閱 [MCP tool hook 欄位](#mcp-tool-hook-fields),了解 `mcp_tool` hooks 何時執行。
971 1193
972匹配器值對應於工作階段的啟動方式:1194匹配器值對應於工作階段的啟動方式:
973 1195
974| 匹配器 | 何時觸發 |1196| 匹配器 | 何時觸發 |
975| :-------- | :---------------------------------- |1197| :-------- | :------------------------------------------------------------------------------------ |
976| `startup` | 新工作階段 |1198| `startup` | 新工作階段 |
977| `resume` | `--resume`、`--continue` 或 `/resume` |1199| `resume` | `--resume`、`--continue` 或 `/resume` |
978| `clear` | `/clear` |1200| `clear` | `/clear` |
979| `compact` | 自動或手動壓縮 |1201| `compact` | 自動或手動壓縮 |
1202| `fork` | 從現有工作階段分支的新工作階段:`--fork-session` 搭配 `--resume` 或 `--continue`、`/fork` 背景複本或 `/branch` |
1203
1204在 v2.1.214 之前,分支工作階段報告來源為 `"resume"`。
1205
1206當您啟動互動式工作階段、在啟動時使用 `--continue` 或 `--resume` 恢復對話,或執行 `/clear` 時,SessionStart hooks 在背景執行。您可以立即輸入,恢復的對話會立即出現,無需等待 hooks。Claude 的第一個回應仍會等待 hooks 完成,因此它們的背景資訊會到達 Claude。
1207
1208當您在工作階段內使用 `/resume` 切換對話時,切換會等待 hooks 完成。如果您在背景 hooks 仍在執行時執行 `/clear` 或切換到另一個對話,它們返回的任何內容都不會套用到工作階段。
1209
1210相同的等待也適用於啟動,包括恢復的工作階段:您在 SessionStart hooks 仍在執行時發送的提示不會到達 Claude,直到它們完成。
1211
1212在任一等待期間,按 `Esc` 將提示返回到輸入中而不發送。Hooks 會繼續執行。
980 1213
981<h4 id="sessionstart-input">1214<h4 id="sessionstart-input">
982 SessionStart 輸入1215 SessionStart 輸入
983</h4>1216</h4>
984 1217
985除了 [通用輸入欄位](#common-input-fields) 外,SessionStart hooks 還接收 `source` 和可選的 `model`、`agent_type` 和 `session_title`:1218除了 [常見輸入欄位](#common-input-fields) 外,SessionStart hooks 還會接收 `source` 和可選的 `model`、`agent_type` 和 `session_title`:
986 1219
987| 欄位 | 描述 |1220| 欄位 | 描述 |
988| :-------------- | :------------------------------------------------------------------------------------------------------- |1221| :-------------- | :---------------------------------------------------------------------------------------------------------------- |
989| `source` | 工作階段如何啟動:新工作階段為 `"startup"`,恢復的工作階段為 `"resume"`,`/clear` 後為 `"clear"`,或壓縮後為 `"compact"` |1222| `source` | 工作階段如何啟動:新工作階段為 `"startup"`、恢復的工作階段為 `"resume"`、`/clear` 後為 `"clear"`、壓縮後為 `"compact"`,或從現有工作階段分支的新工作階段為 `"fork"` |
990| `model` | 活動模型識別碼。它可以被省略,例如在 `/clear` 後或當工作階段通過對話恢復被恢復時,因此在讀取它之前檢查欄位 |1223| `model` | 作用中的模型識別碼。例如在 `/clear` 後或透過對話恢復恢復工作階段時可能會省略,因此在讀取前檢查欄位 |
991| `agent_type` | 代理名稱,當您使用 `claude --agent <name>` 啟動 Claude Code 時出現 |1224| `agent_type` | 代理名稱,當您使用 `claude --agent <name>` 啟動 Claude Code 時出現 |
992| `session_title` | 目前工作階段標題(如果已設定),例如通過 `--name` 或 `/rename`。發出 `sessionTitle` 的 hook 可以先檢查 `session_title` 以避免覆寫使用者明確設定的標題 |1225| `session_title` | 目前工作階段標題(如果已設定),例如透過 `--name` 或 `/rename`。發出 `sessionTitle` 的 hook 可以先檢查 `session_title` 以避免覆寫使用者明確設定的標題 |
1226
1227當 `source` 為 `"resume"` 或 `"fork"` 且文字記錄包含至少一個來自 Claude 的回應時,SessionStart hooks 也會接收下面的四個欄位。您的 hook 可以使用它們在第一個請求之前報告恢復陳舊對話的成本,例如在 [`systemMessage`](#json-output) 中。這些欄位需要 Claude Code v2.1.251 或更新版本。
1228
1229| 欄位 | 描述 |
1230| :---------------------------- | :----------------------------------------------------------------------------------------------- |
1231| `seconds_since_last_response` | 自恢復文字記錄中最後一個回應以來的掛鐘秒數 |
1232| `context_tokens` | 恢復工作階段的第一個請求作為其提示重新發送的令牌 |
1233| `prompt_cache_likely_expired` | 當最後一個回應早於工作階段的 [prompt cache 生命週期](/docs/zh-TW/prompt-caching#cache-lifetime) 或更新的壓縮替換了快取的對話時為 `true` |
1234| `estimated_cache_write_usd` | 將 `context_tokens` 寫入工作階段模型上的 prompt cache 的估計成本(美元),不包括回應 |
1235
1236此範例顯示在最後一個回應後 90 分鐘恢復的工作階段的輸入:
993 1237
994```json theme={null}1238```json theme={null}
995{1239{
997 "transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",1241 "transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",
998 "cwd": "/Users/...",1242 "cwd": "/Users/...",
999 "hook_event_name": "SessionStart",1243 "hook_event_name": "SessionStart",
1000 "source": "startup",1244 "source": "resume",
1001 "model": "claude-sonnet-5"1245 "model": "claude-opus-5",
1246 "seconds_since_last_response": 5400,
1247 "context_tokens": 182340,
1248 "prompt_cache_likely_expired": true,
1249 "estimated_cache_write_usd": 1.1396
1002}1250}
1003```1251```
1004 1252
1005<h4 id="sessionstart-decision-control">1253<h4 id="sessionstart-decision-control">
1006 SessionStart 決定控制1254 SessionStart 決策控制
1007</h4>1255</h4>
1008 1256
1009您的 hook 指令碼列印到 stdout 的任何文字都被新增為 Claude 的上下文。除了所有 hooks 可用的 [JSON 輸出欄位](#json-output) 外,您還可以返回這些事件特定欄位:1257Claude Code 將其 [視為純文字](#exit-code-0) 的 stdout 新增到 Claude 的背景資訊。除了所有 hooks 可用的 [JSON 輸出欄位](#json-output) 外,您還可以返回這些事件特定欄位:
1010 1258
1011| 欄位 | 描述 |1259| 欄位 | 描述 |
1012| :------------------- | :------------------------------------------------------------------------------------------------------------------------------------------- |1260| :------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------- |
1013| `additionalContext` | 新增到 Claude 上下文開始處的字串,在第一個提示之前。請參閱 [為 Claude 新增上下文](#add-context-for-claude) 以了解文字如何傳遞以及要放入其中的內容 |1261| `additionalContext` | 在對話開始時、第一個提示之前新增到 Claude 背景資訊的字串。請參閱 [為 Claude 新增背景資訊](#add-context-for-claude),了解文字如何傳遞以及要放入其中的內容 |
1014| `initialUserMessage` | 用作工作階段第一個使用者訊息的字串。適用於 [非互動模式](/docs/zh-TW/headless)(`-p`),其中即使未提供提示,它也成為第一個轉向。如果提供了提示,它作為下一個轉向跟隨。與 `additionalContext` 不同,後者附加到現有轉向,這會建立轉向 |1262| `initialUserMessage` | 用作工作階段第一個使用者訊息的字串。適用於 [非互動模式](/docs/zh-TW/headless),搭配 `-p` 旗標,即使未提供提示,它也會成為第一個回合。如果提供了提示,它會作為下一個回合跟隨。與附加到現有回合的 `additionalContext` 不同,這會建立回合 |
1015| `sessionTitle` | 設定工作階段標題,與 `/rename` 的效果相同。使用此項根據啟動資料夾、git 分支或 worktree 名稱自動命名工作階段。僅在 `source` 為 `"startup"` 或 `"resume"` 時適用;在 `"clear"` 和 `"compact"` 上被忽略 |1263| `sessionTitle` | 設定工作階段標題,效果與 `/rename` 相同。用於根據啟動資料夾、git 分支或 worktree 名稱自動命名工作階段。當 `source` 為 `"startup"`、`"resume"` 或 `"fork"` 時適用;在 `"clear"` 和 `"compact"` 上忽略 |
1016| `watchPaths` | 絕對路徑的陣列,用於在此工作階段期間監視 [FileChanged](#filechanged) 事件 |1264| `watchPaths` | 絕對路徑陣列,用於在此工作階段期間監視 [FileChanged](#filechanged) 事件 |
1017| `reloadSkills` | 布林值。當為 `true` 時,Claude Code 在 SessionStart hooks 完成後重新掃描 [skill](/docs/zh-TW/skills) 和命令目錄,因此 hook 安裝的 skills 在同一工作階段中可用,從第一個提示開始 |1265| `reloadSkills` | 布林值。當為 `true` 時,Claude Code 在 SessionStart hooks 完成後重新掃描 [skill](/docs/zh-TW/skills) 和命令目錄,因此 hook 安裝的 skills 在同一工作階段中可用,從第一個提示開始 |
1018 1266
1019```json theme={null}1267```json theme={null}
1026}1274}
1027```1275```
1028 1276
1029由於純 stdout 已經到達 Claude 用於此事件,只載入上下文的 hook 可以直接列印到 stdout 而無需建立 JSON。當您需要將上下文與其他欄位(例如 `suppressOutput` 或 `sessionTitle`)結合時,請使用 JSON 形式。1277由於此事件的純文字 stdout 已到達 Claude,只載入背景資訊的 hook 可以直接列印到 stdout,而無需建立 JSON。當您需要將背景資訊與其他欄位(例如 `sessionTitle`)結合時,請使用 JSON 形式。
1030 1278
1031當 SessionStart hook 安裝或更新 skills 時,使用 `reloadSkills`。Skill 發現通常在 SessionStart hooks 完成之前執行,因此 hook 寫入 `~/.claude/skills/` 或 `.claude/skills/` 的檔案否則只會在下一個工作階段中出現。此範例同步共享 skills 儲存庫並請求重新掃描:1279當 SessionStart hook 安裝或更新 skills 時使用 `reloadSkills`。Skill 探索通常在 SessionStart hooks 完成之前執行,因此 hook 寫入 `~/.claude/skills/` 或 `.claude/skills/` 的檔案否則只會在下一個工作階段中出現。此範例同步共享 skills 儲存庫並請求重新掃描:
1032 1280
1033```bash theme={null}1281```bash theme={null}
1034#!/bin/bash1282#!/bin/bash
1039echo '{"hookSpecificOutput": {"hookEventName": "SessionStart", "reloadSkills": true}}'1287echo '{"hookSpecificOutput": {"hookEventName": "SessionStart", "reloadSkills": true}}'
1040```1288```
1041 1289
1290儲存庫 URL 是佔位符;將其替換為您自己的 skills 儲存庫。使用佔位符時,複製會失敗並列印 `fatal:` 訊息到 stderr。來自以 0 退出的 SessionStart hook 的 stderr 僅供參考,因此 `reloadSkills` 請求仍然適用。
1291
1042<h4 id="persist-environment-variables">1292<h4 id="persist-environment-variables">
1043 持久化環境變數1293 保留環境變數
1044</h4>1294</h4>
1045 1295
1046SessionStart hooks 可以存取 `CLAUDE_ENV_FILE` 環境變數,該變數提供一個檔案路徑,您可以在其中為後續 Bash 命令持久化環境變數。1296SessionStart hooks 可以存取 `CLAUDE_ENV_FILE` 環境變數,該變數提供一個檔案路徑,您可以在其中保留後續 Bash 命令的環境變數。
1047 1297
1048要設定個別環境變數,請將 `export` 陳述式寫入 `CLAUDE_ENV_FILE`。使用追加(`>>`)來保留由其他 hooks 設定的變數:1298若要設定個別環境變數,請將 `export` 陳述式寫入 `CLAUDE_ENV_FILE`。使用附加 (`>>`) 以保留由其他 hooks 設定的變數:
1049 1299
1050```bash theme={null}1300```bash theme={null}
1051#!/bin/bash1301#!/bin/bash
1059exit 01309exit 0
1060```1310```
1061 1311
1062要捕獲設定命令中的所有環境變更,請比較之前和之後的匯出變數:1312若要捕獲設定命令中的所有環境變更,請比較之前和之後的匯出變數:
1063 1313
1064```bash theme={null}1314```bash theme={null}
1065#!/bin/bash1315#!/bin/bash
1066 1316
1067ENV_BEFORE=$(export -p | sort)1317ENV_BEFORE=$(export -p | sort)
1068 1318
1069# 執行修改環境的設定命令1319# Run your setup commands that modify the environment
1070source ~/.nvm/nvm.sh1320source ~/.nvm/nvm.sh
1071nvm use 201321nvm use 20
1072 1322
1078exit 01328exit 0
1079```1329```
1080 1330
1081寫入此檔案的任何變數都將在工作階段期間 Claude Code 執行的所有後續 Bash 命令中可用。
1082
1083<Note>1331<Note>
1084 `CLAUDE_ENV_FILE` 可用於 SessionStart、[Setup](#setup)、[CwdChanged](#cwdchanged) 和 [FileChanged](#filechanged) hooks。其他 hook 類型無法存取此變數。1332 `CLAUDE_ENV_FILE` 適用於 SessionStart、[Setup](#setup)、[CwdChanged](#cwdchanged) 和 [FileChanged](#filechanged) hooks。其他 hook 類型無法存取此變數。
1085</Note>1333</Note>
1086 1334
1087<h3 id="setup">1335<h3 id="setup">
1088 Setup1336 Setup
1089</h3>1337</h3>
1090 1338
1091僅當您使用 `--init-only` 啟動 Claude Code,或在非互動模式(`-p`)中使用 `--init` 或 `--maintenance` 時觸發。它在正常啟動時不觸發。使用它進行一次性依賴項安裝或您從 CI 或指令碼明確觸發的計劃清理,與正常工作階段啟動分開。對於每個工作階段的初始化,請改用 [SessionStart](#sessionstart)。1339僅當您使用 `--init-only` 啟動 Claude Code,或在 [非互動模式](/docs/zh-TW/headless) 中使用 `--init` 或 `--maintenance` 搭配 `-p` 旗標時觸發。在正常啟動時不觸發。用於一次性相依性安裝或您從 CI 或指令碼明確觸發的排程清理,與正常工作階段啟動分開。對於每個工作階段的初始化,請改用 [SessionStart](#sessionstart)。
1092 1340
1093匹配器值對應於觸發 hook 的 CLI 標誌:1341匹配器值對應於觸發 hook 的 CLI 旗標:
1094 1342
1095| 匹配器 | 何時觸發 |1343| 匹配器 | 何時觸發 |
1096| :------------ | :---------------------------------------- |1344| :------------ | :---------------------------------------- |
1097| `init` | `claude --init-only` 或 `claude -p --init` |1345| `init` | `claude --init-only` 或 `claude -p --init` |
1098| `maintenance` | `claude -p --maintenance` |1346| `maintenance` | `claude -p --maintenance` |
1099 1347
1100`--init-only` 執行 Setup hooks 和 SessionStart hooks(帶有 `startup` 匹配器),然後退出而不啟動對話。`--init` 和 `--maintenance` 僅在與 `-p` 結合時觸發 Setup hooks;在互動式工作階段中,這兩個標誌目前不觸發 Setup hooks。1348當您執行 `claude --init-only` 時,Claude Code 執行 Setup hooks 和 `startup` 匹配器的 `SessionStart` hooks,然後退出而不啟動對話。
1101 1349
1102因為 Setup 不在每次啟動時觸發,需要安裝依賴項的外掛程式無法僅依賴 Setup。實際的模式是在首次使用時檢查依賴項,如果缺失則安裝,例如測試 `${CLAUDE_PLUGIN_DATA}/node_modules` 的 hook 或 skill,如果不存在則執行 `npm install`。請參閱 [持久資料目錄](/docs/zh-TW/plugins-reference#persistent-data-directory) 以了解在何處儲存已安裝的依賴項。1350當您使用 `-p` 啟動或繼續對話時,您還需要提供提示,作為引數或透過 stdin 管道傳輸。當 `SessionStart` hook 提供 [`initialUserMessage`](#sessionstart-decision-control) 或當您使用 [延遲工具呼叫](#defer-a-tool-call-for-later) 恢復工作階段時,您可以跳過提示。
1351
1352成功時,`--init-only` 不會列印任何內容到終端。若要確認 hooks 已執行,請使用 `claude --debug-file <path> --init-only` 啟動,將 `<path>` 替換為日誌檔案位置,並檢查日誌中的 Setup 和 SessionStart hook 項目。
1353
1354由於 Setup 不會在每次啟動時觸發,需要安裝相依性的外掛無法僅依賴 Setup。實用的模式是在首次使用時檢查相依性,如果缺少則安裝,例如測試 `${CLAUDE_PLUGIN_DATA}/node_modules` 的 hook 或 skill,如果不存在則執行 `npm install`。請參閱 [持久資料目錄](/docs/zh-TW/plugins-reference#persistent-data-directory),了解儲存已安裝相依性的位置。如果您透過市場發佈外掛,您可能不需要此模式:Claude Code [在快取外掛時自動安裝符合條件的 Node.js 套件相依性](/docs/zh-TW/plugins-reference#node-js-package-dependencies)。
1103 1355
1104<h4 id="setup-input">1356<h4 id="setup-input">
1105 Setup 輸入1357 Setup 輸入
1106</h4>1358</h4>
1107 1359
1108除了 [通用輸入欄位](#common-input-fields) 外,Setup hooks 還接收設定為 `"init"` 或 `"maintenance"` 的 `trigger` 欄位:1360除了 [常見輸入欄位](#common-input-fields) 外,Setup hooks 還會接收設定為 `"init"` 或 `"maintenance"` 的 `trigger` 欄位:
1109 1361
1110```json theme={null}1362```json theme={null}
1111{1363{
1118```1370```
1119 1371
1120<h4 id="setup-decision-control">1372<h4 id="setup-decision-control">
1121 Setup 決定控制1373 Setup 決策控制
1122</h4>1374</h4>
1123 1375
1124Setup hooks 無法阻止。任何非零退出代碼(包括 2)都會向使用者顯示 stderr 作為 `<hook name> hook error` 通知,執行繼續。在 [非互動模式](/docs/zh-TW/headless) 中,hook 輸出僅在您使用 `--verbose` 啟動時出現。1376Setup hooks 無法阻止;執行在任何退出代碼上繼續。在每個退出代碼上,Claude Code 捨棄 Setup hook 的 [JSON 輸出欄位](#json-output),例如 `systemMessage`、`continue` 和 `hookSpecificOutput.additionalContext`。使用 `-p` 時,Setup hook 的 stdout、stderr 和退出代碼僅在您使用 `--output-format stream-json --verbose` 啟動時作為 [`hook_response` 事件](/docs/zh-TW/headless#read-session-metadata) 出現在執行的輸出中。
1125
1126要將資訊傳遞到 Claude 的上下文中,請在 JSON 輸出中返回 `additionalContext`;純 stdout 僅寫入偵錯日誌。除了所有 hooks 可用的 [JSON 輸出欄位](#json-output) 外,您還可以返回這些事件特定欄位:
1127
1128| 欄位 | 描述 |
1129| :------------------ | :------------------------------- |
1130| `additionalContext` | 新增到 Claude 上下文的字串。多個 hooks 的值被連接 |
1131
1132```json theme={null}
1133{
1134 "hookSpecificOutput": {
1135 "hookEventName": "Setup",
1136 "additionalContext": "Dependencies installed: node_modules, .venv"
1137 }
1138}
1139```
1140 1377
1141Setup hooks 可以存取 `CLAUDE_ENV_FILE`。寫入該檔案的變數會持久化到工作階段的後續 Bash 命令中,就像在 [SessionStart hooks](#persist-environment-variables) 中一樣。僅支援 `type: "command"` 和 `type: "mcp_tool"` hooks。1378Setup hooks 可以存取 `CLAUDE_ENV_FILE`。寫入該檔案的變數會保留到工作階段的後續 Bash 命令中,就像在 [SessionStart hooks](#persist-environment-variables) 中一樣。只有 `type: "command"` hooks 在 `Setup` 上執行。`type: "mcp_tool"` hook 在 `Setup` 上始終被跳過,如 [MCP tool hook 欄位](#mcp-tool-hook-fields) 下所述。
1142 1379
1143<h3 id="instructionsloaded">1380<h3 id="instructionsloaded">
1144 InstructionsLoaded1381 InstructionsLoaded
1145</h3>1382</h3>
1146 1383
1147當 `CLAUDE.md` 或 `.claude/rules/*.md` 檔案被載入到上下文中時觸發。此事件在工作階段開始時針對急切載入的檔案觸發,稍後當檔案被延遲載入時再次觸發,例如當 Claude 存取包含嵌套 `CLAUDE.md` 的子目錄時,或當具有 `paths:` frontmatter 的條件規則匹配時。該 hook 不支援阻止或決定控制。它以非同步方式執行以用於可觀測性目的。1384在載入 `CLAUDE.md` 或 `.claude/rules/*.md` 檔案到背景資訊時觸發。此事件在工作階段啟動時對於急切載入的檔案觸發,稍後在檔案被延遲載入時再次觸發,例如當 Claude 存取包含巢狀 `CLAUDE.md` 的子目錄或當具有 `paths:` frontmatter 的條件規則匹配時。Hook 不支援阻止或決策控制。它以非同步方式執行以用於可觀測性目的。
1385
1386此事件在 Claude [直接透過 **Project instructions** 設定讀取 `AGENTS.md`](/docs/zh-TW/memory#agents-md) 時不觸發。當 `CLAUDE.md` 匯入您的 `AGENTS.md` 時它會觸發,其中 `load_reason` 設定為 `include`(如同任何其他匯入的檔案),以及當 `CLAUDE.md` 是它的符號連結時,作為正常 `CLAUDE.md` 載入。
1148 1387
1149匹配器針對 `load_reason` 執行。例如,使用 `"matcher": "session_start"` 僅針對在工作階段開始時載入的檔案觸發,或使用 `"matcher": "path_glob_match|nested_traversal"` 僅針對延遲載入觸發。1388匹配器針對 `load_reason` 執行。例如,使用 `"matcher": "session_start"` 僅對工作階段啟動時載入的檔案觸發,或使用 `"matcher": "path_glob_match|nested_traversal"` 僅對延遲載入觸發。
1150 1389
1151<h4 id="instructionsloaded-input">1390<h4 id="instructionsloaded-input">
1152 InstructionsLoaded 輸入1391 InstructionsLoaded 輸入
1153</h4>1392</h4>
1154 1393
1155除了 [通用輸入欄位](#common-input-fields) 外,InstructionsLoaded hooks 還接收這些欄位:1394除了 [常見輸入欄位](#common-input-fields) 外,InstructionsLoaded hooks 還會接收這些欄位:
1156 1395
1157| 欄位 | 描述 |1396| 欄位 | 描述 |
1158| :------------------ | :--------------------------------------------------------------------------------------------------------------------------- |1397| :------------------ | :-------------------------------------------------------------------------------------------------------------------------- |
1159| `file_path` | 被載入的指令檔案的絕對路徑 |1398| `file_path` | 已載入的指令檔案的絕對路徑 |
1160| `memory_type` | 檔案的範圍:`"User"`、`"Project"`、`"Local"` 或 `"Managed"` |1399| `memory_type` | 檔案的範圍:`"User"`、`"Project"`、`"Local"` 或 `"Managed"` |
1161| `load_reason` | 檔案被載入的原因:`"session_start"`、`"nested_traversal"`、`"path_glob_match"`、`"include"` 或 `"compact"`。`"compact"` 值在壓縮事件後重新載入指令檔案時觸發 |1400| `load_reason` | 檔案載入的原因:`"session_start"`、`"nested_traversal"`、`"path_glob_match"`、`"include"` 或 `"compact"`。`"compact"` 值在壓縮事件後重新載入指令檔案時觸發 |
1162| `globs` | 檔案 `paths:` frontmatter 中的路徑 glob 模式(如果有)。僅針對 `path_glob_match` 載入出現 |1401| `globs` | 檔案 `paths:` frontmatter 中的路徑 glob 模式(如果有)。僅對 `path_glob_match` 載入出現 |
1163| `trigger_file_path` | 觸發此載入的檔案的路徑,用於延遲載入 |1402| `trigger_file_path` | 觸發此載入的檔案的路徑,用於延遲載入 |
1164| `parent_file_path` | 包含此檔案的父指令檔案的路徑,用於 `include` 載入 |1403| `parent_file_path` | 包含此檔案的父指令檔案的路徑,用於 `include` 載入 |
1165 1404
1176```1415```
1177 1416
1178<h4 id="instructionsloaded-decision-control">1417<h4 id="instructionsloaded-decision-control">
1179 InstructionsLoaded 決定控制1418 InstructionsLoaded 決策控制
1180</h4>1419</h4>
1181 1420
1182InstructionsLoaded hooks 沒有決定控制。它們無法阻止或修改指令載入。使用此事件進行稽核記錄、合規性追蹤或可觀測性。1421InstructionsLoaded hooks 沒有決策控制。它們無法阻止或修改指令載入。Claude Code 捨棄它們的 [JSON 輸出欄位](#json-output),例如 `systemMessage` 和 `continue`。使用此事件進行稽核日誌、合規性追蹤或可觀測性。
1183 1422
1184<h3 id="userpromptsubmit">1423<h3 id="userpromptsubmit">
1185 UserPromptSubmit1424 UserPromptSubmit
1186</h3>1425</h3>
1187 1426
1188在使用者提交提示時執行,在 Claude 處理之前。這允許您根據提示/對話新增額外上下文、驗證提示或阻止某些類型的提示。1427在使用者提交提示時執行,在 Claude 處理之前。這允許您根據提示/對話新增額外背景資訊、驗證提示或阻止某些類型的提示。
1189 1428
1190`UserPromptSubmit` hooks 對於 `command`、`http` 和 `mcp_tool` 類型的預設逾時為 30 秒,比其他事件上這些類型的 600 秒預設值更短。因為此 hook 在每個提示之前執行並阻止模型處理直到完成,卡住的 hook 會停滯工作階段。如果您的 hook 需要更多時間,請在 hook 項目中設定 `timeout` 欄位。1429`UserPromptSubmit` hooks 對 `command`、`http` 和 `mcp_tool` 類型的預設逾時為 30 秒,比大多數其他事件上這些類型的 600 秒預設值更短。因為此 hook 在每個提示之前執行並阻止模型處理直到完成,卡住的 hook 會停滯工作階段。如果您的 hook 需要更多時間,請在 hook 項目中設定 `timeout` 欄位。
1191 1430
1192達到逾時的 `UserPromptSubmit` hook 被取消,其輸出(包括任何 `additionalContext`)被丟棄。提示仍然到達 Claude,但沒有該上下文。從 v2.1.196 開始,成績單顯示一個通知,命名 hook、觸發的逾時以及輸出被丟棄。較早的版本取消 hook 而不顯示通知。1431除了使用 [`async: true`](#run-hooks-in-the-background) 執行的命令 hook 外,達到其逾時的 `UserPromptSubmit` 命令、HTTP 或 MCP tool hook 會被取消,其輸出(包括任何 `additionalContext`)會被捨棄。提示仍會到達 Claude 而不會有該背景資訊。文字記錄顯示一個通知,命名 hook、觸發的逾時以及輸出已被捨棄。
1193 1432
1194[Agent SDK callback hook](/docs/zh-TW/agent-sdk/hooks) 在 `UserPromptSubmit` 上達到逾時會阻止提示,並顯示命名 hook 和逾時的訊息,因為該處的 callback 可能充當必須不失敗開放的原則閘道。工作階段繼續。在 v2.1.208 之前,callback 在該事件上的逾時以執行錯誤結束轉向。1433在 `UserPromptSubmit` 上達到其逾時的 [Agent SDK 回呼 hook](/docs/zh-TW/agent-sdk/hooks) 會用命名 hook 和逾時的訊息阻止提示,因為該處的回呼可能充當必須不失敗開放的原則閘道。工作階段繼續。在 v2.1.208 之前,該事件上的回呼逾時以執行錯誤結束回合。
1195 1434
1196<h4 id="userpromptsubmit-input">1435<h4 id="userpromptsubmit-input">
1197 UserPromptSubmit 輸入1436 UserPromptSubmit 輸入
1198</h4>1437</h4>
1199 1438
1200除了 [通用輸入欄位](#common-input-fields) 外,UserPromptSubmit hooks 還接收包含使用者提交的文字的 `prompt` 欄位。1439除了 [常見輸入欄位](#common-input-fields) 外,UserPromptSubmit hooks 還會接收包含使用者提交的文字的 `prompt` 欄位。
1201 1440
1202```json theme={null}1441```json theme={null}
1203{1442{
1211```1450```
1212 1451
1213<h4 id="userpromptsubmit-decision-control">1452<h4 id="userpromptsubmit-decision-control">
1214 UserPromptSubmit 決定控制1453 UserPromptSubmit 決策控制
1215</h4>1454</h4>
1216 1455
1217`UserPromptSubmit` hooks 可以控制使用者提示是否被處理並新增上下文。所有 [JSON 輸出欄位](#json-output) 都可用。1456`UserPromptSubmit` hooks 可以控制是否處理使用者提示並新增背景資訊。所有 [JSON 輸出欄位](#json-output) 都可用。
1218 1457
1219有兩種方式在退出代碼 0 時向對話新增上下文:1458有兩種方式可以在退出代碼 0 上新增背景資訊到對話:
1220 1459
1221* **純文字 stdout**:寫入 stdout 的任何非 JSON 文字都被新增為上下文1460* **純文字 stdout**:Claude Code 將其 [視為純文字](#exit-code-0) 的 stdout 新增到 Claude 的背景資訊
1222* **帶有 `additionalContext` 的 JSON**:使用下面的 JSON 格式以獲得更多控制。`additionalContext` 欄位被新增為上下文1461* **JSON 搭配 `additionalContext`**:使用下面的 JSON 格式以獲得更多控制。`additionalContext` 欄位作為背景資訊新增
1223 1462
1224純 stdout 在成績單中顯示為 hook 輸出。`additionalContext` 值被注入為系統提醒,Claude 讀取時不會有可見的成績單項目。1463兩個通道都不會產生可見的文字記錄項目。純文字和 `additionalContext` 值各自作為以 hook 名稱開頭的系統提醒注入;Claude 讀取兩者。若要確認傳遞,請檢查 [偵錯日誌](#debug-hooks)。
1225 1464
1226要阻止提示,請返回一個 JSON 物件,其中 `decision` 設定為 `"block"`:1465若要阻止提示,請返回一個 JSON 物件,其中 `decision` 設定為 `"block"`:
1227 1466
1228| 欄位 | 描述 |1467| 欄位 | 描述 |
1229| :----------------------- | :----------------------------------------------------------------------- |1468| :----------------------- | :------------------------------------------------------------------------ |
1230| `decision` | `"block"` 防止提示被處理並從上下文中清除它。省略以允許提示進行 |1469| `decision` | `"block"` 防止提示被處理並從背景資訊中清除。省略以允許提示繼續 |
1231| `reason` | 當 `decision` 為 `"block"` 時向使用者顯示。不新增到上下文 |1470| `reason` | 當 `decision` 為 `"block"` 時顯示給使用者。不新增到背景資訊 |
1232| `additionalContext` | 新增到 Claude 上下文的字串,與提交的提示一起。請參閱 [為 Claude 新增上下文](#add-context-for-claude) |1471| `additionalContext` | 與提交的提示一起新增到 Claude 背景資訊的字串。請參閱 [為 Claude 新增背景資訊](#add-context-for-claude) |
1233| `sessionTitle` | 設定工作階段標題。使用此項根據提示內容自動命名工作階段 |1472| `sessionTitle` | 設定工作階段標題。用於根據提示內容自動命名工作階段 |
1234| `suppressOriginalPrompt` | 如果在 `decision` 為 `"block"` 時為 `true`,則從向使用者顯示的阻止訊息中省略原始提示文字 |1473| `suppressOriginalPrompt` | 當 `decision` 為 `"block"` 時,如果為 `true`,則從顯示給使用者的阻止訊息中省略原始提示文字 |
1474
1475透過退出 2 阻止的 hook 路由方式與 `reason` 相同:阻止訊息向使用者顯示 stderr 文字,且不新增到背景資訊。
1235 1476
1236```json theme={null}1477```json theme={null}
1237{1478{
1249 UserPromptExpansion1490 UserPromptExpansion
1250</h3>1491</h3>
1251 1492
1252當使用者輸入的斜杠命令在到達 Claude 之前展開為提示時執行。使用此項來阻止特定命令的直接呼叫、為特定 skill 注入上下文,或記錄使用者呼叫哪些命令。例如,匹配 `deploy` 的 hook 可以在不存在批准檔案時阻止 `/deploy`,或匹配審查 skill 的 hook 可以將團隊的審查檢查清單附加為 `additionalContext`。1493在使用者輸入的命令擴展為到達 Claude 之前的提示時執行。使用此來阻止特定命令的直接呼叫、為特定 skill 注入背景資訊,或記錄使用者呼叫的命令。例如,匹配 `deploy` 的 hook 可以阻止 `/deploy`,除非存在核准檔案,或匹配審查 skill 的 hook 可以將團隊的審查檢查清單附加為 `additionalContext`。
1253 1494
1254此事件涵蓋 `PreToolUse` 不涵蓋的路徑:匹配 `Skill` 工具的 `PreToolUse` hook 僅在 Claude 呼叫工具時觸發,但直接輸入 `/skillname` 會繞過 `PreToolUse`。`UserPromptExpansion` 在該直接路徑上觸發。1495此事件涵蓋 `PreToolUse` 不涵蓋的路徑:匹配 `Skill` 工具的 `PreToolUse` hook 僅在 Claude 呼叫工具時觸發,但直接輸入 `/skillname` 會繞過 `PreToolUse`。`UserPromptExpansion` 在該直接路徑上觸發。
1255 1496
1256匹配 `command_name`。留空匹配器以針對每個提示類型斜杠命令觸發。1497在 `command_name` 上匹配。將匹配器留空以對每個提示類型命令觸發。
1257 1498
1258<h4 id="userpromptexpansion-input">1499<h4 id="userpromptexpansion-input">
1259 UserPromptExpansion 輸入1500 UserPromptExpansion 輸入
1260</h4>1501</h4>
1261 1502
1262除了 [通用輸入欄位](#common-input-fields) 外,UserPromptExpansion hooks 還接收 `expansion_type`、`command_name`、`command_args`、`command_source` 和原始 `prompt` 字串。`expansion_type` 欄位對於 skill 和自訂命令為 `slash_command`,或對於 MCP 伺服器提示為 `mcp_prompt`。1503除了 [常見輸入欄位](#common-input-fields) 外,UserPromptExpansion hooks 還會接收 `expansion_type`、`command_name`、`command_args`、`command_source` 和原始 `prompt` 字串。`expansion_type` 欄位對於 skill 和自訂命令為 `slash_command`,或對於 MCP 伺服器提示為 `mcp_prompt`。
1263 1504
1264```json theme={null}1505```json theme={null}
1265{1506{
1277```1518```
1278 1519
1279<h4 id="userpromptexpansion-decision-control">1520<h4 id="userpromptexpansion-decision-control">
1280 UserPromptExpansion 決定控制1521 UserPromptExpansion 決策控制
1281</h4>1522</h4>
1282 1523
1283`UserPromptExpansion` hooks 可以阻止展開或新增上下文。所有 [JSON 輸出欄位](#json-output) 都可用。1524`UserPromptExpansion` hooks 可以阻止擴展或新增背景資訊。所有 [JSON 輸出欄位](#json-output) 都可用。
1284 1525
1285| 欄位 | 描述 |1526| 欄位 | 描述 |
1286| :------------------ | :----------------------------------------------------------------------- |1527| :------------------ | :------------------------------------------------------------------------ |
1287| `decision` | `"block"` 防止斜杠命令展開。省略以允許它進行 |1528| `decision` | `"block"` 防止命令擴展。省略以允許它繼續 |
1288| `reason` | 當 `decision` 為 `"block"` 時向使用者顯示 |1529| `reason` | 當 `decision` 為 `"block"` 時顯示給使用者 |
1289| `additionalContext` | 新增到 Claude 上下文的字串,與展開的提示一起。請參閱 [為 Claude 新增上下文](#add-context-for-claude) |1530| `additionalContext` | 與擴展的提示一起新增到 Claude 背景資訊的字串。請參閱 [為 Claude 新增背景資訊](#add-context-for-claude) |
1531
1532透過退出 2 阻止的 hook 路由方式與 `reason` 相同:阻止訊息向使用者顯示 stderr 文字。
1290 1533
1291```json theme={null}1534```json theme={null}
1292{1535{
1303 MessageDisplay1546 MessageDisplay
1304</h3>1547</h3>
1305 1548
1306在助手訊息流向螢幕時執行。Claude Code 分批顯示訊息:每次一批新完成的行準備好呈現時,hook 執行一次,這些行,Claude Code 在其位置呈現 hook 的替換文字。長訊息產生多個呼叫;短訊息可能只產生一個。1549在助手訊息流向螢幕時執行。Claude Code 分批顯示訊息:每次一批新完成的行準備好呈現時,hook 執行一次,其中包含這些行,Claude Code 呈現 hook 的替換文字代替它們。長訊息會產生多個呼叫;短訊息可能只產生一個。
1307 1550
1308使用 MessageDisplay 來:1551使用 MessageDisplay 來:
1309 1552
1310* 去除 markdown 以獲得最小顯示1553* 為最小顯示去除 markdown
1311* 轉換 Agent SDK 應用程式向其使用者顯示的文字1554* 轉換 Agent SDK 應用程式向其使用者顯示的文字
1312* 從 Claude 的回應中編輯 API 金鑰或內部主機名稱1555* 從 Claude 的回應中編輯 API 金鑰或內部主機名稱
1313 1556
1314Claude Code 保持每批直到您的 hook 返回,因此請保持 hook 快速。如果 hook 失敗或逾時,Claude Code 顯示原始文字。此事件的預設逾時為 10 秒;如果您的 hook 需要更多時間,請在 hook 項目中設定 `timeout` 欄位。1557Claude Code 保留每個批次直到您的 hook 返回,因此請保持 hook 快速。如果 hook 失敗或逾時,Claude Code 顯示原始文字。此事件的預設逾時為 10 秒;如果您的 hook 需要更多時間,請在 hook 項目中設定 `timeout` 欄位。
1315 1558
1316MessageDisplay 僅用於顯示:替換文字僅改變螢幕上呈現的內容。成績單和 Claude 看到的內容保持原始文字,因此 Claude 永遠看不到替換,詳細模式顯示原始文字。Hook 接收助手訊息文字,因此工具結果和您輸入的文字呈現不變。1559MessageDisplay 僅用於顯示:替換文字僅更改螢幕上呈現的內容。文字記錄和 Claude 看到的內容保持原始文字,因此 Claude 永遠看不到替換,詳細模式顯示原始文字。Hook 僅接收助手訊息文字,因此工具結果和您輸入的文字呈現不變。
1317 1560
1318MessageDisplay 不支援匹配器,針對每個流向文字的助手訊息觸發;沒有文字的訊息(例如僅工具呼叫回應)不觸發它。1561MessageDisplay 不支援匹配器,對每個流向文字的助手訊息觸發;沒有文字的訊息(例如僅工具呼叫回應)不觸發它。
1319 1562
1320在非互動執行中,包括 Agent SDK 查詢和 `claude -p`,MessageDisplay 每個助手訊息執行一次,而不是每批行執行一次。單一呼叫在訊息完成後到達,並攜帶完整訊息文字:`index` 為 `0`,`final` 為 `true`,`delta` 保存整個訊息。為每個訊息收集 `delta` 文字的 hook 在兩種模式中接收相同的總文字。1563在非互動執行中,包括 Agent SDK 查詢和 `claude -p`,MessageDisplay 每個助手訊息執行一次而不是每批行執行一次。單個呼叫在訊息完成後到達並攜帶完整訊息文字:`index` 為 `0`、`final` 為 `true`,`delta` 保留整個訊息。為每個訊息收集 `delta` 文字的 hook 在兩種模式中接收相同的總文字。
1321 1564
1322<h4 id="messagedisplay-input">1565<h4 id="messagedisplay-input">
1323 MessageDisplay 輸入1566 MessageDisplay 輸入
1324</h4>1567</h4>
1325 1568
1326除了 [通用輸入欄位](#common-input-fields) 外,MessageDisplay hooks 還接收轉向和訊息的識別碼、此呼叫在訊息中的位置,以及 `delta` 中的新文字。批次邊界取決於文字如何流動,因此使用 `index` 和 `final` 來追蹤通過訊息的進度,而不是期望行以特定方式分組。1569除了 [常見輸入欄位](#common-input-fields) 外,MessageDisplay hooks 還會接收回合和訊息的識別碼、此呼叫在訊息中的位置,以及 `delta` 中的新文字。批次邊界取決於文字流的方式,因此使用 `index` 和 `final` 追蹤訊息的進度,而不是期望行以特定方式分組。
1327 1570
1328| 欄位 | 描述 |1571| 欄位 | 描述 |
1329| :----------- | :-------------------------------------------------------------------------------------------------------------------------------------------------- |1572| :----------- | :---------------------------------------------------------------------------------------------------------------------------------------------------- |
1330| `turn_id` | 目前轉向的 UUID |1573| `turn_id` | 目前回合的 UUID |
1331| `message_id` | 被顯示的助手訊息的 UUID。在同一訊息的每批中穩定。這不是 API `msg_…` id,因此無法與成績單訊息 ids 相關聯 |1574| `message_id` | 正在顯示的助手訊息的 UUID。在同一訊息的每個批次中穩定。這不是 API `msg_…` id,因此無法與文字記錄訊息 id 相關聯 |
1332| `index` | 此批次在訊息中的零基索引 |1575| `index` | 訊息內此批次的零基索引 |
1333| `final` | 在訊息的最後一批上為 `true`。每個訊息恰好有一個最終批次 |1576| `final` | 在訊息的最後一個批次上為 `true`。每個訊息恰好有一個最終批次 |
1334| `delta` | 自上一批以來新完成的行,包括終止換行符。始終是完整行,除了最終批次可能在行中結束。在互動執行中,當訊息以換行符結束時,最終批次的 delta 為空,因此將 `final` 而不是非空 delta 視為訊息結束信號。在 Agent SDK 和 `claude -p` 執行中,單一呼叫攜帶整個訊息 |1577| `delta` | 自上一個批次以來新完成的行,包括終止換行符。始終是完整行,除了最終批次可能在行中結束。在互動執行中,當訊息以換行符結束時,最終批次的 delta 為空,因此將 `final` 而不是非空 delta 視為訊息結束信號。在 Agent SDK 和 `claude -p` 執行中,單個呼叫攜帶整個訊息 |
1335 1578
1336```json theme={null}1579```json theme={null}
1337{1580{
1351 MessageDisplay 輸出1594 MessageDisplay 輸出
1352</h4>1595</h4>
1353 1596
1354除了所有 hooks 可用的 [JSON 輸出欄位](#json-output) 外,MessageDisplay hooks 可以返回 `displayContent` 來替換螢幕上的 delta:1597除了所有 hooks 可用的 [JSON 輸出欄位](#json-output) 外,MessageDisplay hooks 可以返回 `displayContent` 以替換螢幕上的 delta:
1355 1598
1356| 欄位 | 描述 |1599| 欄位 | 描述 |
1357| :--------------- | :------------------------ |1600| :--------------- | :----------------------- |
1358| `displayContent` | 顯示以代替 delta 的文字。省略以顯示原始文字 |1601| `displayContent` | 顯示代替 delta 的文字。省略以顯示原始文字 |
1359 1602
1360MessageDisplay hooks 沒有決定控制。它們無法阻止訊息或改變成績單中儲存或發送給 Claude 的內容。1603MessageDisplay hooks 沒有決策控制。它們無法阻止訊息或更改文字記錄中儲存或發送給 Claude 的內容。Claude Code 作用於它們的 JSON 輸出中的 `displayContent` 並捨棄 `systemMessage` 和 `continue`。
1361 1604
1362此範例去除 Claude 回應中的 markdown 格式以獲得純文字顯示。指令碼從 stdin 讀取每批,從 `delta` 移除粗體標記和內聯代碼反引號,並將結果作為 `displayContent` 返回。1605此範例從 Claude 的回應中去除 markdown 格式以獲得純文字顯示。指令碼從 stdin 讀取每個批次,從 `delta` 中移除粗體標記和內聯代碼反引號,並將結果作為 `displayContent` 返回。
1363 1606
1364<Tabs>1607<Tabs>
1365 <Tab title="macOS/Linux">1608 <Tab title="macOS/Linux">
1389 #!/bin/bash1632 #!/bin/bash
1390 jq '{hookSpecificOutput: {hookEventName: "MessageDisplay", displayContent: (.delta | gsub("\\*\\*"; "") | gsub("`"; ""))}}'1633 jq '{hookSpecificOutput: {hookEventName: "MessageDisplay", displayContent: (.delta | gsub("\\*\\*"; "") | gsub("`"; ""))}}'
1391 ```1634 ```
1392
1393 指令碼需要 `jq` 在您的 `PATH` 上。
1394 </Tab>1635 </Tab>
1395 1636
1396 <Tab title="Windows (PowerShell)">1637 <Tab title="Windows (PowerShell)">
1397 註冊一個命令 hook,通過 PowerShell 執行指令碼:1638 註冊一個命令 hook,透過 PowerShell 執行指令碼:
1398 1639
1399 ```json theme={null}1640 ```json theme={null}
1400 {1641 {
1420 }1661 }
1421 ```1662 ```
1422 1663
1423 `-NoProfile` 標誌跳過載入您的 PowerShell 設定檔,以便 hook 快速啟動,`-ExecutionPolicy Bypass` 讓 PowerShell 執行本機指令碼檔案。1664 `-NoProfile` 旗標跳過載入您的 PowerShell 設定檔,以便 hook 快速啟動,`-ExecutionPolicy Bypass` 讓 PowerShell 執行本機指令碼檔案。
1424 1665
1425 將此指令碼儲存到您專案中的 `.claude/hooks/plain-display.ps1`:1666 將此指令碼儲存到您專案中的 `.claude/hooks/plain-display.ps1`:
1426 1667
1437 </Tab>1678 </Tab>
1438</Tabs>1679</Tabs>
1439 1680
1440沒有 markdown 的批次通過不變。如果指令碼失敗,例如因為 `jq` 遺失,Claude Code 顯示原始文字,並僅在 [偵錯輸出](#debug-hooks) 中注意失敗,而不是在工作階段中。1681沒有 markdown 的批次通過不變。如果指令碼失敗,例如因為 `jq` 缺失,Claude Code 顯示原始文字並僅在 [偵錯輸出](#debug-hooks) 中記錄失敗,而不是在工作階段中。
1441 1682
1442<h3 id="pretooluse">1683<h3 id="pretooluse">
1443 PreToolUse1684 PreToolUse
1444</h3>1685</h3>
1445 1686
1446在 Claude 建立工具參數後和處理工具呼叫之前執行。匹配工具名稱:`Bash`、`Edit`、`Write`、`Read`、`Glob`、`Grep`、`Agent`、`WebFetch`、`WebSearch`、`AskUserQuestion`、`ExitPlanMode` 和任何 [MCP 工具名稱](#match-mcp-tools)。1687在 Claude 建立工具參數之後、處理工具呼叫之前執行。在除 `EndConversation` 外的任何工具名稱上匹配:內建工具,例如 `Bash`、`PowerShell`、`Edit`、`Write`、`Read`、`Glob`、`Grep`、`Agent`、`Workflow`、`WebFetch`、`WebSearch`、`AskUserQuestion` 和 `ExitPlanMode`,以及任何 [MCP 工具名稱](#match-mcp-tools)。
1688
1689若要在磁碟上的特定檔案變更時執行 hook,無論什麼寫入它,請改用 [FileChanged](#filechanged) 而不是按名稱匹配檔案編輯工具。與 PreToolUse 不同,Claude Code 在變更後執行 FileChanged hooks,它們沒有決策控制,因此無法阻止寫入。
1447 1690
1448<Warning>1691<Warning>
1449 PreToolUse 僅在 Claude 呼叫工具時執行。您 [在提示中使用 `@` 參考的檔案](/docs/zh-TW/common-workflows#reference-files-and-directories) 被新增而不進行任何工具呼叫:Claude Code 在建立提示時插入其內容,因此沒有 PreToolUse hook 針對它們觸發,包括匹配 `Read` 的 hooks。要阻止特定路徑的 `@` 參考,請改用 [`Read` 拒絕規則](/docs/zh-TW/permissions#read-and-edit)。1692 PreToolUse 僅在 Claude 呼叫工具時執行。您在提示中 [使用 `@` 參考的檔案](/docs/zh-TW/common-workflows#reference-files-and-directories) 會被新增而不進行任何工具呼叫:Claude Code 在建立提示時插入其內容,因此沒有 PreToolUse hook 對它們觸發,包括匹配 `Read` 的 hooks。若要阻止特定路徑的 `@` 參考,請改用 [`Read` 拒絕規則](/docs/zh-TW/permissions#read-and-edit)。
1693
1694 PreToolUse 也不對 [`EndConversation`](/docs/zh-TW/tools-reference#endconversation-tool-behavior) 觸發。
1450</Warning>1695</Warning>
1451 1696
1452使用 [PreToolUse 決定控制](#pretooluse-decision-control) 來允許、拒絕、詢問或延遲工具呼叫。1697使用 [PreToolUse 決策控制](#pretooluse-decision-control) 來允許、拒絕、詢問或延遲工具呼叫。
1698
1699在 `PreToolUse` 上超過其逾時的 [Agent SDK 回呼 hook](/docs/zh-TW/agent-sdk/hooks) 會阻止工具呼叫,Claude 接收命名逾時的錯誤結果。另一個 hook 返回的明確拒絕仍然優先。
1453 1700
1454<h4 id="pretooluse-input">1701<h4 id="pretooluse-input">
1455 PreToolUse 輸入1702 PreToolUse 輸入
1456</h4>1703</h4>
1457 1704
1458除了 [通用輸入欄位](#common-input-fields) 外,PreToolUse hooks 還接收 `tool_name`、`tool_input` 和 `tool_use_id`。`tool_input` 欄位取決於工具:1705除了 [常見輸入欄位](#common-input-fields) 外,PreToolUse hooks 還會接收 `tool_name`、`tool_input` 和 `tool_use_id`。
1706
1707對於 [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 或更新版本。
1708
1709對於檔案工具 `Write`、`Edit` 和 `Read`,`tool_input.file_path` 始終是絕對的:
1710
1711* Claude Code 在 hooks 執行之前擴展 `~` 和相對路徑,因此匹配路徑的 hook 無法透過 `~` 或相同路徑的相對拼寫繞過
1712* 在 Windows 上,路徑到達時使用反斜線分隔符,即使您的 hook 在 Git Bash 下執行,其中 `$PWD` 看起來像 `/c/project`
1713* 使用正斜線編寫的比較,例如 `/src/` 檢查,永遠不會匹配反斜線路徑,工具呼叫會如同 hook 沒有要阻止的內容一樣進行
1714* 在比較前規範化分隔符:Bash 中的 `FILE_PATH="${FILE_PATH//\\//}"`,或 Python 中的 `file_path.replace("\\", "/")`,然後匹配路徑段,例如 `/src/`,而不是使用 `^` 錨定,因為路徑是絕對的
1715
1716Windows 上的 `Write` 呼叫傳遞:
1717
1718```json theme={null}
1719{
1720 "hook_event_name": "PreToolUse",
1721 "tool_name": "Write",
1722 "tool_input": {
1723 "file_path": "C:\\project\\src\\index.ts",
1724 "content": "..."
1725 },
1726 ...
1727}
1728```
1729
1730`tool_input` 欄位取決於工具:
1731
1732<a id="bash" />
1459 1733
1460<h5 id="bash">1734<h5 id="bash">
1461 Bash1735 Bash
1464執行 shell 命令。1738執行 shell 命令。
1465 1739
1466| 欄位 | 類型 | 範例 | 描述 |1740| 欄位 | 類型 | 範例 | 描述 |
1467| :------------------ | :-- | :----------------- | :----------------------------------------------------------------------------- |1741| :------------------ | :------ | :----------------- | :--------------------------------------------------------------------------- |
1468| `command` | 字串 | `"npm test"` | 要執行的 shell 命令 |1742| `command` | string | `"npm test"` | 要執行的 shell 命令 |
1469| `description` | 字串 | `"Run test suite"` | 命令執行內容的可選描述 |1743| `description` | string | `"Run test suite"` | 命令執行內容的可選描述 |
1470| `timeout` | 數字 | `120000` | 可選逾時(毫秒)。超過 [最大值](/docs/zh-TW/tools-reference#bash-tool-behavior) 的值會被減少到最大值,而不是被拒絕 |1744| `timeout` | number | `120000` | 可選逾時(毫秒)。超過 [最大值](/docs/zh-TW/tools-reference#bash-tool-behavior) 的值會減少到最大值而不是被拒絕 |
1471| `run_in_background` | 布林值 | `false` | 是否在背景執行命令 |1745| `run_in_background` | boolean | `false` | 是否在背景執行命令 |
1746
1747當 Bash 命令更改 Git 儲存庫中的檔案時,Claude Code 可以記錄變更的內容。當 [`bashEditDiffEnabled`](/docs/zh-TW/settings-reference#basheditdiffenabled) 設定打開記錄時,它在每個權限模式中記錄;該設定的項目說明哪些檔案可以設定它。否則它僅在自動模式和 `bypassPermissions` 模式中記錄,並且僅當 Claude Code 指導 Claude 透過 Bash 編輯檔案時。設定 `bashEditDiffEnabled` 為 `false` 以關閉記錄。背景命令和唯讀命令不攜帶 diff。
1748
1749您的 [PostToolUse hook](#posttooluse) 然後在 `tool_response.bashEditDiff` 中接收變更的檔案。該清單涵蓋命令執行時在儲存庫下變更的內容。Git 忽略的檔案和子模組中的檔案不被列出。需要 Claude Code v2.1.269 或更新版本。
1750
1751<Note>
1752 該清單是盡力而為的,處於公開測試版。Claude Code 可能會遺漏變更、包含另一個程序同時變更的檔案,或在其大小限制處停止。欄位形狀可能會變更。使用該清單找到要審查的內容,而不是強制執行原則。
1753</Note>
1754
1755`changedFiles` 和 `files` 列出命令變更的內容;其餘欄位說明該清單的完整性和可靠性。
1756
1757| 欄位 | 類型 | 範例 | 描述 |
1758| :------------- | :------ | :------------------------------------------------------ | :------------------------------------------------------------------------ |
1759| `changedFiles` | array | `["/path/to/src/app.ts"]` | 命令變更的檔案的絕對路徑,最多 200 個。每當 `files` 保留 diff 或 `moreFiles` 高於零時出現 |
1760| `files` | array | `[{"filePath": "/path/to/src/app.ts", "hunks": [...]}]` | 最多 5 個變更檔案的 diffs,用於顯示。對於命令新增或移除的檔案,`created` 或 `deleted` 為 `true` |
1761| `moreFiles` | number | `2` | 在 `files` 中沒有 diff 的變更檔案計數 |
1762| `unavailable` | boolean | `true` | 當 diff 不完整或無法進行時設定 |
1763| `skipped` | boolean | `true` | 對於移動工作樹的 Git 命令設定,例如 `git checkout` 或 `git stash`,因此 Claude Code 不進行 diff |
1764| `shared` | boolean | `true` | 當另一個 Bash 工具呼叫(例如子代理的)同時在同一儲存庫中執行時設定,因此某些列出的變更可能是該命令的 |
1765
1766<a id="powershell" />
1767
1768<h5 id="powershell">
1769 PowerShell
1770</h5>
1771
1772執行 PowerShell 命令。請參閱 [PowerShell 工具](/docs/zh-TW/tools-reference#powershell-tool),了解按平台的可用性。
1773
1774欄位與 Bash 工具匹配,命令字串在 `command` 中:
1775
1776| 欄位 | 類型 | 範例 | 描述 |
1777| :------------------ | :------ | :------------------------- | :----------------- |
1778| `command` | string | `"Get-ChildItem -Recurse"` | 要執行的 PowerShell 命令 |
1779| `description` | string | `"List files recursively"` | 命令執行內容的可選描述 |
1780| `timeout` | number | `120000` | 可選逾時(毫秒) |
1781| `run_in_background` | boolean | `false` | 是否在背景執行命令 |
1782
1783在檢查 shell 命令的 hooks 中匹配 `Bash|PowerShell`,以便它們涵蓋兩個工具:
1784
1785* 在 Windows 上,只要啟用了 PowerShell 工具,Claude 就會將 PowerShell 視為主要 shell 並透過它路由 shell 命令。
1786* 在沒有 Git Bash 的 Windows 上,工具會自動啟用,Claude Code 根本不會註冊 Bash 工具。
1787* 僅匹配 `Bash` 的 hook 永遠不會在那裡觸發。
1472 1788
1473<h5 id="write">1789<h5 id="write">
1474 Write1790 Write
1477建立或覆寫檔案。1793建立或覆寫檔案。
1478 1794
1479| 欄位 | 類型 | 範例 | 描述 |1795| 欄位 | 類型 | 範例 | 描述 |
1480| :---------- | :- | :-------------------- | :---------- |1796| :---------- | :----- | :-------------------- | :---------- |
1481| `file_path` | 字串 | `"/path/to/file.txt"` | 要寫入的檔案的絕對路徑 |1797| `file_path` | string | `"/path/to/file.txt"` | 要寫入的檔案的絕對路徑 |
1482| `content` | 字串 | `"file content"` | 要寫入檔案的內容 |1798| `content` | string | `"file content"` | 要寫入檔案的內容 |
1483 1799
1484<h5 id="edit">1800<h5 id="edit">
1485 Edit1801 Edit
1488替換現有檔案中的字串。1804替換現有檔案中的字串。
1489 1805
1490| 欄位 | 類型 | 範例 | 描述 |1806| 欄位 | 類型 | 範例 | 描述 |
1491| :------------ | :-- | :-------------------- | :---------- |1807| :------------ | :------ | :-------------------- | :---------- |
1492| `file_path` | 字串 | `"/path/to/file.txt"` | 要編輯的檔案的絕對路徑 |1808| `file_path` | string | `"/path/to/file.txt"` | 要編輯的檔案的絕對路徑 |
1493| `old_string` | 字串 | `"original text"` | 要查詢和替換的文字 |1809| `old_string` | string | `"original text"` | 要尋找和替換的文字 |
1494| `new_string` | 字串 | `"replacement text"` | 替換文字 |1810| `new_string` | string | `"replacement text"` | 替換文字 |
1495| `replace_all` | 布林值 | `false` | 是否替換所有出現次數 |1811| `replace_all` | boolean | `false` | 是否替換所有出現次數 |
1496 1812
1497<h5 id="read">1813<h5 id="read">
1498 Read1814 Read
1501讀取檔案內容。1817讀取檔案內容。
1502 1818
1503| 欄位 | 類型 | 範例 | 描述 |1819| 欄位 | 類型 | 範例 | 描述 |
1504| :---------- | :- | :-------------------- | :---------- |1820| :---------- | :----- | :-------------------- | :---------- |
1505| `file_path` | 字串 | `"/path/to/file.txt"` | 要讀取的檔案的絕對路徑 |1821| `file_path` | string | `"/path/to/file.txt"` | 要讀取的檔案的絕對路徑 |
1506| `offset` | 數字 | `10` | 可選的開始讀取的行號 |1822| `offset` | number | `10` | 可選行號以開始讀取 |
1507| `limit` | 數字 | `50` | 可選的要讀取的行數 |1823| `limit` | number | `50` | 可選要讀取的行數 |
1508 1824
1509<h5 id="glob">1825<h5 id="glob">
1510 Glob1826 Glob
1513尋找與 glob 模式匹配的檔案。1829尋找與 glob 模式匹配的檔案。
1514 1830
1515| 欄位 | 類型 | 範例 | 描述 |1831| 欄位 | 類型 | 範例 | 描述 |
1516| :-------- | :- | :--------------- | :---------------- |1832| :-------- | :----- | :--------------- | :----------------- |
1517| `pattern` | 字串 | `"**/*.ts"` | 要匹配檔案的 glob 模式 |1833| `pattern` | string | `"**/*.ts"` | 要匹配檔案的 glob 模式 |
1518| `path` | 字串 | `"/path/to/dir"` | 可選的搜尋目錄。預設為目前工作目錄 |1834| `path` | string | `"/path/to/dir"` | 可選要搜尋的目錄。預設為目前工作目錄 |
1519 1835
1520<h5 id="grep">1836<h5 id="grep">
1521 Grep1837 Grep
1524使用正規表達式搜尋檔案內容。1840使用正規表達式搜尋檔案內容。
1525 1841
1526| 欄位 | 類型 | 範例 | 描述 |1842| 欄位 | 類型 | 範例 | 描述 |
1527| :------------ | :-- | :--------------- | :------------------------------------------------------------------------ |1843| :------------ | :------ | :--------------- | :------------------------------------------------------------------------ |
1528| `pattern` | 字串 | `"TODO.*fix"` | 要搜尋的正規表達式模式 |1844| `pattern` | string | `"TODO.*fix"` | 要搜尋的正規表達式模式 |
1529| `path` | 字串 | `"/path/to/dir"` | 可選的要搜尋的檔案或目錄 |1845| `path` | string | `"/path/to/dir"` | 可選要搜尋的檔案或目錄 |
1530| `glob` | 字串 | `"*.ts"` | 可選的 glob 模式以篩選檔案 |1846| `glob` | string | `"*.ts"` | 可選 glob 模式以篩選檔案 |
1531| `output_mode` | 字串 | `"content"` | `"content"`、`"files_with_matches"` 或 `"count"`。預設為 `"files_with_matches"` |1847| `output_mode` | string | `"content"` | `"content"`、`"files_with_matches"` 或 `"count"`。預設為 `"files_with_matches"` |
1532| `-i` | 布林值 | `true` | 不區分大小寫的搜尋 |1848| `-i` | boolean | `true` | 不區分大小寫搜尋 |
1533| `multiline` | 布林值 | `false` | 啟用多行匹配 |1849| `multiline` | boolean | `false` | 啟用多行匹配 |
1534 1850
1535<h5 id="webfetch">1851<h5 id="webfetch">
1536 WebFetch1852 WebFetch
1539擷取和處理網路內容。1855擷取和處理網路內容。
1540 1856
1541| 欄位 | 類型 | 範例 | 描述 |1857| 欄位 | 類型 | 範例 | 描述 |
1542| :------- | :- | :---------------------------- | :----------- |1858| :------- | :----- | :---------------------------- | :----------- |
1543| `url` | 字串 | `"https://example.com/api"` | 要擷取內容的 URL |1859| `url` | string | `"https://example.com/api"` | 要擷取內容的 URL |
1544| `prompt` | 字串 | `"Extract the API endpoints"` | 在擷取的內容上執行的提示 |1860| `prompt` | string | `"Extract the API endpoints"` | 在擷取的內容上執行的提示 |
1545 1861
1546<h5 id="websearch">1862<h5 id="websearch">
1547 WebSearch1863 WebSearch
1550搜尋網路。1866搜尋網路。
1551 1867
1552| 欄位 | 類型 | 範例 | 描述 |1868| 欄位 | 類型 | 範例 | 描述 |
1553| :---------------- | :- | :----------------------------- | :-------------- |1869| :---------------- | :----- | :----------------------------- | :-------------- |
1554| `query` | 字串 | `"react hooks best practices"` | 搜尋查詢 |1870| `query` | string | `"react hooks best practices"` | 搜尋查詢 |
1555| `allowed_domains` | 陣列 | `["docs.example.com"]` | 可選:僅包含來自這些網域的結果 |1871| `allowed_domains` | array | `["docs.example.com"]` | 可選:僅包含來自這些網域的結果 |
1556| `blocked_domains` | 陣列 | `["spam.example.com"]` | 可選:排除來自這些網域的結果 |1872| `blocked_domains` | array | `["spam.example.com"]` | 可選:排除來自這些網域的結果 |
1557 1873
1558<h5 id="agent">1874<h5 id="agent">
1559 Agent1875 Agent
1560</h5>1876</h5>
1561 1877
1562生成一個 [subagent](/docs/zh-TW/sub-agents)。1878生成 [子代理](/docs/zh-TW/sub-agents)。
1563 1879
1564| 欄位 | 類型 | 範例 | 描述 |1880| 欄位 | 類型 | 範例 | 描述 |
1565| :-------------- | :- | :------------------------- | :------------ |1881| :-------------- | :----- | :------------------------- | :----------- |
1566| `prompt` | 字串 | `"Find all API endpoints"` | 代理要執行的任務 |1882| `prompt` | string | `"Find all API endpoints"` | 代理要執行的任務 |
1567| `description` | 字串 | `"Find API endpoints"` | 任務的簡短描述 |1883| `description` | string | `"Find API endpoints"` | 任務的簡短描述 |
1568| `subagent_type` | 字串 | `"Explore"` | 要使用的專門代理類型 |1884| `subagent_type` | string | `"Explore"` | 要使用的專門代理類型 |
1569| `model` | 字串 | `"sonnet"` | 可選的模型別名以覆蓋預設值 |1885| `model` | string | `"sonnet"` | 可選模型別名以覆寫預設值 |
1570 1886
1571在 `PostToolUse` 中,已完成的 Agent 呼叫的 `tool_response` 攜帶 subagent 的最終文字以及使用量遙測。讀取這些欄位以從 hook 記錄每個 subagent 的成本:1887當前景 Agent 呼叫完成時,您的 [PostToolUse hook](#posttooluse) 在 `tool_response` 中接收子代理的結果和執行遙測。讀取這些欄位以檢查執行;對於跨子代理的令牌和成本匯總,使用 [令牌和成本計數器](/docs/zh-TW/monitoring-usage#token-counter),篩選為 `query_source` `"subagent"`,因為 `totalTokens` 和 `usage` 僅涵蓋最終請求:
1572 1888
1573| 欄位 | 類型 | 範例 | 描述 |1889| 欄位 | 類型 | 範例 | 描述 |
1574| :------------------ | :- | :---------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------- |1890| :------------------ | :----- | :---------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------- |
1575| `status` | 字串 | `"completed"` | 前景 subagents 為 `"completed"`,背景 subagents 為 `"async_launched"`。從 v2.1.198 開始,subagents 預設在背景執行,因此省略的 `run_in_background` 也會產生 `"async_launched"` |1891| `status` | string | `"completed"` | 前景子代理為 `"completed"`,背景子代理為 `"async_launched"`。自 v2.1.198 起,子代理預設在背景執行,因此省略的 `run_in_background` 也會產生 `"async_launched"` |
1576| `agentId` | 字串 | `"a4d2c8f1e0b3a297"` | subagent 執行的識別碼 |1892| `agentId` | string | `"a4d2c8f1e0b3a297"` | 子代理執行的識別碼 |
1577| `content` | 陣列 | `[{"type": "text", "text": "Found 12 endpoints..."}]` | subagent 的最終文字塊 |1893| `content` | array | `[{"type": "text", "text": "Found 12 endpoints..."}]` | 子代理的最終文字區塊,或對於其報告透過 `SubagentHandback` 的子代理,關於該交接的簡短說明代替 |
1578| `resolvedModel` | 字串 | `"claude-sonnet-4-5"` | subagent 執行的模型,可能與請求的模型不同。需要 Claude Code v2.1.174 或更高版本 |1894| `resolvedModel` | string | `"claude-sonnet-4-5"` | 子代理啟動的模型,可能與請求的模型不同 |
1579| `totalTokens` | 數字 | `12450` | 在 subagent 轉向中計費的總令牌數 |1895| `modelsUsed` | array | `["claude-sonnet-4-5", "claude-haiku-4-5"]` | 按順序使用的模型,連續重複摺疊;僅在模型在執行中交換時設定。需要 Claude Code v2.1.212 或更新版本 |
1580| `totalDurationMs` | 數字 | `48211` | subagent 執行的掛鐘時間 |1896| `totalTokens` | number | `12450` | 子代理最終 API 請求的令牌計數:輸入、輸出和快取令牌結合。這不是整個執行的總計 |
1581| `totalToolUseCount` | 數字 | `7` | subagent 進行的工具呼叫計數 |1897| `totalDurationMs` | number | `48211` | 子代理執行的掛鐘持續時間 |
1582| `usage` | 物件 | `{"input_tokens": 8320, ...}` | 按類型的令牌細分:`input_tokens`、`output_tokens`、`cache_creation_input_tokens`、`cache_read_input_tokens` |1898| `totalToolUseCount` | number | `7` | 子代理進行的工具呼叫計數 |
1899| `usage` | object | `{"input_tokens": 8320, ...}` | 最終 API 請求的每類型令牌細目:`input_tokens`、`output_tokens`、`cache_creation_input_tokens`、`cache_read_input_tokens` |
1583 1900
1584對於背景 subagents,工具在啟動 subagent 後立即返回,因此 `tool_response` 不攜帶使用量欄位。它具有 `status: "async_launched"`、`agentId`、`description`、`prompt`、`outputFile` 和 `resolvedModel`。1901在 Claude Code v2.1.271 或更新版本上,使用 [`SubagentHandback`](/docs/zh-TW/tools-reference) 工具執行的子代理(Claude Code 在 [自動模式](/docs/zh-TW/permission-modes#eliminate-prompts-with-auto-mode) 中提供)透過該工具傳遞其報告,而不是作為文字返回。其 `completed` 結果的 `content` 欄位然後攜帶關於該交接的簡短說明,而不是報告本身。若要讀取報告,請在 `SubagentHandback` 上匹配 `PreToolUse` 或 `PostToolUse` hook 並讀取 `tool_input.message`。
1585 1902
1586`resolvedModel` 欄位命名 subagent 實際執行的模型,可能與 `tool_input` 中的 `model` 值不同,例如當 `availableModels` 或其他覆蓋適用時。它需要 Claude Code v2.1.174 或更高版本。1903對於背景子代理,工具在任務移到背景時返回,因此 `tool_response` 不攜帶使用欄位:背景啟動立即返回,前景任務在執行中被背景化時返回。它有 `status: "async_launched"`、`agentId`、`description`、`prompt`、`outputFile` 和 `resolvedModel`。
1904
1905在 `completed` 回應上,`resolvedModel` 命名子代理啟動的模型,可能與 `tool_input` 中的 `model` 值不同,例如當 `availableModels` 或其他覆寫適用時。在 `async_launched` 回應上,`resolvedModel` 命名代理移到背景時使用的模型,因此在背景化之前發生的交換會反映在那裡。`modelsUsed` 和背景化時間 `resolvedModel` 行為需要 Claude Code v2.1.212 或更新版本。
1587 1906
1588<a id="askuserquestion" />1907<a id="askuserquestion" />
1589 1908
1594詢問使用者一到四個多選題。1913詢問使用者一到四個多選題。
1595 1914
1596| 欄位 | 類型 | 範例 | 描述 |1915| 欄位 | 類型 | 範例 | 描述 |
1597| :---------- | :- | :----------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------- |1916| :---------- | :----- | :----------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------- |
1598| `questions` | 陣列 | `[{"question": "Which framework?", "header": "Framework", "options": [{"label": "React"}], "multiSelect": false}]` | 要呈現的問題,每個都有 `question` 字串、簡短 `header`、`options` 陣列和可選的 `multiSelect` 標誌 |1917| `questions` | array | `[{"question": "Which framework?", "header": "Framework", "options": [{"label": "React"}], "multiSelect": false}]` | 要呈現的問題,每個都有 `question` 字串、簡短 `header`、`options` 陣列和可選 `multiSelect` 旗標 |
1599| `answers` | 物件 | `{"Which framework?": "React"}` | 可選。將問題文字對應到選定的選項標籤。多選答案用逗號連接標籤。Claude 不設定此欄位;通過 `updatedInput` 提供它以以程式方式回答 |1918| `answers` | object | `{"Which framework?": "React"}` | 可選。將問題文字對應到選定的選項標籤。多選答案用逗號連接標籤。Claude 不設定此欄位;透過 `updatedInput` 提供以程式設計方式回答 |
1600 1919
1601<h5 id="exitplanmode">1920<h5 id="exitplanmode">
1602 ExitPlanMode1921 ExitPlanMode
1603</h5>1922</h5>
1604 1923
1605呈現一個計劃並要求使用者在 Claude 離開 [plan mode](/docs/zh-TW/permission-modes#analyze-before-you-edit-with-plan-mode) 之前批准它。Claude 在呼叫工具之前將計劃寫入磁碟上的檔案,因此模型的字面 `tool_input` 通常為空。Claude Code 在將輸入傳遞給 hooks 之前注入計劃內容和檔案路徑。1924呈現計畫並要求使用者在 Claude 離開 [計畫模式](/docs/zh-TW/permission-modes#analyze-before-you-edit-with-plan-mode) 之前核准。Claude 在呼叫工具之前將計畫寫入磁碟上的檔案,因此模型的字面 `tool_input` 通常是空的。Claude Code 在將輸入傳遞給 hooks 之前注入計畫內容和檔案路徑。
1606 1925
1607| 欄位 | 類型 | 範例 | 描述 |1926| 欄位 | 類型 | 範例 | 描述 |
1608| :--------------- | :- | :------------------------------------------ | :---------------------------------------------------------------- |1927| :--------------- | :----- | :------------------------------------------ | :---------------------------------------------------------------- |
1609| `plan` | 字串 | `"## Refactor auth\n1. Extract..."` | Markdown 中的計劃內容。從磁碟上的計劃檔案注入 |1928| `plan` | string | `"## Refactor auth\n1. Extract..."` | Markdown 中的計畫內容。從磁碟上的計畫檔案注入 |
1610| `planFilePath` | 字串 | `"/Users/.../plans/refactor-auth.md"` | 計劃檔案的路徑。注入 |1929| `planFilePath` | string | `"/Users/.../plans/refactor-auth.md"` | 計畫檔案的路徑。注入 |
1611| `allowedPrompts` | 陣列 | `[{"tool": "Bash", "prompt": "run tests"}]` | 已棄用。Claude Code 接受該欄位但忽略它。在 v2.1.205 之前,它攜帶 Claude 要求實施計劃的基於提示的權限 |1930| `allowedPrompts` | array | `[{"tool": "Bash", "prompt": "run tests"}]` | 已棄用。Claude Code 接受欄位但忽略它。在 v2.1.205 之前,它攜帶 Claude 請求以實施計畫的基於提示的權限 |
1612 1931
1613在 `PostToolUse` 中,`tool_response` 是一個物件,其中包含 `plan` 和 `filePath` 欄位,保存批准的計劃,加上內部狀態標誌。讀取 `tool_response.plan` 以獲取計劃內容,而不是從磁碟重新讀取檔案。1932在 `PostToolUse` 中,`tool_response` 是一個物件,包含 `plan` 和 `filePath` 欄位保留核准的計畫,加上內部狀態旗標。讀取 `tool_response.plan` 以獲取計畫內容,而不是從磁碟重新讀取檔案。
1614 1933
1615<h4 id="pretooluse-decision-control">1934<h4 id="pretooluse-decision-control">
1616 PreToolUse 決定控制1935 PreToolUse 決策控制
1617</h4>1936</h4>
1618 1937
1619`PreToolUse` hooks 可以控制工具呼叫是否進行。與使用頂層 `decision` 欄位的其他 hooks 不同,PreToolUse 在 `hookSpecificOutput` 物件內返回其決定。這提供了更豐富的控制:四個結果(允許、拒絕、詢問或延遲)加上在執行前修改工具輸入的能力。1938`PreToolUse` hooks 可以控制工具呼叫是否進行。與使用頂級 `decision` 欄位的其他 hooks 不同,PreToolUse 在 `hookSpecificOutput` 物件內返回其決策。這提供了更豐富的控制:四個結果(允許、拒絕、詢問或延遲)加上在執行前修改工具輸入的能力。
1620 1939
1621| 欄位 | 描述 |1940| 欄位 | 描述 |
1622| :------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |1941| :------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
1623| `permissionDecision` | `"allow"` 跳過權限提示,除了 [需要使用者互動的工具](#pretooluse-decision-control) 和連接器工具 [您的組織設定為 `ask`](/docs/zh-TW/mcp#organization-controls-on-connector-tools)。`"deny"` 防止工具呼叫。`"ask"` 提示使用者確認。`"defer"` 優雅地退出,以便稍後可以恢復工具。[拒絕和詢問規則](/docs/zh-TW/permissions#manage-permissions) 仍然適用,無論 hook 返回什麼 |1942| `permissionDecision` | `"allow"` 跳過權限提示,除了 [任何模式自動核准的動作](/docs/zh-TW/permission-modes#actions-no-mode-auto-approves) 和 `AskUserQuestion` 和 `ExitPlanMode`,需要 [`updatedInput` 與其配對](#allow-with-updatedinput)。`"deny"` 防止工具呼叫。`"ask"` 提示使用者確認。`"defer"` 優雅地退出,以便稍後可以恢復工具。[拒絕和詢問規則](/docs/zh-TW/permissions#manage-permissions) 無論 hook 返回什麼都會被評估 |
1624| `permissionDecisionReason` | 對於 `"allow"` 和 `"ask"`,向使用者顯示但不向 Claude 顯示。對於 `"deny"`,向 Claude 顯示。對於 `"defer"`,被忽略 |1943| `permissionDecisionReason` | 對於 `"allow"` 和 `"ask"`,顯示給使用者但不顯示給 Claude。對於 `"deny"`,顯示給 Claude。對於 `"defer"`,忽略 |
1625| `updatedInput` | 在執行前修改工具的輸入參數。替換整個輸入物件,因此包括未修改的欄位以及修改後的欄位。與 `"allow"` 結合以自動批准,或與 `"ask"` 結合以向使用者顯示修改後的輸入。對於 `"defer"`,被忽略 |1944| `updatedInput` | 在執行前修改工具的輸入參數。替換整個輸入物件,因此在修改的欄位旁邊包含未變更的欄位。Claude Code 根據您的 hook 返回的輸入評估權限規則和 Bash 命令的 [自動背景資格](/docs/zh-TW/tools-reference#background-commands),而不是 Claude 發送的輸入。與 `"allow"` 結合以自動核准,或與 `"ask"` 結合以向使用者顯示修改的輸入。對於 `"defer"`,忽略 |
1626| `additionalContext` | 在工具執行前新增到 Claude 上下文的字串。對於 `"defer"`,被忽略。請參閱 [為 Claude 新增上下文](#add-context-for-claude) |1945| `additionalContext` | 與工具結果一起新增到 Claude 背景資訊的字串。當 `permissionDecision` 為 `"defer"` 時忽略。請參閱 [為 Claude 新增背景資訊](#add-context-for-claude) |
1946
1947當多個 PreToolUse hooks 返回不同的決策時,優先順序為 `deny` > `defer` > `ask` > `allow`。
1627 1948
1628當多個 PreToolUse hooks 返回不同的決定時,優先順序是 `deny` > `defer` > `ask` > `allow`。1949透過退出 2 阻止的 hook 路由方式與 `"deny"` 相同:Claude 看到 stderr 訊息作為拒絕原因。
1629 1950
1630當 hook 返回 `"ask"` 時,向使用者顯示的權限提示包括一個標籤,識別 hook 來自何處:例如 `[User]`、`[Project]`、`[Plugin]` 或 `[Local]`。這幫助使用者了解哪個配置來源正在請求確認。1951當 hook 返回 `"ask"` 時,顯示給使用者的權限提示包含一個標籤,識別 hook 來自何處:`[settings]` 對於來自任何設定檔或代理 frontmatter 的 hook,`[plugin:<name>]` 對於外掛的 hook,或 `[skill]` 對於來自 skill frontmatter 的 hook。這幫助使用者理解哪個設定來源要求確認。
1952
1953Hook 的 `"ask"` 也在 [自動模式](/docs/zh-TW/permission-modes#eliminate-prompts-with-auto-mode) 中強制權限提示:分類器仍然可以拒絕工具呼叫,但無法無聲地核准呼叫。在 v2.1.211 之前,分類器可以核准在 [沙箱](/docs/zh-TW/sandboxing) 外執行的 Bash 命令而不顯示 hook 請求的提示;分類器仍然對該命令應用了自己的安全規則,hook `"deny"` 始終被尊重。
1631 1954
1632```json theme={null}1955```json theme={null}
1633{1956{
1643}1966}
1644```1967```
1645 1968
1646`AskUserQuestion` 和 `ExitPlanMode` 需要使用者互動,通常在 [非互動模式](/docs/zh-TW/headless) 中使用 `-p` 標誌時阻止。返回 `permissionDecision: "allow"` 以及 `updatedInput` 滿足該要求:hook 從 stdin 讀取工具的輸入,通過您自己的 UI 收集答案,並在 `updatedInput` 中返回它,以便工具執行而不提示。僅返回 `"allow"` 對這些工具不夠。對於 `AskUserQuestion`,回顯原始 `questions` 陣列並新增一個 [`answers`](#askuserquestion) 物件,將每個問題的文字對應到選定的答案。1969<span id="allow-with-updatedinput" />
1647 1970
1648連接器工具 [您的組織設定為 `ask`](/docs/zh-TW/mcp#organization-controls-on-connector-tools) 即使 hook 返回 `"allow"` 也會提示。1971在 [非互動模式](/docs/zh-TW/headless) 中使用 `-p` 旗標,Claude Code 僅在執行有 [權限主機](/docs/zh-TW/headless#turn-off-permission-prompts-in-unattended-runs) 以接收提示時提供 `AskUserQuestion` 和 `ExitPlanMode`,例如 Agent SDK `canUseTool` 回呼。這些工具需要使用者互動。返回 `permissionDecision: "allow"` 與 `updatedInput` 一起滿足該要求:hook 從 stdin 讀取工具的輸入,透過您自己的 UI 收集答案,並在 `updatedInput` 中返回它,以便工具執行而不提示。單獨返回 `"allow"` 對這些工具不足夠。對於 `AskUserQuestion`,回顯原始 `questions` 陣列並新增一個 [`answers`](#askuserquestion) 物件,將每個問題的文字對應到選定的答案。
1649 1972
1650從 v2.1.199 開始,一個 MCP 工具,其伺服器使用 [`_meta["anthropic/requiresUserInteraction"]`](/docs/zh-TW/mcp#require-approval-for-a-specific-tool) 標記它,更嚴格:hook 無法使用 `"allow"` 跳過其批准提示,無論是否有 `updatedInput`,因為 Claude Code 無法確認 hook 收集了工具需要的互動。1973自 v2.1.199 起,其伺服器使用 [`_meta["anthropic/requiresUserInteraction"]`](/docs/zh-TW/mcp#require-approval-for-a-specific-tool) 標記的 MCP 工具更嚴格:hook 無法使用 `"allow"` 跳過其核准提示,無論是否有 `updatedInput`,因為 Claude Code 無法確認 hook 收集了工具需要的互動。
1651 1974
1652<Note>1975<Note>
1653 PreToolUse 之前使用頂層 `decision` 和 `reason` 欄位,但這些對此事件已棄用。改用 `hookSpecificOutput.permissionDecision` 和 `hookSpecificOutput.permissionDecisionReason`。棄用的值 `"approve"` 和 `"block"` 對應於 `"allow"` 和 `"deny"`。PostToolUse 和 Stop 等其他事件繼續使用頂層 `decision` 和 `reason` 作為其目前格式。1976 PreToolUse 之前使用頂級 `decision` 和 `reason` 欄位,但這些對此事件已棄用。改用 `hookSpecificOutput.permissionDecision` 和 `hookSpecificOutput.permissionDecisionReason`。已棄用的值 `"approve"` 和 `"block"` 對應到 `"allow"` 和 `"deny"`。PostToolUse 和 Stop 等其他事件繼續使用頂級 `decision` 和 `reason` 作為其目前格式。
1654</Note>1977</Note>
1655 1978
1656<h4 id="defer-a-tool-call-for-later">1979<h4 id="defer-a-tool-call-for-later">
1657 延遲工具呼叫以供稍後使用1980 延遲工具呼叫以供稍後使用
1658</h4>1981</h4>
1659 1982
1660`"defer"` 用於執行 `claude -p` 作為子程序並讀取其 JSON 輸出的整合,例如 Agent SDK 應用程式或建立在 Claude Code 之上的自訂 UI。它讓該呼叫程序在工具呼叫處暫停 Claude,通過其自己的介面收集輸入,並從中斷處恢復。Claude Code 僅在 [非互動模式](/docs/zh-TW/headless) 中使用 `-p` 標誌時遵守此值。在互動式工作階段中,它記錄警告並忽略 hook 結果。1983`"defer"` 適用於執行 `claude -p` 作為子程序並讀取其 JSON 輸出的整合,例如 Agent SDK 應用程式或建立在 Claude Code 之上的自訂 UI。它讓該呼叫程序在工具呼叫處暫停 Claude,透過其自己的介面收集輸入,並在中斷處恢復。Claude Code 僅在 [非互動模式](/docs/zh-TW/headless) 中使用 `-p` 旗標時尊重此值。在互動式工作階段中,它記錄警告並忽略 hook 結果。
1661 1984
1662`AskUserQuestion` 工具是典型情況:Claude 想要詢問使用者某些事情,但沒有終端來回答。往返工作如下:1985`AskUserQuestion` 工具是典型情況:Claude 想詢問使用者某事,但沒有終端來回答。`-p` 執行僅在有 [權限主機](/docs/zh-TW/headless#turn-off-permission-prompts-in-unattended-runs) 時提供 `AskUserQuestion`,例如您使用 `--permission-prompt-tool` 傳遞的 MCP 工具,因此使用一個啟動執行。往返工作如下:
1663 1986
16641. Claude 呼叫 `AskUserQuestion`。`PreToolUse` hook 觸發。19871. Claude 呼叫 `AskUserQuestion`。`PreToolUse` hook 觸發。
16652. Hook 返回 `permissionDecision: "defer"`。工具不執行。程序以 `stop_reason: "tool_deferred"` 退出,待處理的工具呼叫保留在成績單中。19882. Hook 返回 `permissionDecision: "defer"`。工具不執行。程序以 `stop_reason: "tool_deferred"` 退出,待處理工具呼叫保留在文字記錄中。
16663. 呼叫程序從 SDK 結果讀取 `deferred_tool_use`,在其自己的 UI 中呈現問題,並等待答案。19893. 呼叫程序從 SDK 結果讀取 `deferred_tool_use`,在其自己的 UI 中呈現問題,並等待答案。
16674. 呼叫程序執行 `claude -p --resume <session-id>`。相同的工具呼叫再次觸發 `PreToolUse`。19904. 呼叫程序執行 `claude -p --resume <session-id>`,使用相同的權限主機。相同的工具呼叫再次觸發 `PreToolUse`。
16685. Hook 返回 `permissionDecision: "allow"`,答案在 `updatedInput` 中。工具執行,Claude 繼續。19915. Hook 返回 `permissionDecision: "allow"`,答案在 `updatedInput` 中。工具執行,Claude 繼續。
1669 1992
1670`deferred_tool_use` 欄位攜帶工具的 `id`、`name` 和 `input`。`input` 是 Claude 為工具呼叫生成的參數,在執行前捕獲:1993`deferred_tool_use` 欄位攜帶工具的 `id`、`name` 和 `input`。`input` 是 Claude 為工具呼叫生成的參數,在執行前捕獲:
1683}2006}
1684```2007```
1685 2008
1686沒有逾時或重試限制。工作階段保留在磁碟上,直到您恢復它,受到 [`cleanupPeriodDays`](/docs/zh-TW/settings#available-settings) 保留掃描的約束,該掃描在預設 30 天後刪除工作階段檔案。如果恢復時答案還沒有準備好,hook 可以再次返回 `"defer"`,程序以相同的方式退出。呼叫程序控制何時通過最終返回 `"allow"` 或 `"deny"` 從 hook 中斷迴圈。2009沒有逾時或重試限制。工作階段保留在磁碟上直到您恢復它,受 [`cleanupPeriodDays`](/docs/zh-TW/settings-reference#cleanupperioddays) 保留掃描約束,預設情況下在 30 天後刪除工作階段檔案,遵循 [保留掃描規則](/docs/zh-TW/claude-directory#cleaned-up-automatically)。如果恢復時答案還未準備好,hook 可以再次返回 `"defer"`,程序以相同方式退出。呼叫程序透過最終從 hook 返回 `"allow"` 或 `"deny"` 來控制何時打破迴圈。
1687 2010
1688`"defer"` 僅在 Claude 在轉向中進行單一工具呼叫時有效。如果 Claude 一次進行多個工具呼叫,`"defer"` 會被忽略並顯示警告,工具通過正常權限流程進行。該限制存在是因為恢復只能重新執行一個工具:沒有辦法延遲一個呼叫而不留下其他呼叫未解決。2011`"defer"` 僅在 Claude 在回合中進行單個工具呼叫時有效。如果 Claude 同時進行多個工具呼叫,`"defer"` 會被忽略並帶有警告,工具透過正常權限流程進行。約束存在是因為恢復只能重新執行一個工具:沒有辦法延遲批次中的一個呼叫而不留下其他未解決。
1689 2012
1690如果恢復時延遲的工具不再可用,程序以 `stop_reason: "tool_deferred_unavailable"` 和 `is_error: true` 退出,在 hook 觸發之前。這發生在提供工具的 MCP 伺服器對於恢復的工作階段未連接時。`deferred_tool_use` 有效負載仍然包括在內,以便您可以識別哪個工具遺失。2013如果恢復時延遲的工具不再可用,程序以 `stop_reason: "tool_deferred_unavailable"` 和 `is_error: true` 退出,在 hook 觸發之前。這發生在為恢復的工作階段未連接提供工具的 MCP 伺服器時。`deferred_tool_use` 有效負載仍然包含,以便您可以識別哪個工具遺失。
1691 2014
1692<Note>2015<Note>
1693 `--resume` 恢復工具被延遲時活動的權限模式,因此您不需要再次傳遞 `--permission-mode`。例外是 `plan` 和 `bypassPermissions`,它們永遠不會被帶過。在恢復時明確傳遞 `--permission-mode` 會覆蓋恢復的值。2016 若要在計畫模式中恢復延遲工作階段,請在 `--resume` 時傳遞 [`--permission-prompt-tool`](/docs/zh-TW/cli-reference#cli-flags),以便 Claude Code 可以呈現計畫以供核准。沒有它,Claude Code 不會恢復計畫模式。需要 Claude Code v2.1.246 或更新版本。
2017
2018 當您使用 `-p` 恢復時,Claude Code 不會恢復任何其他儲存的權限模式。它在新 `claude -p` 執行會啟動的權限模式中啟動執行,因此如果延遲工作階段使用了一個,請再次傳遞 `--permission-mode` 或 `--dangerously-skip-permissions`。當您使用 `claude --resume <session-id>` 恢復而不使用 `-p` 時,Claude Code 會恢復儲存的權限模式,但 [恢復時的權限模式](/docs/zh-TW/sessions#permission-mode-on-resume) 中列出的例外除外。
1694</Note>2019</Note>
1695 2020
1696<h3 id="permissionrequest">2021<h3 id="permissionrequest">
1697 PermissionRequest2022 PermissionRequest
1698</h3>2023</h3>
1699 2024
1700在向使用者顯示權限對話框時執行。使用 [PermissionRequest 決定控制](#permissionrequest-decision-control) 代表使用者允許或拒絕。2025在 Claude Code 即將要求您許可使用工具時執行。在無法顯示提示的工作階段中,例如 [非互動模式](/docs/zh-TW/headless) 中的背景子代理,Claude Code 仍然執行這些 hooks,如果沒有 hook 返回決策,它會拒絕工具呼叫。
2026使用 [PermissionRequest 決策控制](#permissionrequest-decision-control) 代表使用者允許或拒絕。
2027
2028當您需要 Claude 要求許可使用工具時的信號時使用此事件。Claude Code 僅在提示等待約六秒後才執行 [Notification](#notification) hook,其中 `permission_prompt` 類型。
2029
2030Claude Code 不為沙箱命令的 [網路請求](/docs/zh-TW/sandboxing#network-isolation) 執行 PermissionRequest hooks。若要獲得該提示的信號,請使用 `permission_prompt` 通知類型。
1701 2031
1702匹配工具名稱,與 PreToolUse 相同的值。2032在工具名稱上匹配,與 PreToolUse 相同的值。
1703 2033
1704<h4 id="permissionrequest-input">2034<h4 id="permissionrequest-input">
1705 PermissionRequest 輸入2035 PermissionRequest 輸入
1706</h4>2036</h4>
1707 2037
1708PermissionRequest hooks 接收 `tool_name` 和 `tool_input` 欄位,如 PreToolUse hooks,但沒有 `tool_use_id`。可選的 `permission_suggestions` 陣列包含使用者通常在權限對話框中看到的「總是允許」選項。區別在於 hook 何時觸發:PermissionRequest hooks 在權限對話框即將向使用者顯示時執行,而 PreToolUse hooks 在工具執行前執行,無論權限狀態如何。2038PermissionRequest hooks 接收 `tool_name` 和 `tool_input` 欄位,如 PreToolUse hooks,但沒有 `tool_use_id`。對於 MCP 工具,它們也接收 [`mcp_server`](#pretooluse-input) 物件。可選 `permission_suggestions` 陣列包含 Claude Code 為此請求建議的 [權限更新](#permission-update-entries),例如新增允許規則或更改權限模式。
2039
2040`permission_suggestions` 陣列不是您看到的選項的確切清單,因為每個權限對話建立自己的選項。某些對話(例如檔案編輯的對話)根本不讀取陣列,並從請求本身衍生其選項。讀取它的對話仍然可以保留一個選項,其建議保留在陣列中,例如當 [`allowManagedPermissionRulesOnly`](/docs/zh-TW/settings-reference#allowmanagedpermissionrulesonly) 隱藏規則保存選項時。它也可以提供陣列中沒有建議項目的選項,例如 [**是的,並切換到自動模式**](/docs/zh-TW/permission-modes#switch-permission-modes),它直接更改權限模式而不是透過權限更新。
2041
2042PreToolUse hooks 在每個工具呼叫之前執行,無論是否需要權限。PermissionRequest hooks 僅在 Claude Code 即將要求您許可時執行,或當它會以其他方式自動拒絕無法提示的呼叫時執行。兩個事件都不對 [`EndConversation`](/docs/zh-TW/tools-reference#endconversation-tool-behavior) 觸發。
1709 2043
1710```json theme={null}2044```json theme={null}
1711{2045{
1731```2065```
1732 2066
1733<h4 id="permissionrequest-decision-control">2067<h4 id="permissionrequest-decision-control">
1734 PermissionRequest 決定控制2068 PermissionRequest 決策控制
1735</h4>2069</h4>
1736 2070
1737`PermissionRequest` hooks 可以允許或拒絕權限請求。除了所有 hooks 可用的 [JSON 輸出欄位](#json-output) 外,您的 hook 指令碼可以返回一個 `decision` 物件,其中包含這些事件特定欄位:2071`PermissionRequest` hooks 可以允許或拒絕權限請求。除了所有 hooks 可用的 [JSON 輸出欄位](#json-output) 外,您的 hook 指令碼可以返回具有這些事件特定欄位的 `decision` 物件:
1738 2072
1739| 欄位 | 描述 |2073| 欄位 | 描述 |
1740| :------------------- | :------------------------------------------------------------------------------------------------------------------ |2074| :------------------- | :------------------------------------------------------------------------------------------------------------------ |
1741| `behavior` | `"allow"` 授予權限,`"deny"` 拒絕它。[拒絕和詢問規則](/docs/zh-TW/permissions#manage-permissions) 仍然適用,所以返回 `"allow"` 的 hook 不會覆蓋匹配的拒絕規則 |2075| `behavior` | `"allow"` 授予權限,`"deny"` 拒絕。[拒絕和詢問規則](/docs/zh-TW/permissions#manage-permissions) 仍然被評估,因此返回 `"allow"` 的 hook 不會覆寫匹配的拒絕規則 |
1742| `updatedInput` | 僅適用於 `"allow"`:在執行前修改工具的輸入參數。替換整個輸入物件,因此包括未修改的欄位以及修改後的欄位。修改後的輸入會重新評估拒絕和詢問規則 |2076| `updatedInput` | 僅對 `"allow"`:在執行前修改工具的輸入參數。替換整個輸入物件,因此在修改的欄位旁邊包含未變更的欄位。修改的輸入會針對拒絕和詢問規則重新評估 |
1743| `updatedPermissions` | 僅適用於 `"allow"`:應用的 [權限更新項目](#permission-update-entries) 陣列,例如新增允許規則或變更工作階段權限模式 |2077| `updatedPermissions` | 僅對 `"allow"`:[權限更新項目](#permission-update-entries) 陣列以應用,例如新增允許規則或更改工作階段權限模式 |
1744| `message` | 僅適用於 `"deny"`:告訴 Claude 為什麼權限被拒絕 |2078| `message` | 僅對 `"deny"`:告訴 Claude 為什麼權限被拒絕 |
1745| `interrupt` | 僅適用於 `"deny"`:如果為 `true`,停止 Claude |2079| `interrupt` | 僅對 `"deny"`:如果為 `true`,停止 Claude |
2080
2081退出 2 而不帶 `decision` 物件的 hook 保持權限流程不變,其 stderr 被捨棄。只有 `decision` 物件可以授予或拒絕請求。
1746 2082
1747```json theme={null}2083```json theme={null}
1748{2084{
1766 2102
1767| `type` | 欄位 | 效果 |2103| `type` | 欄位 | 效果 |
1768| :------------------ | :------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------- |2104| :------------------ | :------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------- |
1769| `addRules` | `rules`、`behavior`、`destination` | 新增權限規則。`rules` 是 `{toolName, ruleContent?}` 物件的陣列。省略 `ruleContent` 以匹配整個工具。`behavior` 是 `"allow"`、`"deny"` 或 `"ask"` |2105| `addRules` | `rules`、`behavior`、`destination` | 新增權限規則。`rules` 是 `{toolName, ruleContent?}` 物件的陣列。省略 `ruleContent` 以匹配整個工具。`behavior` 為 `"allow"`、`"deny"` 或 `"ask"` |
1770| `replaceRules` | `rules`、`behavior`、`destination` | 用提供的 `rules` 替換 `destination` 處給定 `behavior` 的所有規則 |2106| `replaceRules` | `rules`、`behavior`、`destination` | 將給定 `behavior` 在 `destination` 的所有規則替換為提供的 `rules` |
1771| `removeRules` | `rules`、`behavior`、`destination` | 移除匹配的給定 `behavior` 的規則 |2107| `removeRules` | `rules`、`behavior`、`destination` | 移除給定 `behavior` 的匹配規則 |
1772| `setMode` | `mode`、`destination` | 變更權限模式。有效模式為 `default`、`auto`、`acceptEdits`、`dontAsk`、`bypassPermissions`、`plan` 和 `manual` 作為 `default` 的別名。`manual` 別名需要 Claude Code v2.1.200 或更高版本 |2108| `setMode` | `mode`、`destination` | 更改權限模式。有效模式為 `default`、`auto`、`acceptEdits`、`dontAsk`、`bypassPermissions`、`plan` 和 `manual` 作為 `default` 的別名。`manual` 別名需要 Claude Code v2.1.200 或更新版本 |
1773| `addDirectories` | `directories`、`destination` | 新增工作目錄。`directories` 是路徑字串的陣列 |2109| `addDirectories` | `directories`、`destination` | 新增工作目錄。`directories` 是路徑字串的陣列 |
1774| `removeDirectories` | `directories`、`destination` | 移除工作目錄 |2110| `removeDirectories` | `directories`、`destination` | 移除工作目錄 |
1775 2111
1776<Note>2112<Note>
1777 `setMode` 與 `bypassPermissions` 僅在工作階段已經啟用繞過模式時生效:`--dangerously-skip-permissions`、`--permission-mode bypassPermissions`、`--allow-dangerously-skip-permissions` 或 `permissions.defaultMode: "bypassPermissions"` 在設定中,且模式未被 [`permissions.disableBypassPermissionsMode`](/docs/zh-TW/permissions#managed-settings) 停用。否則更新是無操作。`bypassPermissions` 無論 `destination` 如何都永遠不會被持久化為 `defaultMode`。2113 `setMode` 搭配 `bypassPermissions` 僅在您已啟動工作階段時生效,且繞過模式已可用:`--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) 中啟動時,更新也是無操作。
2114
2115 `bypassPermissions` 無論 `destination` 如何都永遠不會作為 `defaultMode` 保留。
1778</Note>2116</Note>
1779 2117
1780每個項目上的 `destination` 欄位決定變更是保留在記憶體中還是持久化到設定檔。2118每個項目上的 `destination` 欄位決定變更是保留在記憶體中還是保留到設定檔。
1781 2119
1782| `destination` | 寫入 |2120| `destination` | 寫入 |
1783| :---------------- | :---------------------------- |2121| :---------------- | :---------------------------- |
1784| `session` | 僅在記憶體中,工作階段結束時丟棄 |2122| `session` | 僅在記憶體中,工作階段結束時捨棄 |
1785| `localSettings` | `.claude/settings.local.json` |2123| `localSettings` | `.claude/settings.local.json` |
1786| `projectSettings` | `.claude/settings.json` |2124| `projectSettings` | `.claude/settings.json` |
1787| `userSettings` | `~/.claude/settings.json` |2125| `userSettings` | `~/.claude/settings.json` |
1788 2126
1789Hook 可以回顯它接收的 `permission_suggestions` 之一作為其自己的 `updatedPermissions` 輸出,這等同於使用者在對話框中選擇該「總是允許」選項。2127Hook 可以回顯它接收的 `permission_suggestions` 之一作為其自己的 `updatedPermissions` 輸出。
1790 2128
1791<h3 id="posttooluse">2129<h3 id="posttooluse">
1792 PostToolUse2130 PostToolUse
1794 2132
1795在工具成功完成後立即執行。2133在工具成功完成後立即執行。
1796 2134
1797匹配工具名稱,與 PreToolUse 相同的值。2135在工具名稱上匹配,與 PreToolUse 相同的值。
2136
2137當工具名稱不是正確的篩選器時更廣泛地匹配:
2138
2139* 若要在任何工具成功完成後執行 hook,省略 `matcher` 或將其設定為 `"*"`。您的 hook 然後可以自己探索變更的內容,例如執行 `git status --porcelain`,它也列出 `git diff` 遺漏的未追蹤檔案。對於失敗的工具呼叫,在 [PostToolUseFailure](#posttoolusefailure) 下新增相同的 hook。
2140* 若要在特定檔案變更時執行 hook,無論什麼寫入它,請使用 [FileChanged](#filechanged)。當 `Bash` 命令或 Claude Code 外的程序重寫相同檔案時,Claude Code 不執行匹配 `Edit|Write` 的 `PostToolUse` hook。
1798 2141
1799<h4 id="posttooluse-input">2142<h4 id="posttooluse-input">
1800 PostToolUse 輸入2143 PostToolUse 輸入
1801</h4>2144</h4>
1802 2145
1803`PostToolUse` hooks 在工具已經成功執行後觸發。輸入包括 `tool_input`(發送給工具的參數)和 `tool_response`(它返回的結果)。兩者的確切架構取決於工具。2146`PostToolUse` hooks 在工具已成功執行後觸發。輸入包括 `tool_input`(發送給工具的引數)和 `tool_response`(它返回的結果)。兩者的確切架構取決於工具。檔案工具 `tool_input` 路徑以與 [PreToolUse](#pretooluse-input) 相同的格式到達:始終絕對,使用平台的原生分隔符,因此 Windows 上為反斜線。對於 MCP 工具,輸入也攜帶 [`mcp_server`](#pretooluse-input) 物件。
1804 2147
1805```json theme={null}2148```json theme={null}
1806{2149{
1816 },2159 },
1817 "tool_response": {2160 "tool_response": {
1818 "filePath": "/path/to/file.txt",2161 "filePath": "/path/to/file.txt",
1819 "success": true2162 "type": "create"
1820 },2163 },
1821 "tool_use_id": "toolu_01ABC123...",2164 "tool_use_id": "toolu_01ABC123...",
1822 "duration_ms": 122165 "duration_ms": 12
1828| `duration_ms` | 可選。工具執行時間(毫秒)。不包括權限提示和 PreToolUse hooks 中花費的時間 |2171| `duration_ms` | 可選。工具執行時間(毫秒)。不包括權限提示和 PreToolUse hooks 中花費的時間 |
1829 2172
1830<h4 id="posttooluse-decision-control">2173<h4 id="posttooluse-decision-control">
1831 PostToolUse 決定控制2174 PostToolUse 決策控制
1832</h4>2175</h4>
1833 2176
1834`PostToolUse` hooks 可以在工具執行後向 Claude 提供反饋。除了所有 hooks 可用的 [JSON 輸出欄位](#json-output) 外,您的 hook 指令碼可以返回這些事件特定欄位:2177`PostToolUse` hooks 可以在工具執行後提供回饋給 Claude。除了所有 hooks 可用的 [JSON 輸出欄位](#json-output) 外,您的 hook 指令碼可以返回這些事件特定欄位:
1835 2178
1836| 欄位 | 描述 |2179| 欄位 | 描述 |
1837| :--------------------- | :----------------------------------------------------------------------------- |2180| :--------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
1838| `decision` | `"block"` 提示 Claude 使用 `reason`。Claude 仍然看到原始輸出;要替換它,請使用 `updatedToolOutput` |2181| `decision` | `"block"` 在工具結果旁邊新增 `reason`。Claude 仍然看到原始輸出;若要替換它,請使用 `updatedToolOutput` |
1839| `reason` | 當 `decision` 為 `"block"` 時向 Claude 顯示的解釋 |2182| `reason` | 當 `decision` 為 `"block"` 時顯示給 Claude 的解釋 |
1840| `additionalContext` | 新增到 Claude 上下文的字串,與工具結果一起。請參閱 [為 Claude 新增上下文](#add-context-for-claude) |2183| `additionalContext` | 與工具結果一起新增到 Claude 背景資訊的字串。請參閱 [為 Claude 新增背景資訊](#add-context-for-claude) |
1841| `updatedToolOutput` | 在將工具的輸出發送給 Claude 之前,用提供的值替換它。該值必須符合工具的輸出形狀 |2184| `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 或更新版本 |
1842| `updatedMCPToolOutput` | 僅適用於 [MCP 工具](#match-mcp-tools):用提供的值替換工具的輸出。優先使用 `updatedToolOutput`,它適用於所有工具 |2185| `updatedToolOutput` | 在發送給 Claude 之前用提供的值替換工具的輸出。該值必須符合工具的輸出形狀 |
2186| `updatedMCPToolOutput` | 僅替換 [MCP 工具](#match-mcp-tools) 的輸出。優先使用 `updatedToolOutput`,它適用於所有工具 |
1843 2187
1844下面的範例替換 `Bash` 呼叫的輸出。替換值符合 `Bash` 工具的輸出形狀:2188下面的範例替換 `Bash` 呼叫的輸出。替換值符合 `Bash` 工具的輸出形狀:
1845 2189
1859```2203```
1860 2204
1861<Warning>2205<Warning>
1862 `updatedToolOutput` 僅改變 Claude 看到的內容。工具已經在 hook 觸發時執行,因此任何寫入的檔案、執行的命令或發送的網路請求都已生效。遙測(如 OpenTelemetry 工具跨度和分析事件)也會在 hook 執行前捕獲原始輸出。要在執行前防止或修改工具呼叫,請改用 [PreToolUse](#pretooluse) hook。2206 `updatedToolOutput` 僅更改 Claude 看到的內容。工具已在 hook 觸發時執行,因此任何寫入的檔案、執行的命令或發送的網路請求已生效。遙測(例如 OpenTelemetry 工具跨度和分析事件)也會在 hook 執行前捕獲原始輸出。若要在執行前防止或修改工具呼叫,請改用 [PreToolUse](#pretooluse) hook。
2207
2208 替換值必須符合工具的輸出形狀。內建工具返回結構化物件而不是純字串。例如,`Bash` 返回具有 `stdout`、`stderr`、`interrupted` 和 `isImage` 欄位的物件。對於內建工具,不符合工具輸出架構的值會被忽略,使用原始輸出。MCP 工具輸出通過而不進行架構驗證。去除 Claude 需要的錯誤詳細資訊可能導致它在錯誤假設上進行。
2209</Warning>
2210
2211<h4 id="annotate-a-result-for-the-auto-mode-classifier">
2212 為自動模式分類器註釋結果
2213</h4>
2214
2215返回 `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 或更新版本。
2216
2217下面的範例告訴分類器查詢的輸出來自何處:
2218
2219```json theme={null}
2220{
2221 "hookSpecificOutput": {
2222 "hookEventName": "PostToolUse",
2223 "classifierContext": "This query ran against the staging database, not production."
2224 }
2225}
2226```
2227
2228分類器給予說明的權重取決於您設定 hook 的位置:
1863 2229
1864 替換值必須符合工具的輸出形狀。內建工具返回結構化物件而不是純字串。例如,`Bash` 返回一個具有 `stdout`、`stderr`、`interrupted` 和 `isImage` 欄位的物件。對於內建工具,不符合工具輸出架構的值會被忽略,並使用原始輸出。MCP 工具輸出通過而不進行架構驗證。去除 Claude 需要的錯誤詳細資訊可能會導致它在錯誤的假設下進行。2230* **在 Claude Code 中設定的 Hooks**:對於來自設定檔、外掛、skills 和代理 frontmatter 的 hooks,分類器將說明視為未驗證的應用程式提供的背景資訊。說明永遠不會建立使用者意圖,如果它聲稱您核准或請求了某事,分類器會根據您在對話中的自己訊息檢查該聲明
2231* **進程內 Agent SDK 回呼**:當應用程式嵌入 Claude Code 將 hook 註冊為 [TypeScript SDK 回呼](/docs/zh-TW/agent-sdk/hooks) 並在即時工作階段期間返回說明時,分類器可能會將使用者陳述(在說明中轉達)視為使用者意圖。這樣的陳述可以滿足分類器會接受來自您發送的訊息的同意要求,但它永遠不會解除您自己的訊息也無法解除的阻止。工作階段恢復後,Claude Code 將恢復的說明視為未驗證的背景資訊。當兩個群組的 hooks 註釋相同呼叫時,分類器將組合說明視為未驗證
2232
2233Claude Code 在傳遞說明時應用這些限制:
2234
2235* **長度**:Claude Code 將一個工具呼叫的說明上限設定為 2,000 個字元,並截斷其餘部分。上限在回應該呼叫的每個 hook 中共享
2236* **僅同步回應**:Claude Code 忽略 [在背景執行](#run-hooks-in-the-background) 的 hook 回應中的欄位,因為該回應在 Claude Code 記錄工具結果後到達
2237* **分類器不記錄的呼叫**:分類器的文字記錄省略唯讀查詢,例如檔案讀取和搜尋。Claude Code 捨棄附加到其中一個呼叫的說明
2238* **與重寫的互動**:當說明描述您使用 `updatedToolOutput` 替換的輸出時,在相同的 hook 回應中返回兩個欄位。如果該重寫被拒絕或另一個 hook 的重寫替換它,Claude Code 會捨棄說明。Claude Code 傳遞您返回的說明而不進行重寫,即使另一個 hook 重寫輸出
2239
2240<Warning>
2241 分類器將您放在 `classifierContext` 中的內容讀取為來自託管工作階段的應用程式的資訊,因此不要將不受信任的工具輸出或第三方文字複製到其中。將說明保持為關於此一個呼叫的簡短聲明,例如關於其來源的事實或使用者關於它的陳述;不要使用欄位傳遞不相關的訊息或事件流。
1865</Warning>2242</Warning>
1866 2243
1867<h3 id="posttoolusefailure">2244<h3 id="posttoolusefailure">
1868 PostToolUseFailure2245 PostToolUseFailure
1869</h3>2246</h3>
1870 2247
1871當工具執行失敗時執行:工具拋出錯誤,或 MCP 工具返回錯誤結果。使用此項來記錄失敗、發送警報或向 Claude 提供更正反饋。2248在啟動執行的工具失敗時執行:工具拋出錯誤,或 MCP 工具返回錯誤結果。使用此來記錄失敗、發送警報或向 Claude 提供更正回饋。
1872 2249
1873匹配工具名稱,與 PreToolUse 相同的值。2250在工具名稱上匹配,與 PreToolUse 相同的值。
1874 2251
1875<Note>2252<Note>
1876 此事件不針對執行前被拒絕的工具呼叫觸發:未知工具名稱、輸入失敗架構或工具特定驗證,或權限拒絕。驗證拒絕作為 `tool_use_error` 結果返回,在 hooks 執行前發生,因此它們既不觸發 `PreToolUse` 也不觸發此事件。權限拒絕觸發 `PreToolUse` 但不觸發此事件;請參閱 [PermissionDenied](#permissiondenied)。2253 此事件不對執行前被拒絕的工具呼叫觸發:未知工具名稱、失敗架構或工具特定驗證的輸入,或權限拒絕。驗證拒絕作為 `tool_use_error` 結果返回,在 hooks 執行前發生,因此它們既不觸發 `PreToolUse` 也不觸發此事件。權限拒絕觸發 `PreToolUse` 但不觸發此事件;請參閱 [PermissionDenied](#permissiondenied)。
1877</Note>2254</Note>
1878 2255
1879<h4 id="posttoolusefailure-input">2256<h4 id="posttoolusefailure-input">
1880 PostToolUseFailure 輸入2257 PostToolUseFailure 輸入
1881</h4>2258</h4>
1882 2259
1883PostToolUseFailure hooks 接收與 PostToolUse 相同的 `tool_name` 和 `tool_input` 欄位,以及作為頂層欄位的錯誤資訊:2260PostToolUseFailure hooks 接收與 PostToolUse 相同的 `tool_name` 和 `tool_input` 欄位,以及作為頂級欄位的錯誤資訊。對於 MCP 工具,它們也接收 [`mcp_server`](#pretooluse-input) 物件。例如,失敗的 `npm test` 命令可能傳遞:
1884 2261
1885```json theme={null}2262```json theme={null}
1886{2263{
1895 "description": "Run test suite"2272 "description": "Run test suite"
1896 },2273 },
1897 "tool_use_id": "toolu_01ABC123...",2274 "tool_use_id": "toolu_01ABC123...",
1898 "error": "Command exited with non-zero status code 1",2275 "error": "Exit code 1\nError: Cannot find module 'express'",
1899 "is_interrupt": false,2276 "is_interrupt": false,
1900 "duration_ms": 41872277 "duration_ms": 4187
1901}2278}
1902```2279```
1903 2280
1904| 欄位 | 描述 |2281| 欄位 | 描述 |
1905| :------------- | :--------------------------------------------- |2282| :------------- | :------------------------------------------------------------------------- |
1906| `error` | 描述出錯的字串 |2283| `error` | 描述出錯內容的字串。格式取決於失敗的工具 |
1907| `is_interrupt` | 可選的布林值,指示失敗是否由使用者中斷引起 |2284| `is_interrupt` | 可選布林值。當失敗作為中止而不是工具報告的錯誤到達 Claude Code 時為 True。取消執行中的工具不觸發此 hook;工具結果攜帶中斷訊息 |
1908| `duration_ms` | 可選。工具執行時間(毫秒)。不包括權限提示和 PreToolUse hooks 中花費的時間 |2285| `duration_ms` | 可選。工具執行時間(毫秒)。不包括權限提示和 PreToolUse hooks 中花費的時間 |
1909 2286
2287`error` 字串通常是 Claude 作為失敗工具結果接收的相同文字。其格式因工具和失敗而異。根據 `tool_name`、`is_interrupt` 和第一行 `Exit code N` 鍵入您的 hook;將字串的其餘部分視為顯示文字,而不是穩定格式。
2288
2289* 對於 Bash 和 PowerShell,執行並退出的命令產生第一行 `Exit code N`,然後是命令產生的任何輸出作為一個區塊,其中 stdout 和 stderr 交錯
2290* 有效負載也可能攜帶裸失敗訊息,沒有退出代碼行,當 Claude Code 無法啟動 shell 程序本身時
2291* Claude Code 在 `... [N characters truncated] ...` 標記周圍中間截斷長字串,並可以插入自己的行,例如 `Command timed out after 2m 0s`
2292
1910<h4 id="posttoolusefailure-decision-control">2293<h4 id="posttoolusefailure-decision-control">
1911 PostToolUseFailure 決定控制2294 PostToolUseFailure 決策控制
1912</h4>2295</h4>
1913 2296
1914`PostToolUseFailure` hooks 可以在工具失敗後向 Claude 提供上下文。除了所有 hooks 可用的 [JSON 輸出欄位](#json-output) 外,您的 hook 指令碼可以返回這些事件特定欄位:2297`PostToolUseFailure` hooks 可以在工具失敗後向 Claude 提供背景資訊。除了所有 hooks 可用的 [JSON 輸出欄位](#json-output) 外,您的 hook 指令碼可以返回這些事件特定欄位:
1915 2298
1916| 欄位 | 描述 |2299| 欄位 | 描述 |
1917| :------------------ | :-------------------------------------------------------------------- |2300| :------------------ | :--------------------------------------------------------------------- |
1918| `additionalContext` | 新增到 Claude 上下文的字串,與錯誤一起。請參閱 [為 Claude 新增上下文](#add-context-for-claude) |2301| `additionalContext` | 與錯誤一起新增到 Claude 背景資訊的字串。請參閱 [為 Claude 新增背景資訊](#add-context-for-claude) |
1919 2302
1920```json theme={null}2303```json theme={null}
1921{2304{
1930 PostToolBatch2313 PostToolBatch
1931</h3>2314</h3>
1932 2315
1933在批次中的每個工具呼叫都已解決後執行一次,在 Claude Code 向模型發送下一個請求之前。`PostToolUse` 每個工具執行一次,這意味著當 Claude 進行平行工具呼叫時它並發執行。`PostToolBatch` 恰好執行一次,包含完整批次,因此它是注入取決於執行的工具集而不是任何單一工具的上下文的正確位置。此事件沒有匹配器。2316在批次中的每個工具呼叫都已解決後執行一次,在 Claude Code 發送下一個請求給模型之前。`PostToolUse` 每個工具執行一次,這意味著當 Claude 進行平行工具呼叫時它並發執行。`PostToolBatch` 恰好執行一次,包含完整批次,因此它是注入取決於執行的工具集而不是任何單個工具的背景資訊的正確位置。此事件沒有匹配器。
1934 2317
1935<h4 id="posttoolbatch-input">2318<h4 id="posttoolbatch-input">
1936 PostToolBatch 輸入2319 PostToolBatch 輸入
1937</h4>2320</h4>
1938 2321
1939除了 [通用輸入欄位](#common-input-fields) 外,PostToolBatch hooks 還接收 `tool_calls`,一個描述批次中每個工具呼叫的陣列:2322除了 [常見輸入欄位](#common-input-fields) 外,PostToolBatch hooks 還會接收 `tool_calls`,一個描述批次中每個工具呼叫的陣列:
1940 2323
1941```json theme={null}2324```json theme={null}
1942{2325{
1962}2345}
1963```2346```
1964 2347
1965`tool_response` 包含與模型在相應 `tool_result` 塊中接收的內容相同的內容。該值是序列化的字串或內容塊陣列,完全如工具發出的那樣。對於 `Read`,這意味著行號前綴的文字而不是原始檔案內容。回應可能很大,因此僅解析您需要的欄位。2348`tool_response` 包含模型在對應 `tool_result` 區塊中接收的相同內容。該值是序列化字串或內容區塊陣列,完全如工具發出的一樣。對於 `Read`,這意味著行號前綴文字而不是原始檔案內容。回應可能很大,因此僅解析您需要的欄位。
1966 2349
1967<Note>2350<Note>
1968 `tool_response` 形狀與 `PostToolUse` 的不同。`PostToolUse` 傳遞工具的結構化 `Output` 物件,例如 `Write` 的 `{filePath: "...", success: true}`;`PostToolBatch` 傳遞序列化的 `tool_result` 內容模型看到的。2351 `tool_response` 形狀與 `PostToolUse` 的不同。`PostToolUse` 傳遞工具的結構化 `Output` 物件,例如 `Write` 的 `{filePath: "...", type: "create"}`;`PostToolBatch` 傳遞模型看到的序列化 `tool_result` 內容。
1969</Note>2352</Note>
1970 2353
1971<h4 id="posttoolbatch-decision-control">2354<h4 id="posttoolbatch-decision-control">
1972 PostToolBatch 決定控制2355 PostToolBatch 決策控制
1973</h4>2356</h4>
1974 2357
1975`PostToolBatch` hooks 可以為 Claude 注入上下文。除了所有 hooks 可用的 [JSON 輸出欄位](#json-output) 外,您的 hook 指令碼可以返回這些事件特定欄位:2358`PostToolBatch` hooks 可以為 Claude 注入背景資訊。除了所有 hooks 可用的 [JSON 輸出欄位](#json-output) 外,您的 hook 指令碼可以返回這些事件特定欄位:
1976 2359
1977| 欄位 | 描述 |2360| 欄位 | 描述 |
1978| :------------------ | :------------------------------------------------------------------------------------------------------ |2361| :------------------ | :------------------------------------------------------------------------------------------------------ |
1979| `additionalContext` | 在下一個模型呼叫之前注入一次的上下文字串。請參閱 [為 Claude 新增上下文](#add-context-for-claude) 以了解傳遞詳細資訊、要放入其中的內容,以及恢復的工作階段如何處理過去的值 |2362| `additionalContext` | 在下一個模型呼叫之前注入一次的背景資訊字串。請參閱 [為 Claude 新增背景資訊](#add-context-for-claude),了解傳遞詳細資訊、要放入其中的內容以及恢復的工作階段如何處理過去的值 |
1980 2363
1981```json theme={null}2364```json theme={null}
1982{2365{
1987}2370}
1988```2371```
1989 2372
1990返回 `decision: "block"` 或 `continue: false` 在下一個模型呼叫之前停止代理迴圈。2373返回 `decision: "block"` 或 `continue: false` 在下一個模型呼叫之前停止代理迴圈。阻止訊息來自 JSON `reason` 或 `stopReason`,或來自退出 2 時的 stderr。您在文字記錄中看到它作為警告,它保留在對話中,因此 Claude 在對話繼續時看到它。
1991 2374
1992<h3 id="permissiondenied">2375<h3 id="permissiondenied">
1993 PermissionDenied2376 PermissionDenied
1994</h3>2377</h3>
1995 2378
1996當 [自動模式](/docs/zh-TW/permission-modes#eliminate-prompts-with-auto-mode) 分類器拒絕工具呼叫時執行。此 hook 僅在自動模式中觸發:當您手動拒絕權限對話框、當 `PreToolUse` hook 阻止呼叫或當 `deny` 規則匹配時,它不執行。使用它來記錄分類器拒絕、調整配置或告訴模型它可能重試工具呼叫。2379在 [自動模式](/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` 規則匹配時不執行。使用它來記錄拒絕、調整設定或告訴模型它可能重試工具呼叫。
1997 2380
1998匹配工具名稱,與 PreToolUse 相同的值。2381在工具名稱上匹配,與 PreToolUse 相同的值。
1999 2382
2000<h4 id="permissiondenied-input">2383<h4 id="permissiondenied-input">
2001 PermissionDenied 輸入2384 PermissionDenied 輸入
2002</h4>2385</h4>
2003 2386
2004除了 [通用輸入欄位](#common-input-fields) 外,PermissionDenied hooks 還接收 `tool_name`、`tool_input`、`tool_use_id` 和 `reason`。2387除了 [常見輸入欄位](#common-input-fields) 外,PermissionDenied hooks 還會接收 `tool_name`、`tool_input`、`tool_use_id` 和 `reason`。對於 MCP 工具,它們也接收 [`mcp_server`](#pretooluse-input) 物件。
2005 2388
2006```json theme={null}2389```json theme={null}
2007{2390{
2016 "description": "Clean build directory"2399 "description": "Clean build directory"
2017 },2400 },
2018 "tool_use_id": "toolu_01ABC123...",2401 "tool_use_id": "toolu_01ABC123...",
2019 "reason": "Auto mode denied: command targets a path outside the project"2402 "reason": "[Irreversible Local Destruction]"
2020}2403}
2021```2404```
2022 2405
2023| 欄位 | 描述 |2406| 欄位 | 描述 |
2024| :------- | :-------------- |2407| :------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
2025| `reason` | 分類器拒絕工具呼叫的原因的解釋 |2408| `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` |
2026 2409
2027<h4 id="permissiondenied-decision-control">2410<h4 id="permissiondenied-decision-control">
2028 PermissionDenied 決定控制2411 PermissionDenied 決策控制
2029</h4>2412</h4>
2030 2413
2031PermissionDenied hooks 可以告訴模型它可能重試被拒絕的工具呼叫。返回一個 JSON 物件,其中 `hookSpecificOutput.retry` 設定為 `true`:2414PermissionDenied hooks 可以告訴模型它可能重試被拒絕的工具呼叫。返回一個 JSON 物件,其中 `hookSpecificOutput.retry` 設定為 `true`:
2039}2422}
2040```2423```
2041 2424
2042當 `retry` 為 `true` 時,Claude Code 向對話新增一條訊息,告訴模型它可能重試工具呼叫。拒絕本身不被反轉。如果您的 hook 不返回 JSON,或返回 `retry: false`,拒絕成立,模型接收原始拒絕訊息。2425當 `retry` 為 `true` 時,Claude Code 向對話新增一條訊息,告訴模型它可能重試工具呼叫。Claude Code 不反轉拒絕本身。如果您的 hook 不返回 JSON 或返回 `retry: false`,拒絕成立,模型接收原始拒絕訊息。
2426
2427當分類器對動作 [沒有判決](/docs/zh-TW/errors#auto-mode-cannot-determine-the-safety-of-an-action) 時,Claude Code 忽略 `retry: true`:其回應未解析,或與自動模式分開的安全檢查拒絕了分類器自己的請求。對於這些拒絕,Claude Code 已經在拒絕訊息中告訴模型是否稍後重試或繼續。
2043 2428
2044<h3 id="notification">2429<h3 id="notification">
2045 Notification2430 Notification
2046</h3>2431</h3>
2047 2432
2048當 Claude Code 發送通知時執行。匹配通知類型。省略匹配器以針對所有通知類型執行 hooks。2433在 Claude Code 發送通知時執行。在通知類型上匹配。省略匹配器以對所有通知類型執行 hooks。
2434
2435即使桌面通知已關閉,您也會接收這些 hook 事件:`preferredNotifChannel` 設定(包括 `notifications_disabled`)僅更改您如何被警報,而不是您的 hook 是否執行。
2049 2436
2050| 匹配器 | 何時觸發 |2437| 匹配器 | 何時觸發 |
2051| :--------------------- | :---------------------------------------------------------- |2438| :--------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
2052| `permission_prompt` | Claude 需要您批准工具使用 |2439| `permission_prompt` | Claude 需要您核准工具使用或沙箱命令的 [網路請求](/docs/zh-TW/sandboxing#network-isolation),提示已等待約六秒 |
2053| `idle_prompt` | Claude 完成並等待您的下一個提示 |2440| `idle_prompt` | Claude 約 60 秒前完成回應,您自那以後未輸入 |
2054| `auth_success` | 驗證完成 |2441| `auth_success` | 驗證完成 |
2055| `elicitation_dialog` | MCP 伺服器開啟徵詢表單 |2442| `elicitation_dialog` | MCP 伺服器開啟引出表單,您約六秒未輸入 |
2056| `elicitation_complete` | MCP 徵詢表單被提交或關閉 |2443| `elicitation_url_dialog` | MCP 伺服器要求您開啟瀏覽器 URL,您約六秒未輸入 |
2057| `elicitation_response` | MCP 徵詢回應被發送回伺服器 |2444| `elicitation_complete` | MCP 伺服器報告 [URL 模式引出](#elicitation-input) 完成 |
2058| `agent_needs_input` | 背景工作階段開始等待您的輸入。僅在 [agent view](/docs/zh-TW/agent-view) 在終端中開啟時觸發 |2445| `elicitation_response` | MCP 引出回應發送回伺服器 |
2059| `agent_completed` | 背景工作階段完成或失敗。僅在 [agent view](/docs/zh-TW/agent-view) 在終端中開啟時觸發 |2446| `agent_needs_input` | 背景工作階段在 [代理檢視](/docs/zh-TW/agent-view) 在終端中開啟時開始等待您的輸入,或目前工作階段詢問您 [代理團隊隊友的終端設定問題](/docs/zh-TW/agent-teams#choose-a-display-mode),您約六秒未輸入 |
2447| `agent_completed` | 背景工作階段完成或失敗。僅在 [代理檢視](/docs/zh-TW/agent-view) 在終端中開啟時觸發 |
2448| `quota_auto_resume_fired` | Claude Code 在 claude.ai 使用限制暫停後繼續您的任務:在重設時,或更早當您在 Claude Code 中執行某事時,例如新增使用額度、升級計畫或切換模型,使使用可用,搭配 [模型設定例外](/docs/zh-TW/interactive-mode#wait-for-a-usage-limit-to-reset) |
2449| `quota_auto_resume_stale` | claude.ai 使用限制在您的電腦睡眠超過約 30 分鐘時重設。Claude Code 等待您按 `Enter` 而不是繼續。睡眠較短後它繼續並改為觸發 `quota_auto_resume_fired` |
2450| `quota_auto_resume_disabled` | Claude Code 結束其對 claude.ai 使用限制的等待而不繼續您的任務:[`autoContinueAtUsageLimit`](/docs/zh-TW/settings-reference#autocontinueatusagelimit) 關閉或重設在 Claude Code 啟動的等待期間移動超過 24 小時,繼續的任務持續命中限制,或繼續在到達模型之前被阻止。當您按 `Esc` 或 `Ctrl+C` 或選擇 **不要自動繼續** 時不觸發 |
2451
2452`agent_needs_input` 和 `agent_completed` 類型需要 Claude Code v2.1.198 或更新版本。
2453
2454`quota_auto_resume_fired`、`quota_auto_resume_stale` 和 `quota_auto_resume_disabled` 類型需要 Claude Code v2.1.234 或更新版本。
2455
2456在終端工作階段中,沙箱命令的網路請求的 `permission_prompt` 需要 Claude Code v2.1.246 或更新版本。
2060 2457
2061`agent_needs_input` 和 `agent_completed` 類型需要 Claude Code v2.1.198 或更高版本。2458隊友終端設定問題的 `agent_needs_input` 需要 Claude Code v2.1.248 或更新版本。
2062 2459
2063使用單獨的匹配器根據通知類型執行不同的處理程式。此配置在 Claude 需要權限批准時觸發權限特定的警報指令碼,在 Claude 閒置時觸發不同的通知:2460<Note>
2461 `permission_prompt`、`idle_prompt`、`elicitation_dialog` 和 `elicitation_url_dialog` 類型與桌面通知共享其計時,因此在終端工作階段中您僅在您似乎遠離終端時看到它們:
2462
2463 * 期望 `permission_prompt` 一旦您約六秒未輸入。計時器在權限提示出現時啟動,每次按鍵都會延遲它。若要在 Claude 要求許可使用工具時立即執行 hook,請改用 [PermissionRequest](#permissionrequest)。
2464 * 期望 `idle_prompt` 約 60 秒後 Claude 完成回應,且僅在您自那以後未輸入時。Claude Code 在等待 claude.ai 使用限制重設時不發送 `idle_prompt`。等待結束時,其中一個 `quota_auto_resume_*` 類型改為觸發。
2465 * 期望 `elicitation_dialog` 用於引出表單,或 `elicitation_url_dialog` 用於瀏覽器 URL 請求,一旦您約六秒未輸入。兩者共享與 `permission_prompt` 相同的六秒閘門:計時器在對話出現時啟動,每次按鍵都會延遲它。
2466
2467 在另一個對話在螢幕上時到達的權限請求或引出保持相同的六秒閘門,從請求到達時計時。其通知可以在請求仍在開啟對話後面等待時到達您。
2468</Note>
2469
2470Claude Code 在發送權限請求給 Agent SDK 的 [`canUseTool` 回呼](/docs/zh-TW/agent-sdk/user-input) 的工作階段中以不同方式計時 `permission_prompt`,這是 Claude Desktop 和 VS Code 擴充功能託管 Claude Code 的方式:
2471
2472* 期望 `permission_prompt` 約六秒後 Claude 要求許可。Claude Code 在您輸入時不延遲它。
2473* 如果您或 [PermissionRequest](#permissionrequest) hook 更早回答,Claude Code 不執行 `permission_prompt`。
2474* 設定 [`CLAUDE_CODE_DISABLE_PERMISSION_PROMPT_NOTIFY_HOOKS`](/docs/zh-TW/env-vars) 為 `1` 以在這些工作階段中關閉 `permission_prompt`。
2475
2476在 v2.1.233 之前,`permission_prompt` 在這些工作階段中不觸發。
2477
2478使用單獨的匹配器根據通知類型執行不同的處理程式。此設定在 Claude 需要權限核准時觸發權限特定警報指令碼,在 Claude 閒置時觸發不同的通知:
2064 2479
2065```json theme={null}2480```json theme={null}
2066{2481{
2093 Notification 輸入2508 Notification 輸入
2094</h4>2509</h4>
2095 2510
2096除了 [通用輸入欄位](#common-input-fields) 外,Notification hooks 還接收包含通知文字的 `message`、可選的 `title` 和指示哪個類型觸發的 `notification_type`。2511除了 [常見輸入欄位](#common-input-fields) 外,Notification hooks 還會接收 `message` 搭配通知文字、可選 `title` 和 `notification_type` 指示哪個類型觸發。
2097 2512
2098```json theme={null}2513```json theme={null}
2099{2514{
2107}2522}
2108```2523```
2109 2524
2110Notification hooks 無法阻止或修改通知。它們用於副作用,例如將通知轉發到外部服務。[通用 JSON 輸出欄位](#json-output)(例如 `systemMessage`)適用。2525Notification hooks 無法阻止或修改通知。Claude Code 捨棄它們的 `systemMessage` 和 `continue` 欄位,但仍然發出 [`terminalSequence`](#emit-terminal-notifications),這是桌面通知範例所依賴的。Notification hooks 用於副作用,例如將通知轉發到外部服務。
2111 2526
2112<h3 id="subagentstart">2527<h3 id="subagentstart">
2113 SubagentStart2528 SubagentStart
2114</h3>2529</h3>
2115 2530
2116當通過 Agent 工具生成 Claude Code subagent 時執行。支援匹配器以按代理類型名稱篩選。對於內建代理,這是代理名稱,如 `general-purpose`、`Explore` 或 `Plan`。對於 [自訂 subagents](/docs/zh-TW/sub-agents),這是代理 frontmatter 中的 `name` 欄位,而不是檔案名稱。2531在 Claude 使用 Agent 工具生成子代理時執行,當 Claude [恢復子代理](/docs/zh-TW/sub-agents#resume-subagents) 時,以及每次進程內 [代理團隊](/docs/zh-TW/agent-teams) 隊友處理新訊息時執行。支援匹配器以按代理類型名稱篩選。對於內建代理,這是代理名稱,例如 `general-purpose`、`Explore` 或 `Plan`。對於 [自訂子代理](/docs/zh-TW/sub-agents),這是代理 frontmatter 中的 `name` 欄位,而不是檔案名稱。
2117 2532
2118對於由 [plugin](/docs/zh-TW/plugins) 提供的 subagents,代理類型是外掛程式範圍的識別碼,例如 `my-plugin:reviewer`,而不是裸露的 frontmatter 名稱。冒號將外掛程式範圍的名稱放在正規表達式路徑上,因此使用 `^` 和 `$` 錨定匹配器以進行精確匹配:`^my-plugin:reviewer$`。2533對於由 [外掛](/docs/zh-TW/plugins) 提供的子代理,代理類型是外掛範圍識別碼,例如 `my-plugin:reviewer`,而不是裸 frontmatter 名稱。冒號將外掛範圍名稱放在正規表達式路徑上,因此使用 `^` 和 `$` 錨定匹配器以進行精確匹配:`^my-plugin:reviewer$`。
2119 2534
2120<h4 id="subagentstart-input">2535<h4 id="subagentstart-input">
2121 SubagentStart 輸入2536 SubagentStart 輸入
2122</h4>2537</h4>
2123 2538
2124除了 [通用輸入欄位](#common-input-fields) 外,SubagentStart hooks 還接收 `agent_id`(subagent 的唯一識別碼)和 `agent_type`(代理名稱,匹配器篩選的值)。2539除了 [常見輸入欄位](#common-input-fields) 外,SubagentStart hooks 還會接收 `agent_id` 搭配子代理的唯一識別碼和 `agent_type` 搭配匹配器篩選的代理名稱。
2125 2540
2126```json theme={null}2541```json theme={null}
2127{2542{
2134}2549}
2135```2550```
2136 2551
2137SubagentStart hooks 無法阻止 subagent 建立,但它們可以將上下文注入到 subagent 中。除了所有 hooks 可用的 [JSON 輸出欄位](#json-output) 外,您可以返回:2552SubagentStart hooks 無法阻止子代理建立,但它們可以將背景資訊注入到子代理中。除了所有 hooks 可用的 [JSON 輸出欄位](#json-output) 外,您可以返回:
2138 2553
2139| 欄位 | 描述 |2554| 欄位 | 描述 |
2140| :------------------ | :----------------------------------------------------------------------------- |2555| :------------------ | :----------------------------------------------------------------------------- |
2141| `additionalContext` | 新增到 subagent 上下文開始處的字串,在其第一個提示之前。請參閱 [為 Claude 新增上下文](#add-context-for-claude) |2556| `additionalContext` | 在子代理對話開始時、其第一個提示之前新增到子代理背景資訊的字串。請參閱 [為 Claude 新增背景資訊](#add-context-for-claude) |
2142 2557
2143```json theme={null}2558```json theme={null}
2144{2559{
2149}2564}
2150```2565```
2151 2566
2567當 hook 再次為相同子代理執行時,Claude Code 僅在子代理的背景資訊還不包含早期執行副本時注入返回的背景資訊。在啟動時注入的副本保留在位置,保持子代理的 [prompt cache](/docs/zh-TW/prompt-caching#subagents-and-the-cache) 完整。在 [自動壓縮](/docs/zh-TW/sub-agents#auto-compaction) 捨棄該副本後,Claude Code 在下一次執行時再次注入背景資訊。
2568
2152<h3 id="subagentstop">2569<h3 id="subagentstop">
2153 SubagentStop2570 SubagentStop
2154</h3>2571</h3>
2155 2572
2156當 Claude Code subagent 完成回應時執行。匹配代理類型,與 SubagentStart 相同的值。2573在 Claude Code 子代理完成回應時執行。在代理類型上匹配,與 SubagentStart 相同的值。
2157 2574
2158<h4 id="subagentstop-input">2575<h4 id="subagentstop-input">
2159 SubagentStop 輸入2576 SubagentStop 輸入
2160</h4>2577</h4>
2161 2578
2162除了 [通用輸入欄位](#common-input-fields) 外,SubagentStop hooks 還接收 `stop_hook_active`、`agent_id`、`agent_type`、`agent_transcript_path` 和 `last_assistant_message`。`agent_type` 欄位是用於匹配器篩選的值。`transcript_path` 是主工作階段的成績單,而 `agent_transcript_path` 是 subagent 自己的成績單,存儲在嵌套的 `subagents/` 資料夾中。`last_assistant_message` 欄位包含 subagent 最終回應的文字內容,因此 hooks 可以存取它而無需解析成績單檔案。2579除了 [常見輸入欄位](#common-input-fields) 外,SubagentStop hooks 還會接收 `stop_hook_active`、`agent_id`、`agent_type`、`agent_transcript_path` 和 `last_assistant_message`。`agent_type` 欄位是用於匹配器篩選的值。`transcript_path` 是主工作階段的文字記錄,而 `agent_transcript_path` 是子代理自己的文字記錄,儲存在巢狀 `subagents/` 資料夾中。`last_assistant_message` 欄位包含子代理最終回應的文字內容,因此 hooks 可以存取它而不解析文字記錄檔案。
2580
2581在 Claude Code v2.1.271 或更新版本上,使用 [`SubagentHandback`](/docs/zh-TW/tools-reference) 工具執行的子代理在停止之前透過該工具傳遞其報告。`last_assistant_message` 欄位然後保留子代理的結束文字(如果有),這不是傳遞的報告。報告是該呼叫的 `message` 輸入,`PreToolUse` 或 `PostToolUse` hook 在 `SubagentHandback` 上匹配時接收為 `tool_input.message`。
2163 2582
2164SubagentStop hooks 也接收 [Stop 輸入](#stop-input) 中描述的 `background_tasks` 和 `session_crons` 陣列,在 Claude Code v2.1.145 或更高版本中可用。兩個陣列都限定於父工作階段,而不是 subagent。2583SubagentStop hooks 也接收 [Stop 輸入](#stop-input) 下描述的 `background_tasks` 和 `session_crons` 陣列。兩個陣列的範圍是父工作階段,而不是子代理。
2165 2584
2166```json theme={null}2585```json theme={null}
2167{2586{
2180}2599}
2181```2600```
2182 2601
2183SubagentStop hooks 使用與 [Stop hooks](#stop-decision-control) 相同的決定控制格式,包括 `hookSpecificOutput.additionalContext`,其中 `hookEventName` 設定為 `"SubagentStop"`,用於非錯誤反饋,使 subagent 保持執行。返回 `decision: "block"` 與 `reason` 會保持 subagent 執行並將 `reason` 作為其下一個指令傳遞給 subagent。要在 subagent 返回後將上下文注入到父工作階段,請改用 `Agent` 工具上的 [`PostToolUse`](#posttooluse) hook。2602SubagentStop hooks 使用與 [Stop hooks](#stop-decision-control) 相同的決策控制格式,包括 `hookSpecificOutput.additionalContext` 搭配 `hookEventName` 設定為 `"SubagentStop"`,用於保持子代理執行的非錯誤回饋。返回 `decision: "block"` 搭配 `reason` 保持子代理執行並將 `reason` 作為其下一個指令傳遞給子代理。透過退出 2 阻止的 hook 以相同方式傳遞其 stderr 訊息。若要在子代理返回後將背景資訊注入到父工作階段,請改用 `Agent` 工具上的 [`PostToolUse`](#posttooluse) hook。
2184 2603
2185<h3 id="taskcreated">2604<h3 id="taskcreated">
2186 TaskCreated2605 TaskCreated
2187</h3>2606</h3>
2188 2607
2189當任務通過 `TaskCreate` 工具被建立時執行。使用此項來強制執行命名慣例、要求任務描述或防止某些任務被建立。2608在透過 `TaskCreate` 工具建立任務時執行。使用此來強制命名慣例、要求任務描述或防止建立某些任務。在 [沒有 Task 工具的工作階段](/docs/zh-TW/tools-reference#task-tool-availability) 中,此事件不觸發。
2190 2609
2191當 `TaskCreated` hook 以代碼 2 退出時,任務不被建立,stderr 訊息被反饋給模型作為反饋。要完全停止隊友而不是重新執行它,請返回 JSON,其中 `{"continue": false, "stopReason": "..."}`。TaskCreated hooks 不支援匹配器,在每次出現時觸發。2610TaskCreated hooks 不支援匹配器,對每個出現觸發。
2192 2611
2193<h4 id="taskcreated-input">2612<h4 id="taskcreated-input">
2194 TaskCreated 輸入2613 TaskCreated 輸入
2195</h4>2614</h4>
2196 2615
2197除了 [通用輸入欄位](#common-input-fields) 外,TaskCreated hooks 還接收 `task_id`、`task_subject` 和可選的 `task_description`、`teammate_name` 和 `team_name`。2616除了 [常見輸入欄位](#common-input-fields) 外,TaskCreated hooks 還會接收 `task_id`、`task_subject` 和可選的 `task_description`、`teammate_name` 和 `team_name`。
2198 2617
2199```json theme={null}2618```json theme={null}
2200{2619{
2201 "session_id": "abc123",2620 "session_id": "abc123",
2202 "transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",2621 "transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",
2203 "cwd": "/Users/...",2622 "cwd": "/Users/...",
2204 "permission_mode": "default",
2205 "hook_event_name": "TaskCreated",2623 "hook_event_name": "TaskCreated",
2206 "task_id": "task-001",2624 "task_id": "task-001",
2207 "task_subject": "Implement user authentication",2625 "task_subject": "Implement user authentication",
2213 2631
2214| 欄位 | 描述 |2632| 欄位 | 描述 |
2215| :----------------- | :------------------------ |2633| :----------------- | :------------------------ |
2216| `task_id` | 被建立的任務的識別碼 |2634| `task_id` | 正在建立的任務的識別碼 |
2217| `task_subject` | 任務的標題 |2635| `task_subject` | 任務的標題 |
2218| `task_description` | 任務的詳細描述。可能不存在 |2636| `task_description` | 任務的詳細描述。可能不存在 |
2219| `teammate_name` | 建立任務的隊友的名稱。可能不存在 |2637| `teammate_name` | 建立任務的隊友的名稱。可能不存在 |
2220| `team_name` | 已棄用。工作階段衍生的團隊名稱;將在未來版本中移除 |2638| `team_name` | 已棄用。工作階段衍生的團隊名稱;將在未來版本中移除 |
2221 2639
2222<h4 id="taskcreated-decision-control">2640<h4 id="taskcreated-decision-control">
2223 TaskCreated 決定控制2641 TaskCreated 決策控制
2224</h4>2642</h4>
2225 2643
2226TaskCreated hooks 支援兩種方式來控制任務建立:2644TaskCreated hook 可以透過兩種方式阻止建立。任一方式,Claude Code 刪除任務並將您的訊息返回給 Claude 作為工具的錯誤。Claude Code 忽略此事件中的 `continue: false`,Claude 繼續工作。
2227 2645
2228* **退出代碼 2**:任務不被建立,stderr 訊息被反饋給模型作為反饋。2646* **退出代碼 2**:Claude Code 將 stderr 文字返回作為訊息。
2229* **JSON `{"continue": false, "stopReason": "..."}`**:完全停止隊友,匹配 `Stop` hook 行為。`stopReason` 向使用者顯示。2647* **JSON `{"decision": "block", "reason": "..."}`**:Claude Code 將 `reason` 返回作為訊息。
2230 2648
2231此範例阻止主題不遵循所需格式的任務:2649此範例阻止主題不遵循所需格式的任務:
2232 2650
2247 TaskCompleted2665 TaskCompleted
2248</h3>2666</h3>
2249 2667
2250當任務被標記為已完成時執行。這在兩種情況下觸發:當任何代理通過 TaskUpdate 工具明確標記任務為已完成時,或當 [agent team](/docs/zh-TW/agent-teams) 隊友完成其輪次並有進行中的任務時。使用此項來強制執行完成條件,例如通過測試或 lint 檢查,然後任務才能關閉。2668在任務被標記為完成時執行。這在兩種情況下觸發:當任何代理透過 TaskUpdate 工具明確標記任務為完成時,或當 [代理團隊](/docs/zh-TW/agent-teams) 隊友以進行中的任務完成其回合時。使用此來強制完成條件,例如通過測試或 lint 檢查,然後任務才能關閉。
2251 2669
2252當 `TaskCompleted` hook 以代碼 2 退出時,任務不被標記為已完成,stderr 訊息被反饋給模型作為反饋。要完全停止隊友而不是重新執行它,請返回 JSON,其中 `{"continue": false, "stopReason": "..."}`。TaskCompleted hooks 不支援匹配器,在每次出現時觸發。2670TaskCompleted hooks 不支援匹配器,對每個出現觸發。
2253 2671
2254<h4 id="taskcompleted-input">2672<h4 id="taskcompleted-input">
2255 TaskCompleted 輸入2673 TaskCompleted 輸入
2256</h4>2674</h4>
2257 2675
2258除了 [通用輸入欄位](#common-input-fields) 外,TaskCompleted hooks 還接收 `task_id`、`task_subject` 和可選的 `task_description`、`teammate_name` 和 `team_name`。2676除了 [常見輸入欄位](#common-input-fields) 外,TaskCompleted hooks 還會接收 `task_id`、`task_subject` 和可選的 `task_description`、`teammate_name` 和 `team_name`。
2259 2677
2260```json theme={null}2678```json theme={null}
2261{2679{
2274 2692
2275| 欄位 | 描述 |2693| 欄位 | 描述 |
2276| :----------------- | :------------------------ |2694| :----------------- | :------------------------ |
2277| `task_id` | 被完成的任務的識別碼 |2695| `task_id` | 正在完成的任務的識別碼 |
2278| `task_subject` | 任務的標題 |2696| `task_subject` | 任務的標題 |
2279| `task_description` | 任務的詳細描述。可能不存在 |2697| `task_description` | 任務的詳細描述。可能不存在 |
2280| `teammate_name` | 完成任務的隊友的名稱。可能不存在 |2698| `teammate_name` | 完成任務的隊友的名稱。可能不存在 |
2281| `team_name` | 已棄用。工作階段衍生的團隊名稱;將在未來版本中移除 |2699| `team_name` | 已棄用。工作階段衍生的團隊名稱;將在未來版本中移除 |
2282 2700
2283<h4 id="taskcompleted-decision-control">2701<h4 id="taskcompleted-decision-control">
2284 TaskCompleted 決定控制2702 TaskCompleted 決策控制
2285</h4>2703</h4>
2286 2704
2287TaskCompleted hooks 支援兩種方式來控制任務完成:2705TaskCompleted hooks 支援兩種方式來控制任務完成:
2288 2706
2289* **退出代碼 2**:任務不被標記為已完成,stderr 訊息被反饋給模型作為反饋。2707* **退出代碼 2**:任務未被標記為完成,stderr 訊息作為回饋反饋給模型。
2290* **JSON `{"continue": false, "stopReason": "..."}`**:完全停止隊友,匹配 `Stop` hook 行為。`stopReason` 向使用者顯示。2708* **JSON `{"continue": false, "stopReason": "..."}`**:當隊友完成其回合觸發事件時,完全停止隊友,匹配 `Stop` hook 行為。`stopReason` 顯示給使用者。當 `TaskUpdate` 工具觸發事件時,Claude Code 忽略 `continue: false`;退出代碼 2 仍然阻止完成。
2291 2709
2292此範例執行測試並在失敗時阻止任務完成:2710此範例執行測試並在它們失敗時阻止任務完成:
2293 2711
2294```bash theme={null}2712```bash theme={null}
2295#!/bin/bash2713#!/bin/bash
2296INPUT=$(cat)2714INPUT=$(cat)
2297TASK_SUBJECT=$(echo "$INPUT" | jq -r '.task_subject')2715TASK_SUBJECT=$(echo "$INPUT" | jq -r '.task_subject')
2298 2716
2299# 執行測試套件2717# Run the test suite
2300if ! npm test 2>&1; then2718if ! npm test 2>&1; then
2301 echo "Tests not passing. Fix failing tests before completing: $TASK_SUBJECT" >&22719 echo "Tests not passing. Fix failing tests before completing: $TASK_SUBJECT" >&2
2302 exit 22720 exit 2
2309 Stop2727 Stop
2310</h3>2728</h3>
2311 2729
2312當主 Claude Code 代理完成回應時執行。如果停止是由於使用者中斷,則不執行。API 錯誤會觸發 [StopFailure](#stopfailure)。2730在主 Claude Code 代理完成回應時執行。如果停止發生是由於使用者中斷,則不執行。API 錯誤改為觸發 [StopFailure](#stopfailure)。
2313 2731
2314<Tip>2732<Tip>
2315 [`/goal`](/docs/zh-TW/goal) 命令是工作階段範圍提示型 Stop hook 的內建快捷方式。當您想要 Claude 繼續工作直到條件成立而不編寫 hook 配置時,請使用它。2733 [`/goal`](/docs/zh-TW/goal) 命令是工作階段範圍提示型 Stop hook 的內建快捷方式。當您想讓 Claude 在不編寫 hook 設定的情況下朝著條件繼續工作時使用它。
2316</Tip>2734</Tip>
2317 2735
2318<h4 id="stop-input">2736<h4 id="stop-input">
2319 Stop 輸入2737 Stop 輸入
2320</h4>2738</h4>
2321 2739
2322除了 [通用輸入欄位](#common-input-fields) 外,Stop hooks 還接收 `stop_hook_active`、`last_assistant_message`、`background_tasks` 和 `session_crons`。`stop_hook_active` 欄位在 Claude Code 已經作為 stop hook 的結果繼續時為 `true`。檢查此值或處理成績單以防止 Claude Code 無限執行。Claude Code 在 8 次連續阻止後覆蓋 hook 並結束轉向。2740除了 [常見輸入欄位](#common-input-fields) 外,Stop hooks 還會接收 `stop_hook_active`、`last_assistant_message`、`background_tasks` 和 `session_crons`。`stop_hook_active` 欄位在 Claude Code 已作為 stop hook 的結果繼續時為 `true`。檢查此值或處理文字記錄以避免在永遠不會解決的條件上阻止。Claude Code 在 8 個連續阻止後覆寫 hook 並結束回合。
2323 2741
2324`last_assistant_message` 欄位包含 Claude 最終回應的文字內容,因此 hooks 可以存取它而無需解析成績單檔案。對於作用於剛完成的轉向的 hooks,例如朗讀或通知 hooks,請使用此欄位而不是讀取 `transcript_path`:成績單檔案在所有版本上的 Stop 時間都不保證包含最終訊息。2742`last_assistant_message` 欄位包含 Claude 最終回應的文字內容,因此 hooks 可以存取它而不解析文字記錄檔案。對於作用於剛完成回合的 hooks,例如朗讀或通知 hooks,使用此欄位而不是讀取 `transcript_path`:文字記錄檔案不保證在所有版本上的 Stop 時間包含最終訊息。
2325 2743
2326`background_tasks` 和 `session_crons` 陣列在 Claude Code v2.1.145 或更高版本中可用,讓 hooks 區分「工作階段完成」和「工作階段暫停等待背景工作喚醒它」。當任務登錄表可達時,兩個陣列都存在,當沒有任何內容在進行中或計劃時為空。2744`background_tasks` 和 `session_crons` 陣列讓 hooks 區分「工作階段完成」與「工作階段暫停等待背景工作喚醒它」。當任務登錄可到達時兩個陣列都存在,當沒有任何內容在進行中或排程時為空。
2327 2745
2328`background_tasks` 中的每個項目描述一個進行中的任務,並使用這些欄位:2746`background_tasks` 中的每個項目描述一個進行中的任務並使用這些欄位:
2329 2747
2330| 欄位 | 描述 |2748| 欄位 | 描述 |
2331| :------------ | :------------------------------------------------------------------------------------------------------------------------------------------- |2749| :------------ | :----------------------------------------------------------------------------------------------------------------------------------------- |
2332| `id` | 任務識別碼 |2750| `id` | 任務識別碼 |
2333| `type` | 友好的任務類型標籤,例如 `shell`、`subagent`、`monitor`、`workflow`、`teammate`、`cloud session` 或 `MCP task`。每個標籤識別哪個 Claude Code 功能建立了任務。對於無法識別的類型,回退到原始判別式 |2751| `type` | 友善任務類型標籤,例如 `shell`、`subagent`、`monitor`、`workflow`、`teammate`、`cloud session` 或 `MCP task`。每個標籤識別哪個 Claude Code 功能建立了任務。對於無法識別的類型回退到原始判別式 |
2334| `status` | 目前任務狀態 |2752| `status` | 目前任務狀態 |
2335| `description` | 自由文字描述,上限為 1000 個字元,當被剪裁時在字串中有 `… [+N chars]` 標記 |2753| `description` | 自由文字描述,上限為 1000 個字元,當剪裁時在字串中帶有 `… [+N chars]` 標記 |
2336| `command` | Shell 命令行,上限為 1000 個字元。僅針對 `shell` 任務出現 |2754| `command` | Shell 命令行,上限為 1000 個字元。僅對 `shell` 任務出現 |
2337| `agent_type` | Subagent 類型名稱。僅針對 `subagent` 任務出現 |2755| `agent_type` | 子代理類型名稱。僅對 `subagent` 任務出現 |
2338| `server` | MCP 伺服器名稱。僅針對 `monitor` 和 `MCP task` 任務出現 |2756| `server` | MCP 伺服器名稱。僅對 `monitor` 和 `MCP task` 任務出現 |
2339| `tool` | MCP 工具名稱。僅針對 `monitor` 和 `MCP task` 任務出現 |2757| `tool` | MCP 工具名稱。僅對 `monitor` 和 `MCP task` 任務出現 |
2340| `name` | 工作流名稱。僅針對 `workflow` 任務出現 |2758| `name` | 工作流程名稱。僅對 `workflow` 任務出現 |
2341 2759
2342`session_crons` 中的每個項目描述一個工作階段範圍的計劃喚醒,來自 `CronCreate`、`ScheduleWakeup` 和 `/loop`:2760`session_crons` 中的每個項目描述一個工作階段範圍排程喚醒,來自 `CronCreate`、`ScheduleWakeup` 和 `/loop`:
2343 2761
2344| 欄位 | 描述 |2762| 欄位 | 描述 |
2345| :---------- | :--------------------------------------------------- |2763| :---------- | :---------------------------------------------------- |
2346| `id` | Cron 任務識別碼 |2764| `id` | Cron 任務識別碼 |
2347| `schedule` | Cron 表達式,例如 `0 9 * * 1-5` |2765| `schedule` | Cron 表達式,例如 `0 9 * * 1-5` |
2348| `recurring` | `false` 用於一次性喚醒,其計劃編碼單一觸發時間,`true` 用於在每次匹配時重新觸發的任務 |2766| `recurring` | 對於一次性喚醒(其排程編碼單個觸發時間)為 `false`,對於在每個匹配上重新觸發的任務為 `true` |
2349| `prompt` | 當 cron 觸發時提交的提示,上限為 1000 個字元,具有相同的 `… [+N chars]` 標記 |2767| `prompt` | Cron 觸發時提交的提示,上限為 1000 個字元,帶有相同的 `… [+N chars]` 標記 |
2350 2768
2351此範例顯示一個 Stop 輸入,其中有一個進行中的 shell 任務和一個循環 cron:2769此範例顯示一個 Stop 輸入,其中一個進行中的 shell 任務和一個循環 cron:
2352 2770
2353```json theme={null}2771```json theme={null}
2354{2772{
2380```2798```
2381 2799
2382<h4 id="stop-decision-control">2800<h4 id="stop-decision-control">
2383 Stop 決定控制2801 Stop 決策控制
2384</h4>2802</h4>
2385 2803
2386`Stop` 和 `SubagentStop` hooks 可以控制 Claude 是否繼續。除了所有 hooks 可用的 [JSON 輸出欄位](#json-output) 外,您的 hook 指令碼可以返回這些事件特定欄位:2804`Stop` 和 `SubagentStop` hooks 可以控制 Claude 是否繼續。除了所有 hooks 可用的 [JSON 輸出欄位](#json-output) 外,您的 hook 指令碼可以返回這些事件特定欄位:
2387 2805
2388| 欄位 | 描述 |2806| 欄位 | 描述 |
2389| :------------------------------------- | :-------------------------------------------------------------------------------------------- |2807| :------------------------------------- | :------------------------------------------------------------------------------------------ |
2390| `decision` | `"block"` 防止 Claude 停止。省略以允許 Claude 停止 |2808| `decision` | `"block"` 防止 Claude 停止。省略以允許 Claude 停止 |
2391| `reason` | 當 `decision` 為 `"block"` 時必需。告訴 Claude 為什麼它應該繼續 |2809| `reason` | 當 `decision` 為 `"block"` 時需要。告訴 Claude 為什麼它應該繼續 |
2392| `hookSpecificOutput.additionalContext` | 非錯誤反饋給 Claude。對話繼續,以便 Claude 可以對其採取行動,但與 `decision: "block"` 不同,它在成績單中顯示為 hook 反饋,而不是 hook 錯誤 |2810| `hookSpecificOutput.additionalContext` | Claude 的非錯誤回饋。對話繼續,以便 Claude 可以作用於它,但與 `decision: "block"` 不同,它在文字記錄中顯示為 hook 回饋而不是 hook 錯誤 |
2811
2812透過退出 2 阻止的 hook 路由方式與 `reason` 相同:Claude 接收 stderr 訊息作為為什麼它應該繼續的解釋。
2393 2813
2394```json theme={null}2814```json theme={null}
2395{2815{
2398}2818}
2399```2819```
2400 2820
2401當 hook 的設計目的是提供指導時,使用 `additionalContext`,例如「在完成前執行測試套件」。它通過與 `decision: "block"` 相同的迴圈保護(即 `stop_hook_active` 輸入和 8 次連續繼續上限)保持對話進行,但成績單將其標籤為 `Stop hook feedback`,不顯示 hook 錯誤通知:2821當 hook 按設計工作並給予 Claude 指導時使用 `additionalContext`,例如「在完成前執行測試套件」。它透過與 `decision: "block"` 相同的迴圈保護保持對話進行,即 `stop_hook_active` 輸入和 8 個連續繼續上限,但文字記錄將其標籤為 `Stop hook feedback`,不顯示 hook 錯誤通知:
2402 2822
2403```json theme={null}2823```json theme={null}
2404{2824{
2413 StopFailure2833 StopFailure
2414</h3>2834</h3>
2415 2835
2416當轉向因 API 錯誤而結束時執行,而不是 [Stop](#stop)。輸出和退出代碼被忽略。使用此項來記錄失敗、發送警報或在 Claude 因速率限制、驗證問題或其他 API 錯誤而無法完成回應時採取恢復操作。2836在回合因 API 錯誤而結束時執行,而不是 [Stop](#stop)。Claude Code 忽略 hook 的輸出和退出代碼,除了 [`terminalSequence`](#emit-terminal-notifications)。使用此來記錄失敗、發送警報或在 Claude 因速率限制、驗證問題或其他 API 錯誤而無法完成回應時採取恢復動作。
2417 2837
2418<h4 id="stopfailure-input">2838<h4 id="stopfailure-input">
2419 StopFailure 輸入2839 StopFailure 輸入
2420</h4>2840</h4>
2421 2841
2422除了 [通用輸入欄位](#common-input-fields) 外,StopFailure hooks 還接收 `error`、可選的 `error_details` 和可選的 `last_assistant_message`。`error` 欄位識別錯誤類型,用於匹配器篩選。2842除了 [常見輸入欄位](#common-input-fields) 外,StopFailure hooks 還會接收 `error`、可選 `error_details` 和可選 `last_assistant_message`。`error` 欄位識別錯誤類型並用於匹配器篩選。
2423 2843
2424| 欄位 | 描述 |2844| 欄位 | 描述 |
2425| :----------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |2845| :----------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
2426| `error` | 錯誤類型:`rate_limit`、`overloaded`、`authentication_failed`、`oauth_org_not_allowed`、`billing_error`、`invalid_request`、`model_not_found`、`server_error`、`max_output_tokens` 或 `unknown` |2846| `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` |
2427| `error_details` | 有關錯誤的其他詳細資訊(如果可用) |2847| `error_details` | 關於錯誤的其他詳細資訊(如果可用) |
2428| `last_assistant_message` | 在對話中顯示的呈現錯誤文字。與 `Stop` 和 `SubagentStop` 不同,其中此欄位包含 Claude 的對話輸出,對於 `StopFailure`,它包含 API 錯誤字串本身,例如 `"API Error: Rate limit reached"` |2848| `last_assistant_message` | 在對話中顯示的呈現錯誤文字。與 `Stop` 和 `SubagentStop` 不同,其中此欄位保留 Claude 的對話輸出,對於 `StopFailure` 它包含 API 錯誤字串本身,例如 `"API Error: Rate limit reached"` |
2429 2849
2430```json theme={null}2850```json theme={null}
2431{2851{
2439}2859}
2440```2860```
2441 2861
2442StopFailure hooks 沒有決定控制。它們僅用於通知和記錄目的執行。2862StopFailure hooks 沒有決策控制。它們僅用於通知和記錄目的執行。
2443 2863
2444<h3 id="teammateidle">2864<h3 id="teammateidle">
2445 TeammateIdle2865 TeammateIdle
2446</h3>2866</h3>
2447 2867
2448當 [agent team](/docs/zh-TW/agent-teams) 隊友在完成其輪次後即將閒置時執行。使用此項來在隊友停止工作之前強制執行品質閘道,例如要求通過 lint 檢查或驗證輸出檔案存在。2868在 [代理團隊](/docs/zh-TW/agent-teams) 隊友在完成其回合後即將閒置時執行。使用此來強制品質閘門,然後隊友停止工作,例如要求通過 lint 檢查或驗證輸出檔案存在。
2449 2869
2450當 `TeammateIdle` hook 以代碼 2 退出時,隊友會收到 stderr 訊息作為反饋,並繼續工作而不是閒置。要完全停止隊友而不是重新執行它,請返回 JSON,其中 `{"continue": false, "stopReason": "..."}`。TeammateIdle hooks 不支援匹配器,在每次出現時觸發。2870TeammateIdle hooks 不支援匹配器,對每個出現觸發。
2451 2871
2452<h4 id="teammateidle-input">2872<h4 id="teammateidle-input">
2453 TeammateIdle 輸入2873 TeammateIdle 輸入
2454</h4>2874</h4>
2455 2875
2456除了 [通用輸入欄位](#common-input-fields) 外,TeammateIdle hooks 還接收 `teammate_name` 和 `team_name`。2876除了 [常見輸入欄位](#common-input-fields) 外,TeammateIdle hooks 還會接收 `teammate_name` 和 `team_name`。
2457 2877
2458```json theme={null}2878```json theme={null}
2459{2879{
2473| `team_name` | 已棄用。工作階段衍生的團隊名稱;將在未來版本中移除 |2893| `team_name` | 已棄用。工作階段衍生的團隊名稱;將在未來版本中移除 |
2474 2894
2475<h4 id="teammateidle-decision-control">2895<h4 id="teammateidle-decision-control">
2476 TeammateIdle 決定控制2896 TeammateIdle 決策控制
2477</h4>2897</h4>
2478 2898
2479TeammateIdle hooks 支援兩種方式來控制隊友行為:2899TeammateIdle hooks 支援兩種方式來控制隊友行為:
2480 2900
2481* **退出代碼 2**:隊友會收到 stderr 訊息作為反饋,並繼續工作而不是閒置。2901* **退出代碼 2**:隊友接收 stderr 訊息作為回饋並繼續工作而不是閒置。
2482* **JSON `{"continue": false, "stopReason": "..."}`**:完全停止隊友,匹配 `Stop` hook 行為。`stopReason` 向使用者顯示。2902* **JSON `{"continue": false, "stopReason": "..."}`**:完全停止隊友,匹配 `Stop` hook 行為。`stopReason` 顯示給使用者。
2483 2903
2484此範例在允許隊友閒置之前檢查建置成品是否存在:2904此範例檢查建置成品存在,然後允許隊友閒置:
2485 2905
2486```bash theme={null}2906```bash theme={null}
2487#!/bin/bash2907#!/bin/bash
2498 ConfigChange2918 ConfigChange
2499</h3>2919</h3>
2500 2920
2501當配置檔案在工作階段期間變更時執行。使用此項來稽核設定變更、強制執行安全原則或阻止對配置檔案的未授權修改。2921在工作階段期間設定檔變更時執行。使用此來稽核設定變更、強制安全原則或阻止對設定檔的未授權修改。
2502 2922
2503ConfigChange hooks 針對設定檔、受管理的原則設定和 skill 檔案的變更觸發。輸入中的 `source` 欄位告訴您哪種類型的配置變更,可選的 `file_path` 欄位提供變更檔案的路徑。2923Claude Code 在設定檔、受管原則檔案或 skill 檔案變更時執行 ConfigChange hooks。對於受管原則,它僅在 `managed-settings.json` 或 `managed-settings.d/` 中的檔案變更時執行。它應用 [伺服器受管設定](/docs/zh-TW/server-managed-settings) 和對 macOS 受管偏好設定或 Windows 登錄原則的變更而不執行。在 WSL 上搭配 [`wslInheritsWindowsSettings`](/docs/zh-TW/settings-reference#wslinheritswindowssettings),它也應用在其原則輪詢上變更的 Windows 端受管設定檔而不執行。
2504 2924
2505匹配器篩選配置來源:2925匹配器篩選設定來源:
2506 2926
2507| 匹配器 | 何時觸發 |2927| 匹配器 | 何時觸發 |
2508| :----------------- | :------------------------------- |2928| :----------------- | :----------------------------------------------------- |
2509| `user_settings` | `~/.claude/settings.json` 變更 |2929| `user_settings` | `~/.claude/settings.json` 變更 |
2510| `project_settings` | `.claude/settings.json` 變更 |2930| `project_settings` | `.claude/settings.json` 變更 |
2511| `local_settings` | `.claude/settings.local.json` 變更 |2931| `local_settings` | `.claude/settings.local.json` 變更 |
2512| `policy_settings` | 受管理的原則設定變更 |2932| `policy_settings` | `managed-settings.json` 或 `managed-settings.d/` 中的檔案變更 |
2513| `skills` | `.claude/skills/` 中的 skill 檔案變更 |2933| `skills` | `.claude/skills/` 中的 skill 檔案變更 |
2514 2934
2515此範例記錄所有配置變更以進行安全稽核:2935此範例記錄所有設定變更以進行安全稽核:
2516 2936
2517```json theme={null}2937```json theme={null}
2518{2938{
2536 ConfigChange 輸入2956 ConfigChange 輸入
2537</h4>2957</h4>
2538 2958
2539除了 [通用輸入欄位](#common-input-fields) 外,ConfigChange hooks 還接收 `source` 和可選的 `file_path`。`source` 欄位指示哪種配置類型變更,`file_path` 提供被修改的特定檔案的路徑。2959除了 [常見輸入欄位](#common-input-fields) 外,ConfigChange hooks 還會接收 `source` 和可選的 `file_path`。`source` 欄位指示哪個設定類型變更,`file_path` 提供修改的特定檔案的路徑。
2540 2960
2541```json theme={null}2961```json theme={null}
2542{2962{
2550```2970```
2551 2971
2552<h4 id="configchange-decision-control">2972<h4 id="configchange-decision-control">
2553 ConfigChange 決定控制2973 ConfigChange 決策控制
2554</h4>2974</h4>
2555 2975
2556ConfigChange hooks 可以阻止配置變更生效。使用退出代碼 2 或 JSON `decision` 來防止變更。被阻止時,新設定不會應用於執行中的工作階段。2976ConfigChange hooks 可以阻止設定變更生效。使用退出代碼 2 或 JSON `decision` 來防止變更。被阻止時,新設定不會套用到執行中的工作階段。
2557 2977
2558| 欄位 | 描述 |2978| 欄位 | 描述 |
2559| :--------- | :---------------------------------- |2979| :--------- | :-------------------------- |
2560| `decision` | `"block"` 防止配置變更被應用。省略以允許變更 |2980| `decision` | `"block"` 防止設定變更被套用。省略以允許變更 |
2561| `reason` | 當 `decision` 為 `"block"` 時向使用者顯示的解釋 |2981| `reason` | 接受但永遠不顯示 |
2562 2982
2563```json theme={null}2983```json theme={null}
2564{2984{
2567}2987}
2568```2988```
2569 2989
2570`policy_settings` 變更無法被阻止。Hooks 仍然針對 `policy_settings` 來源觸發,因此您可以使用它們進行稽核記錄,但任何阻止決定都會被忽略。這確保企業管理的設定始終生效。2990`policy_settings` 變更無法被阻止。當機器上的受管設定檔變更時,Hooks 仍然對 `policy_settings` 來源觸發,因此您可以使用它們來記錄這些編輯,但任何阻止決策都被忽略。這確保企業受管設定始終生效。當 [伺服器受管設定](/docs/zh-TW/server-managed-settings) 到達或重新整理時,Claude Code 不執行 `ConfigChange` hooks。
2991
2992Claude Code 作用於 ConfigChange hook 的 JSON 輸出中的阻止決策,並捨棄 `systemMessage` 和 `continue`。被阻止的變更不向您或 Claude 呈現任何訊息,無論您是否使用 `reason` 或退出 2 時的 stderr 阻止。Claude Code 僅將一行寫入偵錯日誌。
2571 2993
2572<h3 id="cwdchanged">2994<h3 id="cwdchanged">
2573 CwdChanged2995 CwdChanged
2574</h3>2996</h3>
2575 2997
2576當工作目錄在工作階段期間變更時執行,例如當 Claude 執行 `cd` 命令時。使用此項來對目錄變更做出反應:重新載入環境變數、啟動專案特定的工具鏈或自動執行設定指令碼。與 [FileChanged](#filechanged) 配對,用於 [direnv](https://direnv.net/) 等管理每個目錄環境的工具。2998在主對話中的 shell 命令變更工作目錄時執行,例如當 Claude 執行 `cd` 命令時。使用此來對目錄變更做出反應:重新載入環境變數、啟動專案特定工具鏈或自動執行設定指令碼。與 [FileChanged](#filechanged) 配對,用於 [direnv](https://direnv.net/) 等管理每個目錄環境的工具。
2577 2999
2578CwdChanged hooks 可以存取 `CLAUDE_ENV_FILE`。寫入該檔案的變數會持久化到工作階段的後續 Bash 命令中,就像在 [SessionStart hooks](#persist-environment-variables) 中一樣。3000CwdChanged hooks 可以存取 [`CLAUDE_ENV_FILE`](#persist-environment-variables)。寫入該檔案的變數會保留到下一個 CwdChanged 事件,當 Claude Code 清除它們時。
2579 3001
2580CwdChanged 不支援匹配器,在每次目錄變更時觸發。3002CwdChanged 不支援匹配器,對每個出現觸發。
2581 3003
2582<h4 id="cwdchanged-input">3004<h4 id="cwdchanged-input">
2583 CwdChanged 輸入3005 CwdChanged 輸入
2584</h4>3006</h4>
2585 3007
2586除了 [通用輸入欄位](#common-input-fields) 外,CwdChanged hooks 還接收 `old_cwd` 和 `new_cwd`。3008除了 [常見輸入欄位](#common-input-fields) 外,CwdChanged hooks 還會接收 `old_cwd` 和 `new_cwd`。
2587 3009
2588```json theme={null}3010```json theme={null}
2589{3011{
2600 CwdChanged 輸出3022 CwdChanged 輸出
2601</h4>3023</h4>
2602 3024
2603除了所有 hooks 可用的 [JSON 輸出欄位](#json-output) 外,CwdChanged hooks 還可以返回 `watchPaths` 來動態設定 [FileChanged](#filechanged) 監視的檔案路徑:3025除了所有 hooks 可用的 [JSON 輸出欄位](#json-output) 外,CwdChanged hooks 可以返回 `watchPaths` 以動態設定 [FileChanged](#filechanged) 監視的檔案路徑:
2604 3026
2605| 欄位 | 描述 |3027| 欄位 | 描述 |
2606| :----------- | :-------------------------------------------------------------------- |3028| :----------- | :--------------------------------------------------------------------- |
2607| `watchPaths` | 絕對路徑的陣列。替換目前的動態監視清單。來自您 `matcher` 配置的路徑始終被監視。返回空陣列會清除動態清單,這在進入新目錄時很典型 |3029| `watchPaths` | 絕對路徑的陣列。替換目前的動態監視清單。您的 `matcher` 設定中的路徑始終被監視。返回空陣列以清除動態清單,這在進入新目錄時是典型的 |
3030
3031CwdChanged hooks 沒有決策控制。它們無法阻止目錄變更。
2608 3032
2609CwdChanged hooks 沒有決定控制。它們無法阻止目錄變更。3033Claude Code 從其 JSON 輸出讀取 `watchPaths` 和 `systemMessage`,並捨棄 `continue`。在互動式工作階段中,它將 `systemMessage` 顯示為簡短終端通知。訊息不到達 SDK 訊息流。
3034
3035<h3 id="directoryadded">
3036 DirectoryAdded
3037</h3>
3038
3039在您使用 `/add-dir` 命令在工作階段中期新增工作目錄後執行,或在 SDK 用戶端使用 `register_repo_root` 控制請求新增工作目錄後執行。使用此來準備新增的儲存庫,例如安裝其相依性。
3040
3041Claude Code 在以下情況下不觸發此事件:
3042
3043* 您使用 `--add-dir` 啟動旗標傳遞目錄;[SessionStart](#sessionstart) 涵蓋這些目錄
3044* 您在 `/permissions` Workspace 標籤上新增目錄
3045* 您新增已是工作目錄或在其內部的目錄
3046
3047Claude Code 在重新整理沙箱和權限狀態後觸發 DirectoryAdded,因此沙箱工具在您的 hook 執行時已看到新目錄。Hook 命令本身執行未沙箱化。
3048
3049Claude Code 不等待 hook:新增立即完成,hook 在背景執行,使用 600 秒預設逾時。
3050
3051匹配器篩選目錄的新增方式:
3052
3053| 匹配器 | 何時觸發 |
3054| :------------------- | :-------------------------------------- |
3055| `slash_command` | 您使用 `/add-dir` 新增目錄 |
3056| `register_repo_root` | SDK 用戶端使用 `register_repo_root` 控制請求新增目錄 |
3057
3058<h4 id="directoryadded-input">
3059 DirectoryAdded 輸入
3060</h4>
3061
3062除了 [常見輸入欄位](#common-input-fields) 外,DirectoryAdded hooks 還會接收 `directory` 和 `source`。
3063
3064| 欄位 | 描述 |
3065| :---------- | :------------------------------------------------------------------------ |
3066| `directory` | 新增的目錄的絕對路徑 |
3067| `source` | 目錄如何被新增,`/add-dir` 為 `"slash_command"` 或 SDK 控制請求為 `"register_repo_root"` |
3068
3069```json theme={null}
3070{
3071 "session_id": "abc123",
3072 "transcript_path": "/Users/.../.claude/projects/.../transcript.jsonl",
3073 "cwd": "/Users/my-project",
3074 "hook_event_name": "DirectoryAdded",
3075 "directory": "/Users/my-other-repo",
3076 "source": "slash_command"
3077}
3078```
3079
3080DirectoryAdded hooks 沒有決策控制。它們無法阻止新增,這在 hook 執行時已完成。Claude Code 從其 JSON 輸出捨棄 `continue` 欄位,並根據來源以不同方式呈現其餘部分:
3081
3082* `slash_command`:Claude Code 將 hook 的 `systemMessage` 傳遞給 Claude 作為下一個對話回合的背景資訊,而不是向您顯示。失敗 hooks 的計數出現在文字記錄中。完整失敗輸出進入偵錯日誌
3083* `register_repo_root`:Claude Code 僅將 `systemMessage` 輸出和失敗輸出寫入偵錯日誌
2610 3084
2611<h3 id="filechanged">3085<h3 id="filechanged">
2612 FileChanged3086 FileChanged
2613</h3>3087</h3>
2614 3088
2615當監視的檔案在磁碟上變更時執行。適用於在專案配置檔案被修改時重新載入環境變數。3089在監視的檔案在磁碟上變更時執行。Claude Code 使用檔案系統監視器偵測變更,而不是檢查工具呼叫,因此無論什麼變更檔案,它都執行 hook:`Edit` 或 `Write` 工具呼叫、Claude 使用 `Bash` 執行的指令碼,或 Claude Code 外的程序。常見用途是在專案設定檔變更時重新載入環境變數。
3090
3091此事件的 `matcher` 有兩個角色:
3092
3093* **建立監視清單**:值在 `|` 上分割,每個段落註冊為工作目錄中的字面檔案名稱,因此 `".envrc|.env"` 監視恰好這兩個檔案。正規表達式模式在這裡不有用:`^\.env` 之類的值會監視字面名稱為 `^\.env` 的檔案。
3094* **篩選哪些 hooks 執行**:當監視的檔案變更時,相同的值使用標準 [匹配器規則](#matcher-patterns) 針對變更檔案的基名篩選哪些 hook 群組執行。
3095
3096此範例在任何變更後規範化 `data.csv` 中的行結尾,包括 `Bash` 命令或外部指令碼重寫檔案:
3097
3098```json theme={null}
3099{
3100 "hooks": {
3101 "FileChanged": [
3102 {
3103 "matcher": "data.csv",
3104 "hooks": [
3105 {
3106 "type": "command",
3107 "command": "/path/to/normalize-line-endings.sh"
3108 }
3109 ]
3110 }
3111 ]
3112 }
3113}
3114```
3115
3116Hook 從 [JSON 輸入](#filechanged-input) 的 `file_path` 欄位讀取變更檔案的絕對路徑,在 stdin 上。其 `grep` 守衛測試 `perl` 移除的相同內容,行尾的 CR,因此規範化後的執行退出而不觸及檔案。較鬆散的守衛迴圈永遠,因為 `perl -i` 重寫檔案即使它替換無內容,Claude Code 在每次重寫後執行 hook。將此指令碼儲存在 `/path/to/normalize-line-endings.sh` 並使其可執行:
3117
3118```bash theme={null}
3119#!/bin/bash
3120FILE=$(jq -r .file_path)
3121if grep -q $'\r$' "$FILE"; then
3122 perl -pi -e 's/\r$//' "$FILE"
3123fi
3124```
2616 3125
2617`matcher` 對於此事件有兩個角色:3126若要確認 hook 有效,要求 Claude 使用 `Bash` 命令將 CRLF 行附加到 `data.csv`。Claude Code 執行 hook,檔案以 LF 結尾。
2618 3127
2619* **建立監視清單**:值在 `|` 上分割,每個段被註冊為工作目錄中的檔案名稱,因此 `".envrc|.env"` 監視恰好這兩個檔案。正規表達式模式在這裡沒有用:像 `^\.env` 這樣的值會監視一個字面上名為 `^\.env` 的檔案。3128若要監視您無法提前命名的檔案,請從 hook 返回 [`watchPaths`](#filechanged-output) 以動態更新監視清單。Claude Code 僅在某事命名要監視的檔案時啟動監視器,因此使用至少命名一個檔案的 FileChanged 群組播種清單,或使用 [SessionStart](#sessionstart-decision-control) 或 [CwdChanged](#cwdchanged) hook 返回 `watchPaths`。匹配器仍然篩選當監視的檔案變更時哪些 hook 群組執行,因此給處理動態路徑的群組一個省略的匹配器,它匹配每個監視的檔案並不向監視清單新增任何內容。`"*"` 匹配器也匹配每個檔案,但 Claude Code 在監視清單中註冊它,如同任何其他值,作為字面名稱為 `*` 的檔案。
2620* **篩選哪些 hooks 執行**:當監視的檔案變更時,相同的值使用標準 [匹配器規則](#matcher-patterns) 針對變更檔案的基本名稱篩選哪些 hook 群組執行。
2621 3129
2622FileChanged hooks 可以存取 `CLAUDE_ENV_FILE`。寫入該檔案的變數會持久化到工作階段的後續 Bash 命令中,就像在 [SessionStart hooks](#persist-environment-variables) 中一樣。3130FileChanged hooks 可以存取 [`CLAUDE_ENV_FILE`](#persist-environment-variables)。寫入該檔案的變數會保留到下一個 [CwdChanged](#cwdchanged) 事件,當 Claude Code 清除它們時。
2623 3131
2624<h4 id="filechanged-input">3132<h4 id="filechanged-input">
2625 FileChanged 輸入3133 FileChanged 輸入
2626</h4>3134</h4>
2627 3135
2628除了 [通用輸入欄位](#common-input-fields) 外,FileChanged hooks 還接收 `file_path` 和 `event`。3136除了 [常見輸入欄位](#common-input-fields) 外,FileChanged hooks 還會接收 `file_path` 和 `event`。
2629 3137
2630| 欄位 | 描述 |3138| 欄位 | 描述 |
2631| :---------- | :-------------------------------------------------------- |3139| :---------- | :-------------------------------------------------------- |
2632| `file_path` | 變更檔案的絕對路徑 |3140| `file_path` | 變更的檔案的絕對路徑 |
2633| `event` | 發生的情況:`"change"`(檔案被修改)、`"add"`(檔案被建立)或 `"unlink"`(檔案被刪除) |3141| `event` | 發生的情況:修改的檔案為 `"change"`、建立的檔案為 `"add"` 或刪除的檔案為 `"unlink"` |
2634 3142
2635```json theme={null}3143```json theme={null}
2636{3144{
2647 FileChanged 輸出3155 FileChanged 輸出
2648</h4>3156</h4>
2649 3157
2650除了所有 hooks 可用的 [JSON 輸出欄位](#json-output) 外,FileChanged hooks 還可以返回 `watchPaths` 來動態更新監視的檔案路徑:3158除了所有 hooks 可用的 [JSON 輸出欄位](#json-output) 外,FileChanged hooks 可以返回 `watchPaths` 以動態更新監視的檔案路徑:
2651 3159
2652| 欄位 | 描述 |3160| 欄位 | 描述 |
2653| :----------- | :------------------------------------------------------------------------------- |3161| :----------- | :----------------------------------------------------------------------------- |
2654| `watchPaths` | 絕對路徑的陣列。替換目前的動態監視清單。來自您 `matcher` 配置的路徑始終被監視。當您的 hook 指令碼根據變更的檔案發現要監視的其他檔案時,使用此項 |3162| `watchPaths` | 絕對路徑的陣列。替換目前的動態監視清單。您的 `matcher` 設定中的路徑始終被監視。當您的 hook 指令碼根據變更的檔案探索要監視的其他檔案時使用此 |
2655 3163
2656FileChanged hooks 沒有決定控制。它們無法阻止檔案變更的發生。3164FileChanged hooks 沒有決策控制。它們無法阻止檔案變更發生。
3165
3166Claude Code 從其 JSON 輸出讀取 `watchPaths` 和 `systemMessage`,並捨棄 `continue`。在互動式工作階段中,它將 `systemMessage` 顯示為簡短終端通知。訊息不到達 SDK 訊息流。
2657 3167
2658<h3 id="worktreecreate">3168<h3 id="worktreecreate">
2659 WorktreeCreate3169 WorktreeCreate
2660</h3>3170</h3>
2661 3171
2662當您執行 `claude --worktree` 或 [subagent 使用 `isolation: "worktree"`](/docs/zh-TW/sub-agents#choose-the-subagent-scope) 時,Claude Code 使用 `git worktree` 建立隔離的工作副本。如果您配置 WorktreeCreate hook,它會替換預設的 git 行為,讓您使用不同的版本控制系統,如 SVN、Perforce 或 Mercurial。3172在建立 worktree 時執行,無論是從 `claude --worktree`、從 [使用 `isolation: "worktree"` 的子代理](/docs/zh-TW/sub-agents#choose-the-subagent-scope),或用於 Claude Code 在其自己的 worktree 中隔離的 [背景工作階段](/docs/zh-TW/agent-view#how-file-edits-are-isolated)。預設情況下 Claude Code 使用 `git worktree` 建立隔離的工作副本。設定 WorktreeCreate hook 完全替換該預設 git 行為,讓您使用不同的版本控制系統,例如 SVN、Perforce 或 Mercurial。
3173
3174因為 hook 完全替換預設行為,[`.worktreeinclude`](/docs/zh-TW/worktrees#copy-gitignored-files-into-worktrees) 不被處理。如果您需要複製本機設定檔,例如 `.env`,到新 worktree,請在您的 hook 指令碼內執行。
2663 3175
2664因為 hook 完全替換預設行為,[`.worktreeinclude`](/docs/zh-TW/worktrees#copy-gitignored-files-into-worktrees) 不被處理。如果您需要將本機配置檔案(如 `.env`)複製到新 worktree,請在您的 hook 指令碼內執行。3176Hook 必須返回建立的 worktree 目錄的路徑。Claude Code 使用此路徑作為隔離工作階段的工作目錄。請參閱 [WorktreeCreate 輸出](#worktreecreate-output),了解每個 hook 類型如何返回路徑。
2665 3177
2666Hook 必須返回建立的 worktree 目錄的絕對路徑。Claude Code 使用此路徑作為隔離工作階段的工作目錄。請參閱 [WorktreeCreate 輸出](#worktreecreate-output) 以了解每個 hook 類型如何返回路徑。3178Claude Code 作用於 hook 的成功和返回的路徑,並捨棄 `systemMessage` 和 `continue`。
2667 3179
2668此範例建立 SVN 工作副本並列印路徑供 Claude Code 使用。將儲存庫 URL 替換為您自己的:3180此範例建立 SVN 工作副本並列印路徑供 Claude Code 使用。將儲存庫 URL 替換為您自己的:
2669 3181
2684}3196}
2685```3197```
2686 3198
2687Hook 從 stdin 上的 JSON 輸入讀取 worktree `name`,將新副本簽出到新目錄,並列印目錄路徑。最後一行的 `echo` 是 Claude Code 讀取的 worktree 路徑。將任何其他輸出重定向到 stderr,以免干擾路徑。3199Hook 從 stdin 上的 JSON 輸入讀取 worktree `name`,將新副本簽出到新目錄,並列印目錄路徑。最後一行的 `echo` 是 Claude Code 讀取為 worktree 路徑的內容。將任何其他輸出重定向到 stderr,以便它不干擾路徑。
2688 3200
2689<h4 id="worktreecreate-input">3201<h4 id="worktreecreate-input">
2690 WorktreeCreate 輸入3202 WorktreeCreate 輸入
2691</h4>3203</h4>
2692 3204
2693除了 [通用輸入欄位](#common-input-fields) 外,WorktreeCreate hooks 還接收 `name` 欄位。這是新 worktree 的 slug 識別碼,由使用者指定或自動生成,例如 `bold-oak-a3f2`。3205除了 [常見輸入欄位](#common-input-fields) 外,WorktreeCreate hooks 還會接收 `name` 欄位。這是新 worktree 的 slug 識別碼,由使用者指定或自動生成,例如 `bold-oak-a3f2`。
2694 3206
2695```json theme={null}3207```json theme={null}
2696{3208{
2706 WorktreeCreate 輸出3218 WorktreeCreate 輸出
2707</h4>3219</h4>
2708 3220
2709WorktreeCreate hooks 不使用標準的允許/阻止決定模型。相反,hook 的成功或失敗決定結果。Hook 必須返回建立的 worktree 目錄的絕對路徑:3221WorktreeCreate hooks 不使用標準允許/阻止決策模型。相反,hook 的成功或失敗決定結果。Hook 必須返回建立的 worktree 目錄的路徑:
2710 3222
2711* **命令 hooks**(`type: "command"`):在 stdout 上列印路徑。Claude Code 在讀取該行之前去除 ANSI 逃逸代碼,因此在您的 `echo` 之前列印的 shell 啟動橫幅被忽略。將任何其他 hook 輸出重定向到 stderr。3223* **命令 hooks** (`type: "command"`):將路徑列印為 stdout 的最後一個非空行。Claude Code 在讀取該行之前去除 ANSI 逸出代碼,因此在您的 `echo` 之前列印的 shell 啟動橫幅被忽略。將任何其他 hook 輸出重定向到 stderr。
2712* **HTTP hooks**(`type: "http"`):在回應正文中返回 `{ "hookSpecificOutput": { "hookEventName": "WorktreeCreate", "worktreePath": "/absolute/path" } }`。3224* **HTTP hooks** (`type: "http"`):在回應主體中返回 `{ "hookSpecificOutput": { "hookEventName": "WorktreeCreate", "worktreePath": "/absolute/path" } }`。
2713 3225
2714如果 hook 失敗或不產生路徑,worktree 建立失敗並出現錯誤。3226如果 hook 失敗或不產生路徑,worktree 建立失敗並出現錯誤。
2715 3227
2716Claude Code 根據 hook 執行的目錄解析相對路徑。如果結果路徑不是 Claude Code 可以進入的目錄,工作階段列印一個命名路徑的錯誤並以代碼 1 退出。在 v2.1.205 之前,相對路徑或磁碟上不存在的路徑會在啟動時使工作階段崩潰,使用 `-p` 時會停滯約 30 秒,然後以代碼 0 退出。3228Claude Code 根據 hook 執行的目錄解決相對路徑,摺疊其中的任何 `.` 或 `..` 段。如果結果路徑不是 Claude Code 可以進入的目錄,工作階段列印命名路徑的錯誤並以代碼 1 退出。
3229
3230Claude Code 拒絕包含 `.` 或 `..` 段的絕對路徑,以及通過儲存庫根下方的符號連結的任何路徑,因為提交到儲存庫的符號連結可能將 worktree 重定向到其外部。錯誤命名被拒絕的元件。返回不通過儲存庫內符號連結的規範化路徑。在 v2.1.216 之前,worktree 建立遵循 hook 的路徑而不進行此篩選。
2717 3231
2718<h3 id="worktreeremove">3232<h3 id="worktreeremove">
2719 WorktreeRemove3233 WorktreeRemove
2720</h3>3234</h3>
2721 3235
2722當 worktree 被移除時執行,要麼當您退出 `--worktree` 工作階段並選擇移除它時,要麼當具有 `isolation: "worktree"` 的 subagent 完成時。這是 [WorktreeCreate](#worktreecreate) 的清理對應項。對於基於 git 的 worktrees,Claude Code 使用 `git worktree remove` 自動處理清理。如果您為非 git 版本控制系統配置了 WorktreeCreate hook,請將其與 WorktreeRemove hook 配對以處理清理。沒有它,worktree 目錄會留在磁碟上。3236在移除 worktree 時執行。這是 [WorktreeCreate](#worktreecreate) 的清理對應項。事件在以下情況下觸發:
3237
3238* 您退出 `--worktree` 工作階段並選擇移除它
3239* 具有 `isolation: "worktree"` 的子代理完成
3240* 您刪除 [背景工作階段](/docs/zh-TW/agent-view#what-deleting-a-session-removes),其 worktree 由 hook 建立
3241
3242對於基於 git 的 worktrees,Claude Code 使用 `git worktree remove` 自動處理清理。如果您為非 git 版本控制系統設定了 WorktreeCreate hook,請將其與 WorktreeRemove hook 配對以處理清理。沒有它,worktree 目錄保留在磁碟上。
3243
3244Claude Code 捨棄 WorktreeRemove hook 的 [JSON 輸出欄位](#json-output),例如 `systemMessage` 和 `continue`。
3245
3246對於背景工作階段刪除,Claude Code 在執行 hook 之前驗證儲存的 worktree 路徑,並拒絕在儲存庫根下方是符號連結或通過符號連結的路徑。Hook 僅對仍包含檔案的 worktree 執行,當您在 [代理檢視](/docs/zh-TW/agent-view#what-deleting-a-session-removes) 中確認刪除時;對於這樣的 worktree,[`claude rm`](/docs/zh-TW/agent-view#manage-sessions-from-the-shell) 保持工作階段和 worktree。在 v2.1.216 之前,hook 在儲存的路徑上執行而不進行這些檢查。
2723 3247
2724Claude Code 將 WorktreeCreate 返回的路徑作為 `worktree_path` 在 hook 輸入中傳遞。此範例讀取該路徑並移除目錄:3248Claude Code 將 WorktreeCreate 返回的路徑作為 `worktree_path` 在 hook 輸入中傳遞。此範例讀取該路徑並移除目錄:
2725 3249
2744 WorktreeRemove 輸入3268 WorktreeRemove 輸入
2745</h4>3269</h4>
2746 3270
2747除了 [通用輸入欄位](#common-input-fields) 外,WorktreeRemove hooks 還接收 `worktree_path` 欄位,這是被移除的 worktree 的絕對路徑。3271除了 [常見輸入欄位](#common-input-fields) 外,WorktreeRemove hooks 還會接收 `worktree_path` 欄位,這是正在移除的 worktree 的絕對路徑。
2748 3272
2749```json theme={null}3273```json theme={null}
2750{3274{
2756}3280}
2757```3281```
2758 3282
2759WorktreeRemove hooks 沒有決定控制。它們無法阻止 worktree 移除,但可以執行清理任務,如移除版本控制狀態或存檔變更。Hook 失敗僅在偵錯模式中記錄。3283WorktreeRemove hook 的退出代碼決定結果。當 hook 以非零退出且 `worktree_path` 的目錄仍然存在時,移除失敗:
3284
3285* Worktree 保留在磁碟上,hook 的命令和 stderr 進入 [偵錯日誌](#debug-hooks)。
3286* 如果您刪除背景工作階段,工作階段也保留。[代理檢視](/docs/zh-TW/agent-view#what-deleting-a-session-removes) 中的拒絕訊息報告 hook 如何結束,例如 `exited 1`,引用其 stderr 的開頭,並說明再次刪除工作階段是否移除目錄。
2760 3287
2761<h3 id="precompact">3288<h3 id="precompact">
2762 PreCompact3289 PreCompact
2767匹配器值指示壓縮是手動觸發還是自動觸發:3294匹配器值指示壓縮是手動觸發還是自動觸發:
2768 3295
2769| 匹配器 | 何時觸發 |3296| 匹配器 | 何時觸發 |
2770| :------- | :----------- |3297| :------- | :-------------------------------------------------------------------- |
2771| `manual` | `/compact` |3298| `manual` | `/compact` |
2772| `auto` | 當上下文視窗滿時自動壓縮 |3299| `auto` | 當對話到達 [自動壓縮視窗](/docs/zh-TW/model-config#set-the-auto-compact-window) 時自動壓縮 |
2773 3300
2774退出代碼 2 以阻止壓縮。對於手動 `/compact`,stderr 訊息向使用者顯示。您也可以通過返回帶有 `"decision": "block"` 的 JSON 來阻止。3301以代碼 2 退出以阻止壓縮。對於手動 `/compact`,stderr 訊息顯示給使用者。您也可以透過返回 JSON 搭配 `"decision": "block"` 來阻止。
2775 3302
2776阻止自動壓縮有不同的效果,取決於何時觸發。如果壓縮在上下文限制之前主動觸發,Claude Code 會跳過它,對話繼續未壓縮。如果壓縮被觸發以從已由 API 返回的上下文限制錯誤恢復,基礎錯誤會浮出並且目前請求失敗。3303阻止自動壓縮根據何時觸發有不同的效果。如果壓縮在背景資訊限制之前主動觸發,Claude Code 跳過它,對話繼續未壓縮。如果壓縮被觸發以從 API 已返回的背景資訊限制錯誤恢復,基礎錯誤呈現,目前請求失敗。
3304
3305Claude Code 捨棄 PreCompact hook 的 `systemMessage` 和 `continue` 欄位。
2777 3306
2778<h4 id="precompact-input">3307<h4 id="precompact-input">
2779 PreCompact 輸入3308 PreCompact 輸入
2780</h4>3309</h4>
2781 3310
2782除了 [通用輸入欄位](#common-input-fields) 外,PreCompact hooks 還接收 `trigger` 和 `custom_instructions`。對於 `manual`,`custom_instructions` 包含使用者傳遞到 `/compact` 的內容。對於 `auto`,`custom_instructions` 為空。3311除了 [常見輸入欄位](#common-input-fields) 外,PreCompact hooks 還會接收 `trigger` 和 `custom_instructions`。對於 `manual`,`custom_instructions` 包含使用者傳遞到 `/compact` 的內容,當他們傳遞無內容時為 `null`。對於 `auto`,`custom_instructions` 為 `null`。
2783 3312
2784```json theme={null}3313```json theme={null}
2785{3314{
2788 "cwd": "/Users/...",3317 "cwd": "/Users/...",
2789 "hook_event_name": "PreCompact",3318 "hook_event_name": "PreCompact",
2790 "trigger": "manual",3319 "trigger": "manual",
2791 "custom_instructions": ""3320 "custom_instructions": null
2792}3321}
2793```3322```
2794 3323
2796 PostCompact3325 PostCompact
2797</h3>3326</h3>
2798 3327
2799在 Claude Code 完成壓縮操作後執行。使用此事件來對新的壓縮狀態做出反應,例如記錄生成的摘要或更新外部狀態。3328在 Claude Code 完成壓縮操作後執行。使用此事件對新壓縮狀態做出反應,例如記錄生成的摘要或更新外部狀態。Claude Code 捨棄 PostCompact hook 的 `systemMessage` 和 `continue` 欄位。
2800 3329
2801與 `PreCompact` 相同的匹配器值適用:3330與 `PreCompact` 相同的匹配器值適用:
2802 3331
2803| 匹配器 | 何時觸發 |3332| 匹配器 | 何時觸發 |
2804| :------- | :------------- |3333| :------- | :--------------------------------------------------------------------- |
2805| `manual` | 在 `/compact` 後 |3334| `manual` | 在 `/compact` 後 |
2806| `auto` | 在上下文視窗滿時自動壓縮後 |3335| `auto` | 當對話到達 [自動壓縮視窗](/docs/zh-TW/model-config#set-the-auto-compact-window) 時自動壓縮後 |
2807 3336
2808<h4 id="postcompact-input">3337<h4 id="postcompact-input">
2809 PostCompact 輸入3338 PostCompact 輸入
2810</h4>3339</h4>
2811 3340
2812除了 [通用輸入欄位](#common-input-fields) 外,PostCompact hooks 還接收 `trigger` 和 `compact_summary`。`compact_summary` 欄位包含壓縮操作生成的對話摘要。3341除了 [常見輸入欄位](#common-input-fields) 外,PostCompact hooks 還會接收 `trigger` 和 `compact_summary`。`compact_summary` 欄位包含壓縮操作生成的對話摘要。
2813 3342
2814```json theme={null}3343```json theme={null}
2815{3344{
2822}3351}
2823```3352```
2824 3353
2825PostCompact hooks 沒有決定控制。它們無法影響壓縮結果,但可以執行後續任務。3354PostCompact hooks 沒有決策控制。它們無法影響壓縮結果,但可以執行後續任務。
3355
3356<h3 id="premodelswitch">
3357 PreModelSwitch
3358</h3>
3359
3360在 Claude Code 應用您或用戶端請求的模型切換之前執行。使用它來阻止切換、要求確認或在切換發生前顯示成本。
3361
3362PreModelSwitch 需要 Claude Code v2.1.251 或更新版本。Claude Code 為這些請求執行它:
3363
3364* `/model <name>` 和 `/model` 選擇器
3365* `Option+P` 或 `Alt+P` 模型選擇器
3366* `/config` 中的 Model 設定
3367* 當那改變工作階段的模型時打開 [快速模式](/docs/zh-TW/fast-mode)
3368* 來自 [Agent SDK](/docs/zh-TW/agent-sdk/typescript#query-object) 主機或 [Remote Control](/docs/zh-TW/remote-control) 的 `set_model` 請求,或 `apply_flag_settings` 請求中的模型變更
3369
3370Claude Code 不為它自己進行的切換執行 PreModelSwitch hooks,例如 [自動模型回退](/docs/zh-TW/model-config#automatic-model-fallback) 或恢復工作階段時恢復模型。這些變更僅到達 [PostModelSwitch](#postmodelswitch)。
3371
3372Claude Code 根據工作階段切換到的模型的規範名稱比較匹配器,忽略任何 `[1m]` 後綴。別名(例如 `opus`)、日期模型 ID 和提供者特定 ID(例如 Amazon Bedrock 模型 ID)都匹配它們解決到的一個規範名稱,因此 `claude-opus-5` 涵蓋 Opus 5 的每個拼寫。
3373
3374當 Claude Code 無法確定目標的規範名稱時,例如僅您的 [LLM 閘道](/docs/zh-TW/llm-gateway) 知道的自訂模型 ID,它執行每個 PreModelSwitch hook,無論匹配器如何。阻止的 hook 應該檢查其輸入中的 `to_model` 而不是僅依賴匹配器。
3375
3376將匹配器寫為精確名稱、`|` 分隔清單(例如 `claude-opus-4-6|claude-opus-5`)或正規表達式(例如 `.*opus.*`)。此範例使用精確名稱匹配器並也檢查 hook 輸入中的 `to_model`,因此它拒絕切換到 Opus 4.6,透過以代碼 2 退出,並讓任何其他目標通過:
3377
3378<Tabs>
3379 <Tab title="macOS/Linux">
3380 命令使用 `jq` 檢查 `to_model`:
3381
3382 ```json theme={null}
3383 {
3384 "hooks": {
3385 "PreModelSwitch": [
3386 {
3387 "matcher": "claude-opus-4-6",
3388 "hooks": [
3389 {
3390 "type": "command",
3391 "command": "jq -e '.to_model | test(\"opus-4-6\")' > /dev/null && { echo 'Opus 4.6 is retired for this project. Use a newer model.' >&2; exit 2; }; exit 0"
3392 }
3393 ]
3394 }
3395 ]
3396 }
3397 }
3398 ```
3399 </Tab>
3400
3401 <Tab title="Windows (PowerShell)">
3402 註冊一個命令 hook,透過 PowerShell 執行指令碼:
3403
3404 ```json theme={null}
3405 {
3406 "hooks": {
3407 "PreModelSwitch": [
3408 {
3409 "matcher": "claude-opus-4-6",
3410 "hooks": [
3411 {
3412 "type": "command",
3413 "command": "powershell.exe",
3414 "args": [
3415 "-NoProfile",
3416 "-ExecutionPolicy",
3417 "Bypass",
3418 "-File",
3419 "${CLAUDE_PROJECT_DIR}/.claude/hooks/block-opus-46.ps1"
3420 ]
3421 }
3422 ]
3423 }
3424 ]
3425 }
3426 }
3427 ```
3428
3429 將此指令碼儲存到您專案中的 `.claude/hooks/block-opus-46.ps1`:
3430
3431 ```powershell theme={null}
3432 $hookInput = [Console]::In.ReadToEnd() | ConvertFrom-Json
3433 if ($hookInput.to_model -match 'opus-4-6') {
3434 [Console]::Error.WriteLine('Opus 4.6 is retired for this project. Use a newer model.')
3435 exit 2
3436 }
3437 exit 0
3438 ```
3439 </Tab>
3440</Tabs>
3441
3442若要確認 hook 有效,從執行不同模型的工作階段執行 `/model claude-opus-4-6`。Claude Code 保持目前模型並報告 PreModelSwitch hook 阻止了切換,您的訊息作為原因。
3443
3444<h4 id="premodelswitch-input">
3445 PreModelSwitch 輸入
3446</h4>
3447
3448除了 [常見輸入欄位](#common-input-fields) 外,PreModelSwitch hooks 還會接收此表中的欄位。最後五個描述重新發送對話到新模型的成本,因此 hook 可以在切換發生前顯示該數字。
3449
3450| 欄位 | 類型 | 描述 |
3451| :-------------------------- | :--------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
3452| `from_model` | string | 切換變更的模型 ID |
3453| `to_model` | string | 切換變更為的模型 ID。匹配器根據此模型的規範名稱比較 |
3454| `requested_model` | string or `null` | 請求命名的模型:別名(例如 `opus`)、完整模型 ID 或當請求為預設模型時 `null` |
3455| `source` | string | 請求來自何處:`/model <name>`、`/config` 中的 Model 設定或打開快速模式的 `"command"`;模型選擇器的 `"picker"`;來自 Agent SDK 主機或 Remote Control 的 `set_model` 請求或 `apply_flag_settings` 請求中的模型變更的 `"sdk"` |
3456| `context_tokens` | number | 下一個請求重新發送作為其提示的令牌:主對話中最後回應的輸入、快取讀取、快取建立和輸出令牌結合。第一個回應前為 `0` |
3457| `prompt_cache_warm` | boolean | 目前模型的 prompt cache 是否可能仍然溫暖,意味著切換放棄它 |
3458| `cache_ttl` | string | [Prompt cache 生命週期](/docs/zh-TW/prompt-caching#cache-lifetime) Claude Code 為此工作階段請求:`"5m"` 或 `"1h"` |
3459| `estimated_cache_write_usd` | number | 在 `cache_ttl` 速率下將 `context_tokens` 寫入 `to_model` 上的 prompt cache 的估計成本(美元),不包括下一個回應 |
3460| `pricing` | string | Claude Code 如何定價 `estimated_cache_write_usd`:當您的組織已設定它們時在您的組織自己的速率下為 `"configured"`、在清單價格下為 `"catalog"`,或當 `to_model` 沒有已知價格且 Claude Code 假設預設速率時為 `"default"` |
3461
3462此範例顯示在執行 Sonnet 5 的工作階段中 `/model opus` 的輸入:
3463
3464```json theme={null}
3465{
3466 "session_id": "abc123",
3467 "transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",
3468 "cwd": "/Users/...",
3469 "hook_event_name": "PreModelSwitch",
3470 "from_model": "claude-sonnet-5",
3471 "to_model": "claude-opus-5",
3472 "requested_model": "opus",
3473 "source": "command",
3474 "context_tokens": 182340,
3475 "prompt_cache_warm": true,
3476 "cache_ttl": "5m",
3477 "estimated_cache_write_usd": 1.1396,
3478 "pricing": "catalog"
3479}
3480```
3481
3482<h4 id="premodelswitch-decision-control">
3483 PreModelSwitch 決策控制
3484</h4>
3485
3486`PreModelSwitch` hooks 可以取消切換、要求使用者確認或讓它進行。退出代碼 2 或頂級 `decision: "block"` 取消切換。
3487
3488為了更精細的控制,在 `hookSpecificOutput` 物件中返回 `permissionDecision` 和 `permissionDecisionReason`,如 [PreToolUse](#pretooluse-decision-control) 上。`PreModelSwitch` 接受 `"allow"`、`"deny"` 和 `"ask"`。它不接受 `"defer"`、`updatedInput` 或 `additionalContext`。下表描述兩個欄位:
3489
3490| 欄位 | 描述 |
3491| :------------------------- | :-------------------------------------------------------------------------------------------------------------------------- |
3492| `permissionDecision` | `"allow"` 進行並跳過 [Claude Code 在 prompt cache 溫暖時顯示的確認](/docs/zh-TW/prompt-caching#switching-models)。`"deny"` 取消切換。`"ask"` 提示使用者確認 |
3493| `permissionDecisionReason` | 對於 `"deny"`,顯示給使用者作為切換被阻止的原因,或作為 `set_model` 請求的錯誤返回。對於 `"ask"`,在確認提示中顯示。對於 `"allow"` 忽略 |
3494
3495僅互動式工作階段中的 `/model` 可以顯示 `"ask"` 提示。在每個其他表面上,包括搭配 `-p` 旗標的非互動模式、`/config` 和 `set_model` 請求,Claude Code 將 `"ask"` 視為拒絕。
3496
3497此範例要求使用者確認並引用 `context_tokens` 中的令牌計數:
3498
3499```json theme={null}
3500{
3501 "hookSpecificOutput": {
3502 "hookEventName": "PreModelSwitch",
3503 "permissionDecision": "ask",
3504 "permissionDecisionReason": "Switching now re-sends about 180k tokens to the new model. Continue?"
3505 }
3506}
3507```
3508
3509當多個 PreModelSwitch hooks 返回不同的決策時,優先順序為 `deny` > `ask` > `allow`。
3510
3511Claude Code 無論決策如何都顯示您的 hook 返回的任何 `systemMessage`,因此成本報告 hook 可以返回 `{"systemMessage": "..."}` 並退出 0。
3512
3513在其逾時前未回應的 PreModelSwitch hook 會阻止切換。在 [PreToolUse](#timeouts) 上相比,逾時的命令 hook 讓工具呼叫繼續。此事件的預設逾時為 30 秒。`PreModelSwitch` 僅執行 `command`、`http` 和 `mcp_tool` hooks,因此 `prompt` 和 `agent` 預設不適用。
3514
3515以 0 或 2 以外的代碼退出且不列印 JSON 決策的 hook 不阻止:Claude Code 顯示其 stderr 並應用切換,如 [其他退出代碼](#other-exit-codes) 下所述。
3516
3517<h3 id="postmodelswitch">
3518 PostModelSwitch
3519</h3>
3520
3521在工作階段的模型變更後執行。使用它來給予 Claude 模型特定指導,而不編輯每個 CLAUDE.md,例如僅在某些模型上適用的組織範圍指令。
3522
3523PostModelSwitch 需要 Claude Code v2.1.251 或更新版本。它無法阻止,因為模型已變更。Claude Code 在這些變更後執行 PostModelSwitch hooks:
3524
3525* 您或用戶端請求的切換
3526* [自動模型回退](/docs/zh-TW/model-config#automatic-model-fallback),改變工作階段的模型
3527* 設定(例如 [`opusplan`](/docs/zh-TW/model-config#opusplan-model-setting))進入或離開計畫模式
3528* Claude Code 恢復工作階段時恢復模型
3529
3530當 [回退模型鏈](/docs/zh-TW/model-config#fallback-model-chains) 中的模型服務回合時,Claude Code 不執行 PostModelSwitch hooks,因為該替換持續一個回合並保持工作階段的模型不變。
3531
3532匹配器遵循與 [PreModelSwitch](#premodelswitch) 相同的規則:Claude Code 根據工作階段切換到的模型的規範名稱比較它。
3533
3534此範例在工作階段的模型變更為任何 Opus 模型時新增指導:
3535
3536```json theme={null}
3537{
3538 "hooks": {
3539 "PostModelSwitch": [
3540 {
3541 "matcher": ".*opus.*",
3542 "hooks": [
3543 {
3544 "type": "command",
3545 "command": "echo 'On Opus, delegate implementation work to subagents and keep this conversation for planning and review.'"
3546 }
3547 ]
3548 }
3549 ]
3550 }
3551}
3552```
3553
3554若要確認 hook 有效,從執行不同模型的工作階段切換到 Opus 模型,例如從 Sonnet 工作階段執行 `/model opus`,然後詢問 Claude 它對目前模型有什麼指導。
3555
3556<h4 id="postmodelswitch-input">
3557 PostModelSwitch 輸入
3558</h4>
3559
3560PostModelSwitch hooks 接收與 [PreModelSwitch](#premodelswitch-input) 相同的欄位,其中 `hook_event_name` 設定為 `"PostModelSwitch"` 和兩個更多 `source` 值:`"auto"` 用於自動回退或 Claude Code 自己進行的其他變更,`"resume"` 用於恢復工作階段時恢復的模型。
3561
3562當 `source` 為 `"auto"` 時 `requested_model` 為 `null`。當 `source` 為 `"resume"` 時,它是 Claude Code 恢復的儲存模型設定。
3563
3564<h4 id="postmodelswitch-decision-control">
3565 PostModelSwitch 決策控制
3566</h4>
3567
3568Claude Code 在下一個切換後的請求中採用您的 hook 的 [純文字 stdout](#exit-code-0) 退出 0,或 JSON 輸出中的 `additionalContext`,並將其傳遞給 Claude。除了所有 hooks 可用的 [JSON 輸出欄位](#json-output) 外,您可以返回:
3569
3570| 欄位 | 描述 |
3571| :------------------ | :------------------------------------------------------------------------ |
3572| `additionalContext` | 與下一個請求一起新增到 Claude 背景資訊的字串。請參閱 [為 Claude 新增背景資訊](#add-context-for-claude) |
3573
3574如果 hook 在您發送下一個提示後五秒內未完成,Claude Code 發送該請求而不輸出,並改為將其附加到下一個請求。如果模型在下一個請求之前變更多次,Claude Code 僅傳遞最後切換目標模型的輸出。
2826 3575
2827<h3 id="sessionend">3576<h3 id="sessionend">
2828 SessionEnd3577 SessionEnd
2829</h3>3578</h3>
2830 3579
2831當 Claude Code 工作階段結束時執行。適用於清理任務、記錄工作階段統計資訊或儲存工作階段狀態。支援匹配器以按退出原因篩選。3580在 Claude Code 工作階段結束時執行。適用於清理任務、記錄工作階段統計資訊或儲存工作階段狀態。支援匹配器以按退出原因篩選。
2832 3581
2833輸入中的 `reason` 欄位指示工作階段為何結束:3582`reason` 欄位在 hook 輸入中指示工作階段為什麼結束:
2834 3583
2835| 原因 | 描述 |3584| 原因 | 描述 |
2836| :---------------------------- | :--------------------- |3585| :---------------------------- | :------------------------------------------------------- |
2837| `clear` | 使用 `/clear` 命令清除工作階段 |3586| `clear` | 使用 `/clear` 命令清除工作階段 |
2838| `resume` | 通過互動式 `/resume` 切換工作階段 |3587| `resume` | 透過互動式 `/resume` 切換工作階段 |
2839| `logout` | 使用者登出 |3588| `logout` | 使用者登出 |
2840| `prompt_input_exit` | 使用者在提示輸入可見時退出 |3589| `prompt_input_exit` | 使用者在提示輸入可見時退出 |
2841| `bypass_permissions_disabled` | 繞過權限模式被停用 |
2842| `other` | 其他退出原因 |3590| `other` | 其他退出原因 |
3591| `bypass_permissions_disabled` | 在 v2.1.234 中移除;Claude Code 不發送它。從您的 `SessionEnd` 匹配器中刪除它 |
2843 3592
2844<h4 id="sessionend-input">3593<h4 id="sessionend-input">
2845 SessionEnd 輸入3594 SessionEnd 輸入
2846</h4>3595</h4>
2847 3596
2848除了 [通用輸入欄位](#common-input-fields) 外,SessionEnd hooks 還接收指示工作階段為何結束的 `reason` 欄位。有關所有值,請參閱上面的原因表。3597除了 [常見輸入欄位](#common-input-fields) 外,SessionEnd hooks 還會接收指示工作階段為什麼結束的 `reason` 欄位。請參閱上面的 [原因表](#sessionend) 以了解所有值。
2849 3598
2850```json theme={null}3599```json theme={null}
2851{3600{
2857}3606}
2858```3607```
2859 3608
2860SessionEnd hooks 沒有決定控制。它們無法阻止工作階段終止,但可以執行清理任務。3609SessionEnd hooks 沒有決策控制。它們無法阻止工作階段終止,但可以執行清理任務。Claude Code 捨棄它們的 [JSON 輸出欄位](#json-output),例如 `systemMessage`。
3610
3611SessionEnd hooks 的預設逾時為 1.5 秒。它在您退出、執行 `/clear` 或使用互動式 `/resume` 切換工作階段時適用。您可以透過兩種方式給予 hook 更多時間:
2861 3612
2862SessionEnd hooks 的預設逾時為 1.5 秒。這適用於工作階段退出、`/clear` 和通過互動式 `/resume` 切換工作階段。如果 hook 需要更多時間,請在 hook 配置中設定每個 hook 的 `timeout`。整體預算會自動提高到設定檔中配置的最高每個 hook 逾時,最高 60 秒。在外掛程式提供的 hooks 上設定的逾時不會提高預算。要明確覆蓋預算,請在毫秒中設定 `CLAUDE_CODE_SESSIONEND_HOOKS_TIMEOUT_MS` 環境變數。3613* **每個 hook `timeout`**:在該 hook 的設定中設定 `timeout`。整體預算自動上升以符合您設定檔中最高每個 hook `timeout`,最多 60 秒。如果您以這種方式提高預算,沒有自己 `timeout` 的 hook 仍保持預設。在外掛提供的 hooks 上設定的逾時不提高預算。
3614* **`CLAUDE_CODE_SESSIONEND_HOOKS_TIMEOUT_MS`**:以毫秒設定此環境變數以明確覆寫預算。您設定的值也成為每個沒有自己 `timeout` 的 hook 的逾時。
3615
3616此範例將預算設定為 5 秒:
2863 3617
2864```bash theme={null}3618```bash theme={null}
2865CLAUDE_CODE_SESSIONEND_HOOKS_TIMEOUT_MS=5000 claude3619CLAUDE_CODE_SESSIONEND_HOOKS_TIMEOUT_MS=5000 claude
2866```3620```
2867 3621
3622在 v2.1.268 之前,`CLAUDE_CODE_SESSIONEND_HOOKS_TIMEOUT_MS` 僅提高整體預算,沒有自己 `timeout` 的 hook 仍在 1.5 秒後被取消。
3623
2868<h3 id="elicitation">3624<h3 id="elicitation">
2869 Elicitation3625 Elicitation
2870</h3>3626</h3>
2871 3627
2872當 MCP 伺服器在任務中途請求使用者輸入時執行。預設情況下,Claude Code 顯示互動式對話框供使用者回應。Hooks 可以攔截此請求並以程式方式回應,完全跳過對話框。3628在 MCP 伺服器在任務中期請求使用者輸入時執行。預設情況下,Claude Code 為使用者顯示互動式對話以回應。Hooks 可以攔截此請求並以程式設計方式回應,完全跳過對話。
2873 3629
2874匹配器欄位與 MCP 伺服器名稱匹配。3630匹配器欄位根據 MCP 伺服器名稱匹配。
2875 3631
2876<h4 id="elicitation-input">3632<h4 id="elicitation-input">
2877 Elicitation 輸入3633 Elicitation 輸入
2878</h4>3634</h4>
2879 3635
2880除了 [通用輸入欄位](#common-input-fields) 外,Elicitation hooks 還接收 `mcp_server_name`、`message` 和可選的 `mode`、`url`、`elicitation_id` 和 `requested_schema` 欄位。3636除了 [常見輸入欄位](#common-input-fields) 外,Elicitation hooks 還會接收 `mcp_server_name`、`message` 和可選的 `mode`、`url`、`elicitation_id` 和 `requested_schema` 欄位。
2881 3637
2882對於表單模式徵詢(最常見的情況):3638對於表單模式引出,最常見的情況:
2883 3639
2884```json theme={null}3640```json theme={null}
2885{3641{
2886 "session_id": "abc123",3642 "session_id": "abc123",
2887 "transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",3643 "transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",
2888 "cwd": "/Users/...",3644 "cwd": "/Users/...",
2889 "permission_mode": "default",
2890 "hook_event_name": "Elicitation",3645 "hook_event_name": "Elicitation",
2891 "mcp_server_name": "my-mcp-server",3646 "mcp_server_name": "my-mcp-server",
2892 "message": "Please provide your credentials",3647 "message": "Please provide your credentials",
2900}3655}
2901```3656```
2902 3657
2903對於 URL 模式徵詢(基於瀏覽器的驗證):3658對於 URL 模式引出,用於基於瀏覽器的驗證:
2904 3659
2905```json theme={null}3660```json theme={null}
2906{3661{
2907 "session_id": "abc123",3662 "session_id": "abc123",
2908 "transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",3663 "transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",
2909 "cwd": "/Users/...",3664 "cwd": "/Users/...",
2910 "permission_mode": "default",
2911 "hook_event_name": "Elicitation",3665 "hook_event_name": "Elicitation",
2912 "mcp_server_name": "my-mcp-server",3666 "mcp_server_name": "my-mcp-server",
2913 "message": "Please authenticate",3667 "message": "Please authenticate",
2920 Elicitation 輸出3674 Elicitation 輸出
2921</h4>3675</h4>
2922 3676
2923要以程式方式回應而不顯示對話框,請返回帶有 `hookSpecificOutput` 的 JSON 物件:3677若要以程式設計方式回應而不顯示對話,請返回具有 `hookSpecificOutput` 的 JSON 物件:
2924 3678
2925```json theme={null}3679```json theme={null}
2926{3680{
2937| 欄位 | 值 | 描述 |3691| 欄位 | 值 | 描述 |
2938| :-------- | :-------------------------- | :----------------------------------- |3692| :-------- | :-------------------------- | :----------------------------------- |
2939| `action` | `accept`、`decline`、`cancel` | 是否接受、拒絕或取消請求 |3693| `action` | `accept`、`decline`、`cancel` | 是否接受、拒絕或取消請求 |
2940| `content` | 物件 | 要提交的表單欄位值。僅在 `action` 為 `accept` 時使用 |3694| `content` | object | 要提交的表單欄位值。僅在 `action` 為 `accept` 時使用 |
3695
3696退出代碼 2 拒絕引出。Claude Code 不在任何地方顯示您的 stderr 訊息。
2941 3697
2942退出代碼 2 拒絕徵詢並向使用者顯示 stderr。3698Claude Code 作用於 Elicitation hook 的 JSON 輸出中的 `hookSpecificOutput` 並捨棄 `systemMessage` 和 `continue`。
2943 3699
2944<h3 id="elicitationresult">3700<h3 id="elicitationresult">
2945 ElicitationResult3701 ElicitationResult
2946</h3>3702</h3>
2947 3703
2948在使用者回應 MCP 徵詢後執行。Hooks 可以觀察、修改或阻止回應,然後將其發送回 MCP 伺服器。3704在使用者回應 MCP 引出後執行。Hooks 可以觀察、修改或阻止回應,然後將其發送回 MCP 伺服器。
2949 3705
2950匹配器欄位與 MCP 伺服器名稱匹配。3706匹配器欄位根據 MCP 伺服器名稱匹配。
2951 3707
2952<h4 id="elicitationresult-input">3708<h4 id="elicitationresult-input">
2953 ElicitationResult 輸入3709 ElicitationResult 輸入
2954</h4>3710</h4>
2955 3711
2956除了 [通用輸入欄位](#common-input-fields) 外,ElicitationResult hooks 還接收 `mcp_server_name`、`action` 和可選的 `mode`、`elicitation_id` 和 `content` 欄位。3712除了 [常見輸入欄位](#common-input-fields) 外,ElicitationResult hooks 還會接收 `mcp_server_name`、`action` 和可選的 `mode`、`elicitation_id` 和 `content` 欄位。
2957 3713
2958```json theme={null}3714```json theme={null}
2959{3715{
2960 "session_id": "abc123",3716 "session_id": "abc123",
2961 "transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",3717 "transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",
2962 "cwd": "/Users/...",3718 "cwd": "/Users/...",
2963 "permission_mode": "default",
2964 "hook_event_name": "ElicitationResult",3719 "hook_event_name": "ElicitationResult",
2965 "mcp_server_name": "my-mcp-server",3720 "mcp_server_name": "my-mcp-server",
2966 "action": "accept",3721 "action": "accept",
2974 ElicitationResult 輸出3729 ElicitationResult 輸出
2975</h4>3730</h4>
2976 3731
2977要覆蓋使用者的回應,請返回帶有 `hookSpecificOutput` 的 JSON 物件:3732若要覆寫使用者的回應,請返回具有 `hookSpecificOutput` 的 JSON 物件:
2978 3733
2979```json theme={null}3734```json theme={null}
2980{3735{
2988 3743
2989| 欄位 | 值 | 描述 |3744| 欄位 | 值 | 描述 |
2990| :-------- | :-------------------------- | :---------------------------------- |3745| :-------- | :-------------------------- | :---------------------------------- |
2991| `action` | `accept`、`decline`、`cancel` | 覆蓋使用者的操作 |3746| `action` | `accept`、`decline`、`cancel` | 覆寫使用者的動作 |
2992| `content` | 物件 | 覆蓋表單欄位值。僅在 `action` 為 `accept` 時有意義 |3747| `content` | object | 覆寫表單欄位值。僅在 `action` 為 `accept` 時有意義 |
3748
3749退出代碼 2 阻止回應,將有效動作變更為 `decline`。Claude Code 不在任何地方顯示您的 stderr 訊息。
2993 3750
2994退出代碼 2 阻止回應,將有效操作變更為 `decline`。3751Claude Code 作用於 ElicitationResult hook 的 JSON 輸出中的 `hookSpecificOutput` 並捨棄 `systemMessage` 和 `continue`。
2995 3752
2996<h2 id="prompt-based-hooks">3753<h2 id="prompt-based-hooks">
2997 基於提示的 hooks3754 基於提示的 hooks
3019 3776
3020* `ConfigChange`3777* `ConfigChange`
3021* `CwdChanged`3778* `CwdChanged`
3779* `DirectoryAdded`
3022* `Elicitation`3780* `Elicitation`
3023* `ElicitationResult`3781* `ElicitationResult`
3024* `FileChanged`3782* `FileChanged`
3025* `InstructionsLoaded`3783* `InstructionsLoaded`
3784* `MessageDisplay`
3026* `Notification`3785* `Notification`
3027* `PostCompact`3786* `PostCompact`
3787* `PostModelSwitch`
3028* `PreCompact`3788* `PreCompact`
3789* `PreModelSwitch`
3029* `SessionEnd`3790* `SessionEnd`
3030* `StopFailure`3791* `StopFailure`
3031* `SubagentStart`3792* `SubagentStart`
3032* `WorktreeCreate`3793* `WorktreeCreate`
3033* `WorktreeRemove`3794* `WorktreeRemove`
3034 3795
3035`SessionStart` 和 `Setup` 支援 `command` 和 `mcp_tool` hooks。它們不支援 `http`、`prompt` 或 `agent` hooks。3796`SessionStart` 和 `Setup` 支援 `command` 和 `mcp_tool` hooks,而 [MCP tool hook 欄位](#mcp-tool-hook-fields)描述了它們的 `mcp_tool` hooks 何時執行。它們不支援 `http`、`prompt` 或 `agent` hooks。
3036 3797
3037<h3 id="how-prompt-based-hooks-work">3798<h3 id="how-prompt-based-hooks-work">
3038 基於提示的 hooks 如何工作3799 基於提示的 hooks 如何工作
3048 提示 hook 配置3809 提示 hook 配置
3049</h3>3810</h3>
3050 3811
3051將 `type` 設定為 `"prompt"` 並提供 `prompt` 字串而不是 `command`。使用 `$ARGUMENTS` 佔位符將 hook 的 JSON 輸入資料注入到您的提示文字中。Claude Code 將組合的提示和輸入發送到快速 Claude 模型,該模型返回 JSON 決定。3812將 `type` 設定為 `"prompt"` 並提供 `prompt` 字串而不是 `command`。使用 `$ARGUMENTS` 佔位符將 hook 的 JSON 輸入資料注入到您的提示文字中。
3052 3813
3053此 `Stop` hook 詢問 LLM 在允許 Claude 完成之前是否應該停止:3814此 `Stop` hook 詢問 LLM 在允許 Claude 完成之前是否應該停止:
3054 3815
3070```3831```
3071 3832
3072| 欄位 | 必需 | 描述 |3833| 欄位 | 必需 | 描述 |
3073| :---------------- | :- | :------------------------------------------------------------------------------------------------------------------------------------------- |3834| :---------------- | :- | :----------------------------------------------------------------------------------------------------- |
3074| `type` | 是 | 必須為 `"prompt"` |3835| `type` | 是 | 必須為 `"prompt"` |
3075| `prompt` | 是 | 要發送到 LLM 的提示文字。使用 `$ARGUMENTS` 作為 hook 輸入 JSON 的佔位符。如果 `$ARGUMENTS` 不存在,輸入 JSON 會附加到提示 |3836| `prompt` | 是 | 要發送到 LLM 的提示文字。使用 `$ARGUMENTS` 作為 hook 輸入 JSON 的佔位符。如果 `$ARGUMENTS` 不存在,輸入 JSON 會附加到提示 |
3076| `model` | 否 | 用於評估的模型。預設為快速模型 |3837| `model` | 否 | 用於評估的模型。預設為快速模型 |
3077| `timeout` | 否 | 逾時(秒)。預設值:30 |3838| `timeout` | 否 | 逾時(秒)。預設值:30 |
3078| `continueOnBlock` | 否 | 當提示返回 `ok: false` 時,將原因反饋給 Claude 並繼續轉換而不是停止。預設值:`false`。在結果 `decision: "block"` 上實現為 `continue: true`。請參閱[回應架構](#response-schema)以了解每個事件的行為 |3839| `continueOnBlock` | 否 | 在適用的事件上,`true` 將 `ok: false` 原因反饋給 Claude 並繼續而不是結束轉換。預設值:`false`。請參閱[回應架構](#response-schema)以了解每個事件的行為 |
3079 3840
3080<h3 id="response-schema">3841<h3 id="response-schema">
3081 回應架構3842 回應架構
3086```json theme={null}3847```json theme={null}
3087{3848{
3088 "ok": true | false,3849 "ok": true | false,
3089 "reason": "Explanation for the decision"3850 "reason": "Explanation for the decision",
3851 "impossible": true | false
3090}3852}
3091```3853```
3092 3854
3093| 欄位 | 描述 |3855| 欄位 | 描述 |
3094| :------- | :------------------------------------------------------ |3856| :----------- | :-------------------------------------------------------------------------------------------------------------- |
3095| `ok` | `true` 允許操作。`false` 產生 `decision: "block"`。請參閱下面的每個事件行為 |3857| `ok` | `true` 允許操作。`false` 時,請參閱下面的每個事件行為 |
3096| `reason` | 當 `ok` 為 `false` 時必需。用作阻止原因 |3858| `reason` | 當 `ok` 為 `false` 時必需 |
3859| `impossible` | 選用。當模型判斷條件永遠無法滿足時,模型會以 `ok: false` 返回它。在 `Stop` 和 `SubagentStop` 上,Claude Code 會讓轉換結束而不是反饋原因。代理 hooks 和其他事件會忽略它 |
3097 3860
3098`ok: false` 時發生的情況取決於事件:3861`ok: false` 時發生的情況取決於事件:
3099 3862
3100* `Stop` 和 `SubagentStop`:原因被反饋給 Claude 作為其下一個指令,轉換繼續3863* `Stop` 和 `SubagentStop`:原因被反饋給 Claude 作為其下一個指令,轉換繼續,除非回應也設定 `impossible: true`,在這種情況下 Claude Code 允許停止,轉換結束
3101* `PreToolUse`:工具呼叫被拒絕,原因作為工具錯誤返回給 Claude,相當於命令 hook 的 `permissionDecision: "deny"`3864* `PreToolUse`:工具呼叫被拒絕;預設情況下轉換結束,拒絕原因在聊天中顯示為警告行。設定 `continueOnBlock: true` 以改為將原因作為工具錯誤返回給 Claude,使其可以調整並繼續,相當於命令 hook 的 `permissionDecision: "deny"`。在 v2.1.210 之前,拒絕原因被作為工具錯誤返回給 Claude,轉換繼續
3102* `PostToolUse`:預設情況下轉換結束,原因在聊天中顯示為警告行。設定 `continueOnBlock: true` 以將原因反饋給 Claude 並繼續轉換3865* `PostToolUse`:預設情況下轉換結束,原因在聊天中顯示為警告行。設定 `continueOnBlock: true` 以將原因反饋給 Claude 並繼續轉換
3103* `PostToolBatch`、`UserPromptSubmit` 和 `UserPromptExpansion`:轉換結束,原因顯示為警告行。這些事件在 `decision: "block"` 上結束轉換,無論 `continue` 如何3866* `PostToolBatch`、`UserPromptSubmit` 和 `UserPromptExpansion`:轉換結束,原因顯示為警告行。這些事件在 `decision: "block"` 上結束轉換,無論 `continue` 如何
3104* `PostToolUseFailure`、`TaskCreated` 和 `TaskCompleted`:原因作為工具錯誤返回給 Claude,類似於 `PreToolUse`3867* `PostToolUseFailure` 和 `TaskCreated`:原因作為工具錯誤返回給 Claude,轉換繼續,無論 `continueOnBlock` 如何
3868* `TaskCompleted`:當它因為任務在轉換期間被標記為完成而觸發時,原因作為工具錯誤返回給 Claude,轉換繼續,無論 `continueOnBlock` 如何。當它因為隊友停止而觸發時,它的行為類似 `TeammateIdle` 並預設停止隊友
3105* `TeammateIdle`:預設情況下隊友停止,原因顯示為警告行。設定 `continueOnBlock: true` 以將原因反饋給隊友並保持其工作狀態3869* `TeammateIdle`:預設情況下隊友停止,原因顯示為警告行。設定 `continueOnBlock: true` 以將原因反饋給隊友並保持其工作狀態
3106* `PermissionRequest`:`ok: false` 沒有效果。要從 hook 拒絕批准,請使用[命令 hook](#command-hook-fields)返回 `hookSpecificOutput.decision.behavior: "deny"`3870* `PermissionRequest`:`ok: false` 沒有效果。要從 hook 拒絕批准,請使用[命令 hook](#command-hook-fields)返回 `hookSpecificOutput.decision.behavior: "deny"`
3107* `PermissionDenied`:`ok: false` 沒有效果,因為拒絕已經發生。此事件讀取的唯一輸出是 `hookSpecificOutput.retry`,提示和代理 hooks 無法設定。它們在此事件上執行,但其輸出被丟棄。使用[命令 hook](#command-hook-fields)返回 `retry`3871* `PermissionDenied`:`ok: false` 沒有效果,因為拒絕已經發生。此事件讀取的唯一輸出是 `hookSpecificOutput.retry`,提示和代理 hooks 無法設定。它們在此事件上執行,但其輸出被丟棄。使用[命令 hook](#command-hook-fields)返回 `retry`
3112 在停止前檢查多個條件3876 在停止前檢查多個條件
3113</h3>3877</h3>
3114 3878
3115此 `Stop` hook 使用詳細提示在允許 Claude 停止之前檢查三個條件。`SubagentStop` hooks 使用相同的格式來評估 [subagent](/docs/zh-TW/sub-agents) 是否應該停止。如果 `"ok"` 為 `false`,Claude 繼續工作,提供的原因作為其下一個指令:3879此 `Stop` hook 使用詳細提示在允許 Claude 停止之前檢查三個條件。`SubagentStop` hooks 使用相同的格式來評估 [subagent](/docs/zh-TW/sub-agents) 是否應該停止。如果模型因為條件尚未滿足而返回 `"ok": false`,Claude 繼續工作,提供的原因作為其下一個指令:
3116 3880
3117```json theme={null}3881```json theme={null}
3118{3882{
31511. Claude Code 生成一個 subagent,使用您的提示和 hook 的 JSON 輸入39151. Claude Code 生成一個 subagent,使用您的提示和 hook 的 JSON 輸入
31522. Subagent 可以使用 Read、Grep 和 Glob 等工具進行調查39162. Subagent 可以使用 Read、Grep 和 Glob 等工具進行調查
31533. 在最多 50 輪後,subagent 返回結構化的 `{ "ok": true/false }` 決定39173. 在最多 50 輪後,subagent 返回結構化的 `{ "ok": true/false }` 決定
31544. Claude Code 以與提示 hook 相同的方式處理決定39184. Claude Code 允許該動作(如果 `ok` 是 `true`)。如果 `ok` 是 `false`,Claude Code 會以與提示 hook 相同的方式處理阻止,該提示 hook 在該事件上具有 `continueOnBlock: true`,如[回應架構](#response-schema)下所列
3155 3919
3156代理 hooks 在驗證需要檢查實際檔案或測試輸出時很有用,而不僅僅是評估 hook 輸入資料。3920代理 hooks 在驗證需要檢查實際檔案或測試輸出時很有用,而不僅僅是評估 hook 輸入資料。
3157 3921
3159 代理 hook 配置3923 代理 hook 配置
3160</h3>3924</h3>
3161 3925
3162將 `type` 設定為 `"agent"` 並提供 `prompt` 字串。配置欄位與[提示 hooks](#prompt-hook-configuration) 相同,但逾時更長:3926將 `type` 設定為 `"agent"` 並提供 `prompt` 字串,使用 `$ARGUMENTS` 作為 hook 輸入 JSON 的佔位符。配置欄位與[提示 hooks](#prompt-hook-configuration) 相同,除了代理 hooks 具有更長的預設逾時 60 秒,且沒有 `continueOnBlock` 欄位。
3163
3164| 欄位 | 必需 | 描述 |
3165| :-------- | :- | :----------------------------------------------- |
3166| `type` | 是 | 必須為 `"agent"` |
3167| `prompt` | 是 | 描述要驗證的內容的提示。使用 `$ARGUMENTS` 作為 hook 輸入 JSON 的佔位符 |
3168| `model` | 否 | 要使用的模型。預設為快速模型 |
3169| `timeout` | 否 | 逾時(秒)。預設值:60 |
3170 3927
3171回應架構與提示 hooks 相同:`{ "ok": true }` 允許或 `{ "ok": false, "reason": "..." }` 阻止。3928回應架構是 `{ "ok": true }` 允許或 `{ "ok": false, "reason": "..." }` 阻止。在 `ok: false` 時,Claude Code 會以處理[提示 hook 且具有 `continueOnBlock: true`](#response-schema) 的相同方式處理代理 hook;代理 hooks 沒有 `continueOnBlock` 欄位,且不支援提示 hook 的 `impossible` 欄位。
3172 3929
3173此 `Stop` hook 驗證所有單元測試通過,然後允許 Claude 完成:3930此 `Stop` hook 驗證所有單元測試通過,然後允許 Claude 完成:
3174 3931
3202 3959
3203將 `"async": true` 新增到命令 hook 的配置以在背景執行它而不阻止 Claude。此欄位僅在 `type: "command"` hooks 上可用。3960將 `"async": true` 新增到命令 hook 的配置以在背景執行它而不阻止 Claude。此欄位僅在 `type: "command"` hooks 上可用。
3204 3961
3205此 hook 在每個 `Write` 工具呼叫後執行測試指令碼。Claude 立即繼續工作,同時 `run-tests.sh` 執行最多 120 秒。當指令碼完成時,其輸出在下一個對話輪次上傳遞:3962此 hook 在每個 `Write` 工具呼叫後執行測試指令碼。Claude 立即繼續工作,同時 `run-tests.sh` 執行。當指令碼完成時,其輸出在下一個對話輪次上傳遞:
3206 3963
3207```json theme={null}3964```json theme={null}
3208{3965{
3214 {3971 {
3215 "type": "command",3972 "type": "command",
3216 "command": "/path/to/run-tests.sh",3973 "command": "/path/to/run-tests.sh",
3217 "async": true,3974 "async": true
3218 "timeout": 120
3219 }3975 }
3220 ]3976 ]
3221 }3977 }
3224}3980}
3225```3981```
3226 3982
3227`timeout` 欄位設定背景程序的最大時間(秒)。如果未指定,非同步 hooks 使用與同步 hooks 相同的 10 分鐘預設值。3983一旦非同步 hook 在背景執行,Claude Code 不會對其強制執行 `timeout`。Claude Code 仍然會對使用 `asyncRewake` 執行的 hook 強制執行 `timeout`。
3984
3985Claude Code 只在工作階段執行時傳遞非同步 hook 的結果:
3986
3987* 在[非互動模式](/docs/zh-TW/headless)中使用 `-p` 旗標,Claude Code 會在清理時終止任何仍在執行的非同步 hook,並以 `cancelled` 結果完成它
3988* 如果你的 hook 工作必須超越 `claude -p` 工作階段,請從它啟動一個完全分離的程序
3228 3989
3229<h3 id="how-async-hooks-execute">3990<h3 id="how-async-hooks-execute">
3230 非同步 hooks 如何執行3991 非同步 hooks 如何執行
3232 3993
3233當非同步 hook 觸發時,Claude Code 啟動 hook 程序並立即繼續,而不等待它完成。Hook 在 stdin 上接收與同步 hook 相同的 JSON 輸入。3994當非同步 hook 觸發時,Claude Code 啟動 hook 程序並立即繼續,而不等待它完成。Hook 在 stdin 上接收與同步 hook 相同的 JSON 輸入。
3234 3995
3235背景程序退出後,如果 hook 產生了帶有 `additionalContext` 欄位的 JSON 回應,該內容會在下一個對話輪次上作為上下文傳遞給 Claude。`systemMessage` 欄位會顯示給你,而不是 Claude。3996背景程序退出後,Claude Code 會在下一個對話輪次將 hook 的 JSON 回應中的 `additionalContext` 和 `systemMessage` 欄位傳遞給 Claude。與同步 hook 的 `systemMessage` 不同,這兩個欄位都不會顯示給你。
3236 3997
3237Claude Code 驗證該 JSON 回應是否符合與同步 hooks 相同的[輸出結構](#json-output),並捨棄任何值類型錯誤的欄位,例如不是字串的 `systemMessage`,而不是傳遞它。使用 `--debug` 執行以查看命名每個捨棄欄位的警告。在 v2.1.202 之前,來自非同步 hook 的格式不正確的 JSON 輸出可能會導致工作階段崩潰,每次恢復工作階段時都會重複發生崩潰。3998Claude Code 驗證該 JSON 回應是否符合與同步 hooks 相同的[輸出結構](#json-output),並捨棄任何值類型錯誤的欄位,例如不是字串的 `systemMessage`,而不是傳遞它。使用 `--debug` 執行以查看命名每個捨棄欄位的警告。在 v2.1.202 之前,來自非同步 hook 的格式不正確的 JSON 輸出可能會導致工作階段崩潰,每次恢復工作階段時都會重複發生崩潰。
3238 3999
3269jq -nc --arg msg "$MSG" '{hookSpecificOutput: {hookEventName: "PostToolUse", additionalContext: $msg}}'4030jq -nc --arg msg "$MSG" '{hookSpecificOutput: {hookEventName: "PostToolUse", additionalContext: $msg}}'
3270```4031```
3271 4032
3272然後將此配置新增到專案根目錄中的 `.claude/settings.json`。`async: true` 標誌讓 Claude 在測試執行時繼續工作:4033然後將此配置新增到專案根目錄中的 `.claude/settings.json`。`async: true` 旗標讓 Claude 在測試執行時繼續工作:
3273 4034
3274```json theme={null}4035```json theme={null}
3275{4036{
3282 "type": "command",4043 "type": "command",
3283 "command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/run-tests-async.sh",4044 "command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/run-tests-async.sh",
3284 "args": [],4045 "args": [],
3285 "async": true,4046 "async": true
3286 "timeout": 300
3287 }4047 }
3288 ]4048 ]
3289 }4049 }
3296 限制4056 限制
3297</h3>4057</h3>
3298 4058
3299非同步 hooks 與同步 hooks 相比有幾個限制:4059非同步 hooks 與同步 hooks 相比有額外的限制:
3300 4060
3301* 僅 `type: "command"` hooks 支援 `async`。基於提示的 hooks 無法非同步執行。4061* Hook 輸出在下一個對話輪次上傳遞。如果工作階段閒置,回應會等待直到下一個使用者互動。例外:退出代碼為 2 的 `asyncRewake` hook 即使在工作階段閒置時也會立即喚醒 Claude。
3302* 非同步 hooks 無法阻止工具呼叫或返回決定。到 hook 完成時,觸發操作已經進行。
3303* Hook 輸出在下一個對話輪次上傳遞。如果工作階段閒置,回應會等待直到下一個使用者互動。例外:`asyncRewake` hook 在退出代碼 2 時喚醒 Claude,即使工作階段閒置。
3304* 每次執行都會建立一個單獨的背景程序。同一非同步 hook 的多次觸發之間沒有去重。4062* 每次執行都會建立一個單獨的背景程序。同一非同步 hook 的多次觸發之間沒有去重。
3305 4063
3306<h2 id="security-considerations">4064<h2 id="security-considerations">
3311 免責聲明4069 免責聲明
3312</h3>4070</h3>
3313 4071
3314命令 hooks 以您的系統使用者的完整權限執行。
3315
3316<Warning>4072<Warning>
3317 命令 hooks 以您的完整使用者權限執行 shell 命令。它們可以修改、刪除或存取您的使用者帳戶可以存取的任何檔案。在將任何 hook 命令新增到您的配置之前,請審查並測試它們。4073 命令 hooks 以您的完整使用者權限執行 shell 命令。它們可以修改、刪除或存取您的使用者帳戶可以存取的任何檔案。在將任何 hook 命令新增到您的設定之前,請審查並測試它們。
3318</Warning>4074</Warning>
3319 4075
4076<h3 id="workspace-trust">
4077 工作區信任
4078</h3>
4079
4080Claude Code 在執行任何來自設定檔的 hook 之前會檢查工作區信任。什麼算作受信任取決於工作階段類型:
4081
4082* **互動式工作階段**:Claude Code 會保留來自每個設定檔的 hooks,包括您自己的 `~/.claude/settings.json`,直到您接受該資料夾的[工作區信任對話框](/docs/zh-TW/permissions#project-allow-rules-and-workspace-trust),或接受其信任延伸到該資料夾的父目錄
4083* **`-p` 或 SDK 工作階段**:Claude Code 不會顯示對話框,並將該資料夾視為受信任,因此儲存庫 `.claude/settings.json` 中提交的 hooks 會在您從未信任過的資料夾中執行
4084
4085在您對儲存庫執行 `claude -p` 之前,如果您沒有編寫該儲存庫,請審查其 `.claude/` 設定檔,使用 [`--bare`](/docs/zh-TW/headless#start-faster-with-bare-mode) 開始,或[為該執行關閉 hooks](#disable-or-remove-hooks),使用 `--settings '{"disableAllHooks": true}'`。專案子代理中的 Frontmatter hooks 遵循比設定檔 hooks 更嚴格的規則。[在您信任資料夾之前執行的內容](/docs/zh-TW/permissions#what-runs-before-you-trust-a-folder)按工作階段類型列出每種儲存庫內容。
4086
3320<h3 id="security-best-practices">4087<h3 id="security-best-practices">
3321 安全最佳實踐4088 安全最佳實踐
3322</h3>4089</h3>
3333 Windows PowerShell 工具4100 Windows PowerShell 工具
3334</h2>4101</h2>
3335 4102
3336在 Windows 上,您可以通過在命令 hook 上設定 `"shell": "powershell"` 在 PowerShell 中執行個別 hooks。Hooks 直接生成 PowerShell,因此無論是否設定 `CLAUDE_CODE_USE_POWERSHELL_TOOL` 都有效。Claude Code 自動偵測 `pwsh.exe`(PowerShell 7 及更新版本的可執行檔),並回退到 `powershell.exe`(Windows PowerShell 5.1)。4103在 Windows 上,您可以通過在命令 hook 上設定 `"shell": "powershell"` 在 PowerShell 中執行個別 hooks。Claude Code 自動偵測 `pwsh.exe`(PowerShell 7 及更新版本的可執行檔),並回退到 `powershell.exe`(Windows PowerShell 5.1)。
3337 4104
3338```json theme={null}4105```json theme={null}
3339{4106{
3374 偵錯 hooks4141 偵錯 hooks
3375</h2>4142</h2>
3376 4143
3377Hook 執行詳細資訊,包括哪些 hooks 匹配、它們的退出代碼和完整 stdout 和 stderr,被寫入詳細日誌檔案。使用 `claude --debug-file <path>` 啟動 Claude Code 以將日誌寫入已知位置,或執行 `claude --debug` 並在 `~/.claude/debug/<session-id>.txt` 讀取日誌。`--debug` 標誌不列印到終端。4144Hook 執行詳細資訊被寫入偵錯日誌檔案。使用 `claude --debug-file <path>` 啟動 Claude Code 以將日誌寫入已知位置,或執行 `claude --debug` 並在 `~/.claude/debug/<session-id>.txt` 讀取日誌。`--debug` 標誌不列印到終端。
4145
4146例如,在 `Write` 上的 `PostToolUse` hook,其命令列印 `hook-ran` 會產生如下項目:
3378 4147
3379```text theme={null}4148```text theme={null}
3380[DEBUG] Executing hooks for PostToolUse:Write41492026-07-19T02:03:24.382Z [DEBUG] Hook output does not start with {, treating as plain text
3381[DEBUG] Found 1 hook commands to execute41502026-07-19T02:03:24.382Z [DEBUG] "Hook PostToolUse:Write (PostToolUse) success:\nhook-ran"
3382[DEBUG] Executing hook command: <Your command> with timeout 600000ms
3383[DEBUG] Hook command completed with status 0: <Your stdout>
3384```4151```
3385 4152
3386有關更細粒度的 hook 匹配詳細資訊,設定 `CLAUDE_CODE_DEBUG_LOG_LEVEL=verbose` 以查看額外的日誌行,例如 hook 匹配器計數和查詢匹配。4153有關更細粒度的 hook 匹配詳細資訊,設定 `CLAUDE_CODE_DEBUG_LOG_LEVEL=verbose` 以查看額外的日誌行,例如 hook 匹配器計數和查詢匹配。
3387 4154
3388有關故障排除常見問題,如 hooks 不觸發、Stop hooks 持續阻擋或配置錯誤,請參閱指南中的 [限制和故障排除](/docs/zh-TW/hooks-guide#limitations-and-troubleshooting)。有關涵蓋 `/context`、`/doctor` 和設定優先順序的更廣泛診斷逐步解說,請參閱 [偵錯您的配置](/docs/zh-TW/debug-your-config)。4155有關故障排除常見問題,如 hooks 不觸發、Stop hooks 持續阻擋或配置錯誤,請參閱指南中的 [限制和故障排除](/docs/zh-TW/hooks-guide#limitations-and-troubleshooting)。有關涵蓋 `/context`、`/doctor` 和設定優先順序的更廣泛診斷逐步解說,請參閱 [偵錯您的設定](/docs/zh-TW/debug-your-config)。