Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 26 additions & 1 deletion docs/en/customization/hooks.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ Only **blockable events** (`PreToolUse`, `Stop`, `UserPromptSubmit`) have return

| Event | Matcher matches | Supports blocking? | Description |
| --- | --- | --- | --- |
| `UserPromptSubmit` | The text submitted by the user | ✓ | Triggered when the user sends a message; returned text is appended to context; if blocked, the model is not called for this turn |
| `UserPromptSubmit` | Text extracted from the submitted content parts | ✓ | Triggered when the user sends a message; returned text is appended to context; if blocked, the model is not called for this turn |
| `PreToolUse` | Tool name | ✓ | Triggered before a tool call (before permission checks); the tool will not execute if blocked |
| `Stop` | Empty string | ✓ | Triggered when the model is about to end the current turn; if blocked, a message can be appended to let the model continue |
| `PostToolUse` | Tool name | — | Triggered after a tool executes successfully (observation only) |
Expand All @@ -115,6 +115,31 @@ Only **blockable events** (`PreToolUse`, `Stop`, `UserPromptSubmit`) have return
| `PostCompact` | `manual` or `auto` | — | Triggered after context compaction completes (observation only) |
| `Notification` | Notification type (e.g. `task.completed`) | — | Triggered when a background task status changes (observation only) |

### Per-event payload fields

Every hook receives `hook_event_name`, `session_id`, and `cwd`. These event-specific fields are added when available; fields without a value are omitted from stdin.

| Event | Extra stdin fields |
| --- | --- |
| `UserPromptSubmit` | `prompt` (`ContentPart[]`) |
| `PreToolUse` | `tool_name`, `tool_input`, `tool_call_id` |
| `PermissionRequest` | `turn_id`, `tool_call_id`, `tool_name`, `action`, `tool_input`, `display` |
| `PermissionResult` | `turn_id`, `tool_call_id`, `tool_name`, `action`, `decision`; may also include `scope`, `feedback`, `selected_label`, or `error` |
| `PostToolUse` | `tool_name`, `tool_input`, `tool_call_id`, `tool_output` (truncated to 2000 characters) |
| `PostToolUseFailure` | `tool_name`, `tool_input`, `tool_call_id`, `error` |
| `Stop` | `stop_hook_active` |
| `StopFailure` | `error_type`, `error_message` |
| `Interrupt` | `turn_id`, `reason` |
| `SessionStart` | `source` (`startup` or `resume`) |
| `SessionEnd` | `reason` (`exit`) |
| `SubagentStart` | `agent_name`, `prompt` (preview-truncated) |
| `SubagentStop` | `agent_name`, `response` (preview-truncated) |
| `PreCompact` | `trigger`, `token_count` |
| `PostCompact` | `trigger`, `estimated_token_count` |
| `Notification` | `notification_type`, `title`, `body`, `severity`, `source_kind`, `source_id`, `sink` |

For `UserPromptSubmit`, the hook receives the submitted message as `prompt: ContentPart[]` on stdin. Text-only prompts are represented as `[{"type":"text","text":"..."}]`; prompts with images or other media include additional content-part objects. The matcher still runs against the text extracted from those content parts.

## Example: Blocking Dangerous Shell Commands

The following hook checks the command content before the Agent calls the `Bash` tool and blocks it if `rm -rf` is detected:
Expand Down
27 changes: 26 additions & 1 deletion docs/zh/customization/hooks.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ Hook 命令的工作目录是当前会话的项目目录。非 Windows 平台上

| 事件 | Matcher 匹配的是 | 会触发阻断? | 说明 |
| --- | --- | --- | --- |
| `UserPromptSubmit` | 用户提交的文本内容 | ✓ | 用户发送消息时触发;返回文本会附加到上下文;若阻断,本轮不调用模型 |
| `UserPromptSubmit` | 从提交的 content part 中提取的文本 | ✓ | 用户发送消息时触发;返回文本会附加到上下文;若阻断,本轮不调用模型 |
| `PreToolUse` | 工具名 | ✓ | 工具调用前触发(权限检查前);阻断后工具不会执行 |
| `Stop` | 空字符串 | ✓ | 模型准备结束本轮时触发;阻断后可追加一条消息让模型继续 |
| `PostToolUse` | 工具名 | — | 工具成功执行后触发(观察用) |
Expand All @@ -115,6 +115,31 @@ Hook 命令的工作目录是当前会话的项目目录。非 Windows 平台上
| `PostCompact` | `manual` 或 `auto` | — | 上下文压缩完成后触发(观察用) |
| `Notification` | 通知类型(如 `task.completed`) | — | 后台任务状态变化时触发(观察用) |

### 各事件的 payload 字段

每个 hook 都会收到 `hook_event_name`、`session_id` 和 `cwd`。下表列出各事件额外加入的字段;没有值的字段会从 stdin 中省略。

| 事件 | 额外 stdin 字段 |
| --- | --- |
| `UserPromptSubmit` | `prompt`(`ContentPart[]`) |
| `PreToolUse` | `tool_name`、`tool_input`、`tool_call_id` |
| `PermissionRequest` | `turn_id`、`tool_call_id`、`tool_name`、`action`、`tool_input`、`display` |
| `PermissionResult` | `turn_id`、`tool_call_id`、`tool_name`、`action`、`decision`;也可能包含 `scope`、`feedback`、`selected_label` 或 `error` |
| `PostToolUse` | `tool_name`、`tool_input`、`tool_call_id`、`tool_output`(截断到 2000 个字符) |
| `PostToolUseFailure` | `tool_name`、`tool_input`、`tool_call_id`、`error` |
| `Stop` | `stop_hook_active` |
| `StopFailure` | `error_type`、`error_message` |
| `Interrupt` | `turn_id`、`reason` |
| `SessionStart` | `source`(`startup` 或 `resume`) |
| `SessionEnd` | `reason`(`exit`) |
| `SubagentStart` | `agent_name`、`prompt`(预览内容会被截断) |
| `SubagentStop` | `agent_name`、`response`(预览内容会被截断) |
| `PreCompact` | `trigger`、`token_count` |
| `PostCompact` | `trigger`、`estimated_token_count` |
| `Notification` | `notification_type`、`title`、`body`、`severity`、`source_kind`、`source_id`、`sink` |

对于 `UserPromptSubmit`,hook 在 stdin 中收到的 `prompt` 是 `ContentPart[]` 数组。纯文本 prompt 会表示为 `[{"type":"text","text":"..."}]`;带图片或其他媒体的 prompt 会包含额外的 content part 对象。matcher 仍然匹配从这些 content part 中提取出的文本。

## 示例:阻断危险 Shell 命令

下面的 hook 在 Agent 调用 `Bash` 工具前检查命令内容,发现 `rm -rf` 就阻断:
Expand Down