> ## Documentation Index
> Fetch the complete documentation index at: https://docs.devin.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# 生命周期钩子

> 了解钩子事件及各阶段可用的数据

每个钩子事件都会在 Agent 生命周期的特定阶段触发。使用 **matcher** 字段 (即一个与钩子事件 `tool_name` 匹配的正则表达式) 来筛选会触发你的钩子的工具调用。

***

<div id="pretooluse">
  ## PreToolUse
</div>

在工具执行**前**触发。可用于阻止、修改工具调用，或为其添加上下文。

**Stdin 数据：**

| 字段           | 说明       | 示例                                              |
| ------------ | -------- | ----------------------------------------------- |
| `tool_name`  | 被调用的工具名称 | `exec`, `edit`, `mcp__github__create_issue`     |
| `tool_input` | 传递给工具的参数 | `{ "command": "rm -rf /", "shell_id": "main" }` |

**示例 — 阻止危险命令：**

```json theme={null}
{
  "PreToolUse": [
    {
      "matcher": "exec",
      "hooks": [
        {
          "type": "command",
          "command": "python3 -c \"import sys, json; data = json.load(sys.stdin); cmd = data.get('tool_input', {}).get('command', ''); sys.exit(2 if 'rm -rf' in cmd else 0)\""
        }
      ]
    }
  ]
}
```

**示例——要求对 `src/` 之外的写入操作进行确认：**

使用一个脚本来检查工具输入并返回决策：

```json theme={null}
{
  "PreToolUse": [
    {
      "matcher": "edit",
      "hooks": [
        {
          "type": "command",
          "command": "./scripts/check-edit-path.sh",
          "timeout": 5
        }
      ]
    }
  ]
}
```

***

<div id="posttooluse">
  ## PostToolUse
</div>

在工具执行**后**触发。可用于记录日志、验证，或触发后续操作。

**Stdin 数据：**

| Field           | Description                                                  |
| --------------- | ------------------------------------------------------------ |
| `tool_name`     | 已执行的工具名称                                                     |
| `tool_input`    | 传入的参数                                                        |
| `tool_response` | 包含 `success` (布尔值) 、`output` (字符串) 和 `error` (字符串或 null) 的对象 |

**示例——记录所有 shell 命令：**

```json theme={null}
{
  "PostToolUse": [
    {
      "matcher": "exec",
      "hooks": [
        {
          "type": "command",
          "command": "sh -c 'cat >> ~/.devin-command-log'"
        }
      ]
    }
  ]
}
```

***

<div id="permissionrequest">
  ## PermissionRequest
</div>

当 Agent 需要进行权限判定时触发。可用它来实现自定义审批逻辑。

**Stdin 数据：**

| Field        | Description |
| ------------ | ----------- |
| `tool_name`  | 请求权限的工具名称   |
| `tool_input` | 工具调用的参数     |

**示例 — 自动批准 git 命令：**

```json theme={null}
{
  "PermissionRequest": [
    {
      "matcher": "exec",
      "hooks": [
        {
          "type": "command",
          "command": "python3 -c \"import sys, json; data = json.load(sys.stdin); cmd = data.get('tool_input', {}).get('command', ''); print(json.dumps({'decision': 'approve'})) if cmd.startswith('git ') else sys.exit(0)\""
        }
      ]
    }
  ]
}
```

***

<div id="userpromptsubmit">
  ## UserPromptSubmit
</div>

当用户提交消息时触发。可用于添加上下文或触发工作流程。

**Stdin 数据：**

| Field    | Description |
| -------- | ----------- |
| `prompt` | 用户提交的消息文本   |

**示例 — 在每个提示中注入上下文：**

```json theme={null}
{
  "UserPromptSubmit": [
    {
      "matcher": "",
      "hooks": [
        {
          "type": "command",
          "command": "echo '{\"hookSpecificOutput\": {\"hookEventName\": \"UserPromptSubmit\", \"additionalContext\": \"Deploys require an approved change ticket.\"}}'"
        }
      ]
    }
  ]
}
```

该命令会将 `additionalContext` 输出到 stdout 中的 `hookSpecificOutput` 对象内，并附带事件名称标签。该文本会被注入到 Agent 的上下文中：

```json theme={null}
{
  "hookSpecificOutput": {
    "hookEventName": "UserPromptSubmit",
    "additionalContext": "Deploys require an approved change ticket."
  }
}
```

***

<div id="stop">
  ## Stop
</div>

当 Agent 决定停止 (结束当前回合) 时触发。可用它来添加后续指示，或防止过早停止。

**Stdin 数据：**

| Field              | Description |
| ------------------ | ----------- |
| `stop_hook_active` | 停止钩子是否已激活   |

**示例 — 提醒 Agent 执行测试：**

```json theme={null}
{
  "Stop": [
    {
      "matcher": "",
      "hooks": [
        {
          "type": "command",
          "command": "echo '{\"decision\": \"block\", \"reason\": \"Please run the test suite before stopping.\"}'"
        }
      ]
    }
  ]
}
```

<Warning>
  注意会阻塞的 stop 钩子——如果条件始终无法满足，Agent 可能会陷入循环。
</Warning>

***

<div id="postcompaction">
  ## PostCompaction
</div>

在上下文压缩成功完成**后**触发。可用于记录日志、触发后续操作，或重新注入在压缩过程中可能丢失的上下文。

**Stdin 数据：**

| Field     | Description                       |
| --------- | --------------------------------- |
| `summary` | 由压缩器生成的摘要文本 (如果未生成摘要，则该值可能为 null) |

**示例 — 记录压缩事件：**

```json theme={null}
{
  "PostCompaction": [
    {
      "matcher": "",
      "hooks": [
        {
          "type": "command",
          "command": "sh -c 'cat >> ~/.devin-compaction-log'"
        }
      ]
    }
  ]
}
```

***

<div id="sessionstart">
  ## SessionStart
</div>

当新会话开始时触发。可用于初始化、日志记录或环境准备。

**Stdin 数据：**

| 字段       | 描述      |
| -------- | ------- |
| `source` | 会话的启动方式 |

**示例 — 运行初始化脚本：**

```json theme={null}
{
  "SessionStart": [
    {
      "matcher": "",
      "hooks": [
        {
          "type": "command",
          "command": "./scripts/dev-setup.sh",
          "timeout": 10
        }
      ]
    }
  ]
}
```

SessionStart 命令也可以通过在 `hookSpecificOutput` 对象中向 stdout 输出 `additionalContext` 来注入上下文：

```json theme={null}
{
  "hookSpecificOutput": {
    "hookEventName": "SessionStart",
    "additionalContext": "Session started. Project uses ESM imports only."
  }
}
```

***

<div id="sessionend">
  ## SessionEnd
</div>

在会话结束时触发。可用于清理或记录最终日志。

**Stdin 数据：**

| 字段       | 说明      |
| -------- | ------- |
| `reason` | 会话结束的原因 |

***

<div id="matching-multiple-events">
  ## 匹配多个事件
</div>

一个 hooks 文件可以为多个事件定义钩子：

```json theme={null}
{
  "PreToolUse": [
    {
      "matcher": "",
      "hooks": [
        { "type": "command", "command": "./scripts/audit.sh" }
      ]
    }
  ],
  "PostToolUse": [
    {
      "matcher": "",
      "hooks": [
        { "type": "command", "command": "./scripts/audit.sh" }
      ]
    }
  ]
}
```

<div id="using-the-matcher">
  ## 使用 matcher
</div>

`matcher` 字段是一个**正则表达式**，用于匹配钩子事件的 `tool_name`。它适用于与工具相关的事件：`PreToolUse`、`PostToolUse` 和 `PermissionRequest`。

对于非工具事件 (`UserPromptSubmit`、`Stop`、`PostCompaction`、`SessionStart` 和 `SessionEnd`) ，不存在 `tool_name`；请使用 `""` 或省略 matcher，以便钩子在该类型的每个事件上运行。

<Note>
  matcher 不是权限 glob。像 `mcp__github__*` 这样的模式可用于权限，但钩子的 matcher 使用的是正则表达式。在钩子 matcher 中，请使用 `mcp__github__.*`。
</Note>

| 匹配器                             | 匹配内容                                 |
| ------------------------------- | ------------------------------------ |
| `""` (空) 或省略                    | 工具事件中的所有工具名称                         |
| `"exec"`                        | 名称中包含 `exec` 的工具                     |
| `"^exec$"`                      | 仅 `exec` 工具                          |
| `"^(exec\|edit)$"`              | 仅 `exec` 或 `edit`                    |
| `"^mcp__.*"`                    | 所有 MCP 工具                            |
| `"^mcp__github__.*"`            | `github` MCP 服务器中的所有工具               |
| `"^mcp__github__create_issue$"` | `github` MCP 服务器中的 `create_issue` 工具 |

<div id="tool-names-you-can-match">
  ### 你可以匹配的工具名称
</div>

钩子匹配器匹配的是钩子脚本通过 stdin 中的 `tool_name` 接收到的、同样对外可见的工具名称。具体有哪些可用工具名称，可能因 CLI 模式、模型以及启用的集成而有所不同。

最常见的公共核心工具名称包括：

* `read`
* `edit`
* `grep`
* `glob`
* `exec`

MCP 服务器工具的名称格式为 `mcp__<server>__<tool>`。例如，`github` MCP 服务器中名为 `create_issue` 的工具会显示为 `mcp__github__create_issue`。

对于其他工具，请匹配钩子 stdin 中显示的确切 `tool_name`。要确认当前会话中完整的可用工具集，请添加一个临时的 `PostToolUse` 钩子，将 `matcher` 设为 `""`，并记录 stdin payload。
