
# Hooks
Hooks（钩子）是码道CLI插件系统的核心机制，允许开发者在工具执行、消息处理、权限控制等关键节点注入自定义逻辑。插件通过返回一个Hooks对象来声明自己关注的生命周期事件，当对应事件触发时，插件的自定义函数将被调用。
#### 插件及依赖文件存放路径
插件是一个JavaScript/TypeScript模块，通过导出插件函数来工作。每个函数接收一个上下文对象，并返回对应的Hook对象。如果插件文件中需要使用外部包，必须在配置目录中创建package.json文件并配置所需的依赖项。华为云码道代码智能体在启动时会自动安装这些依赖项。
表1插件文件加载路径 
| 插件类型 | 插件文件存放路径                                                                                                                                         | 插件依赖文件存放路径                     | 说明             |
|:---|:---|:---|:---|
| 项目级  | 当前项目根目录./.codeartsdoer/plugin或./.codeartsdoer/plugins                                                                                            | 当前项目根目录./.codeartsdoer/        | 仅对当前项目有效。      |
| 个人级  | 本地%USERPROFILE%/.codeartsdoer/plugin或 %USERPROFILE%/.codeartsdoer/plugins | 本地%USERPROFILE%/.codeartsdoer/ | 对当前用户下所有项目均有效。 |
   
#### 支持的Hook事件
码道CLI支持的Hook事件请参考[表2]，各Hook事件示例详见文档[Hook事件参考](https://support.huaweicloud.com/usermanual-codeartssnap/codeartsdoer_ug_0036.html#section5)。
 表2支持的Hook事件 
| 事件分类    | 事件名称                                 | 触发时机            | 可阻断 | 典型使用场景        | 说明                                                        |
|:---|:---|:---|:---|:---|:---|
| 聊天消息    | chat.message                         | 用户发送消息后、进入处理流程前 | 是   | 聊天消息处理        | 新消息到达时自动触发，支持对消息内容及Parts进行编辑                              |
| 聊天参数    | chat.params                          | 每次调用LLM前        | 是   | 聊天参数修改        | 支持动态调整大模型推理参数，包含temperature、topP、topK等，按需优化模型输出结果         |
| 聊天请求头   | chat.headers                         | 每次调用LLM前        | 是   | 聊天请求头修改       | 支持自定义修改HTTP请求头字段，适配网络代理、接口鉴权等复杂场景需求                       |
| 聊天响应    | chat.response                        | LLM返回响应后        | 否   | 聊天响应记录        | 自动捕获模型响应的Tokens、Cost、Duration等核心指标，实现精准计费统计、高效故障排查与完整日志留存 |
| 聊天错误    | chat.error                           | LLM调用发生错误时      | 否   | 聊天错误记录        | 记录LLM调用失败时的错误日志                                           |
| 聊天压缩    | chat.compression                     | 上下文压缩时          | 否   | 聊天压缩记录        | 记录上下文压缩前后的Token数量，辅助存储与性能调优                               |
| 聊天结束    | chat.finished                        | 聊天会话结束时         | 否   | 聊天结束记录        | 记录会话结束事件，包含本次运行的Token消耗和运行信息                              |
| 用户审批    | user.approval                        | 需要用户确认/审批操作时    | 是   | 用户审批记录        | 拦截高风险操作，发起人工确认审批，管控敏感操作执行权限                               |
| Turn结束  | turn.end                             | 每个对话轮次结束时       | 否   | Turn结束记录      | 记录每轮对话结束日志，包含处理耗时、终止原因等关键信息                               |
| 命令执行    | command.execute.before               | 命令执行前           | 是   | 命令执行前置处理      | 支持对Parts进行自定义配置，实现命令的前置处理与灵活适配                            |
| 工具执行    | tool.execute.before                  | 工具执行前           | 是   | 工具执行前置参数调整    | 支持在工具执行前自定义修改参数args，实现校验、动态改写与业务适配                        |
| 工具执行    | tool.execute.after                   | 工具执行后           | 是   | 工具执行后置结果处理    | 支持自定义修改返回结果，包括title、output及metadata字段                     |
| 工具定义    | tool.definition                      | 工具定义发送给LLM前     | 是   | 工具定义修改        | 支持在工具推送模型前自定义配置描述与参数，确保精准适配业务场景                           |
| Shell环境 | shell.env                            | 获取Shell环境变量时    | 是   | Shell环境变量配置管理 | 获取Shell环境变量时，支持添加或修改环境变量                                  |
| 权限请求    | permission.ask                       | 需要权限验证时         | 是   | 权限请求处理        | 处理权限校验请求，支持配置allow（允许）、deny（拒绝）、ask（询问）三种策略               |
| 消息转换    | experimental.chat.messages.transform | 消息列表发送给LLM前     | 是   | 消息转换          | 支持在模型上报前预处理聊天消息列表                                         |
| 系统消息转换  | experimental.chat.system.transform   | 系统提示词发送前        | 是   | 系统消息转换        | 支持在系统提示词发送前优化指令内容                                         |
| 会话压缩    | experimental.session.compacting      | 上下文压缩开始前        | 是   | 会话压缩          | 支持在执行上下文压缩前，自定义压缩提示词                                      |
| 文本补全    | experimental.text.complete           | 文本补全完成时触发       | 是   | 文本补全结果定制      | 文本补全完成后，支持对输出内容进行修改                                       |
| 配置加载    | config                               | 应用启动配置加载时       | 否   | 配置加载          | 在加载自定义配置时触发，用于执行配置初始化及动态参数注入                              |
| 通用事件    | event                                | 订阅所有Bus事件时触发    | 否   | 事件处理          | 通用事件处理                                                    |
   
#### 编写示例
本文以创建个人级别的Hook为例。
以下示例创建一个JsonFormatPlugin插件，在读取.json文件后，自动将挤成一行的压缩JSON，整理成2个空格缩进的格式化形式。
1. 进入"\~\\.codeartsdoer\\plugin"，创建并编写文件"JsonFormatPlugin.ts"。 
   ```
   // 导入Plugin类型，用于定义插件
   import type { Plugin } from "@opencode-ai/plugin"
   // 导入文件系统模块，用于读写磁盘文件
   import { readFileSync, writeFileSync } from "fs"
   // 导出插件实现，Plugin是一个异步函数，接收插件输入参数并返回Hooks对象
   export const JsonFormatPlugin: Plugin = async ({}) => {
     return {
       // 监听工具执行后的钩子，在工具执行完成后触发
       "tool.execute.after": async (
         // 输入参数：包含工具名称、会话ID、调用ID、参数等信息
         input: { tool: string; sessionID: string; callID: string; args: any },
         // 输出参数：包含工具执行结果的标题、输出内容、元数据
         output: { title: string; output: string; metadata: any },
       ) => {
         if (input.tool !== "read") return
         // 获取文件路径，只处理.json文件
         const filePath = input.args?.filePath || input.args?.[0] || ""
         if (!filePath.endsWith(".json")) return
         try {
           const raw = readFileSync(filePath, "utf-8").trim()
           const parsed = JSON.parse(raw)
           const formatted = JSON.stringify(parsed, null, 2) + "\n"
           if (formatted === raw) return
           // 将格式化后的内容写回磁盘文件
           writeFileSync(filePath, formatted, "utf-8")
         } catch {}
       },
     }
   }
   ```
   
   
2. 进入项目文件夹目录，创建并编写测试文件"test-plugin.json"，内容为压缩格式的JSON。 
   ```
   {"plugin":"JsonFormatPlugin","test":{"input":"压缩的单行JSON","output":"格式化的多行JSON"}}
   ```
   图1格式化前   
   ![](https://support.huaweicloud.com/usermanual-cli/zh-cn_image_0000002616131257.png "点击放大")
   
   
3. 根据不同的开发模式，执行命令： 
   - 如果是TUI开发模式，在TUI对话框中输入如下指令并回车：
     ```
     读取 test-plugin.json
     ```
     
   
   - 如果是CLI开发模式，请执行如下命令：
     ```
     codearts run "读取 test-plugin.json"
     ```
     图2CLI开发模式的命令截图   
     ![](https://support.huaweicloud.com/usermanual-cli/zh-cn_image_0000002650053214.png "点击放大") 
   
   
   
   
4. 执行完成后，"test-plugin.json"文件将被自动格式化为多行缩进形式。再次读取同一文件时，由于已是格式化状态，不会重复处理。 
   打开目标JSON文件，可发现该JSON文件已被格式化。
   图3格式化后的效果图   
   ![](https://support.huaweicloud.com/usermanual-cli/zh-cn_image_0000002650054870.png "点击放大")
   
   
 
