本文档介绍 TRAE IDE 中 Hook 的配置方式、执行环境、输入输出规范,以及各类事件的触发与处理机制。
TRAE 支持全局 Hook 和项目 Hook。两类配置文件在不同操作系统中的存储位置如下:
|
Hook 类型 |
操作系统 |
Hook 配置文件位置 |
作用范围 |
|---|---|---|---|
|
全局 Hook |
macOS & Linux |
|
对本机当前用户下的所有工作区生效。 |
|
Windows |
|
||
|
项目 Hook |
macOS & Linux |
若当前工作区包含多个项目,默认会在第一个项目中创建配置文件。 |
仅对当前项目或工作区生效。 |
|
Windows |
同时,TRAE 支持读取 Claude Code 中的 Hook 配置,配置流程参考导入 Claude Code 中的 Hook。Claude Code 同样支持全局与项目 Hook:
|
Hook 类型 |
操作系统 |
Hook 配置文件位置 |
作用范围 |
|---|---|---|---|
|
全局 Hook |
macOS & Linux |
|
对本机当前用户下的所有工作区生效。 |
|
Windows |
|
||
|
项目 Hook |
macOS & Linux |
|
仅对当前项目或工作区生效。 |
|
Windows |
提示
多个 Hook 配置文件共存时,TRAE 的行为如下:
hooks.json 文件的配置格式如下:
{
"version": 1,
"hooks": {
"<EventName>": [
{
"matcher": "<ToolPattern>",
"loop_limit": 5,
"hooks": [
{
"type": "command",
"command": "<shell command>",
"timeout": 30
}
]
}
]
}
}
Hook 相关字段的说明如下:
|
字段 |
类型 |
是否必填 |
描述 |
|---|---|---|---|
|
|
|
否 |
配置文件的 schema 版本,默认为 |
|
|
|
是 |
Hook 事件名到 Hook 组的映射。 |
hooks.<EventName>)
|
字段 |
类型 |
是否必填 |
描述 |
|---|---|---|---|
|
|
|
是 |
某个 Hook 事件下的 Hook 组列表。 |
|
字段 |
类型 |
是否必填 |
描述 |
|---|---|---|---|
|
|
|
否 |
匹配规则,支持正则表达式(如 提示: |
|
|
|
否 |
循环次数限制。 当 该字段仅支持正整数;未配置或配置的值小于等于 提示: |
|
|
|
是 |
该 Hook 组下要执行的 Hook 列表。 |
|
字段 |
类型 |
是否必填 |
描述 |
|---|---|---|---|
|
|
|
否 |
Hook 类型,默认为 “命令” 类型( |
|
|
|
是 |
要执行的 Shell 命令。 |
|
|
|
否 |
超时时间(秒),默认 |
所有 Hook 命令都遵循标准的输入/输出(I/O)机制:通过 stdin 接收 JSON 格式的输入,并通过 stdout 输出和退出码来控制智能体的行为。
每个 Hook 事件的 stdin JSON 都包含以下通用字段:
{
"session_id": "string",
"cwd": "/path/to/workspace",
"hook_event_name": "PreToolUse",
"workspace_roots": ["/path/to/workspace"]
}
|
字段 |
类型 |
描述 |
|---|---|---|
|
|
|
当前会话 ID。 |
|
|
|
当前 Hook 命令的实际工作目录。详情参考工作目录。 |
|
|
|
当前 Hook 事件的名称。 |
|
|
|
如果存在多个工作区,此字段将包含所有工作区的根目录。 |
Hook 命令可以通过 stdout 输出两种格式的数据:
SessionStart 和 UserPromptSubmit 事件。对于 JSON 格式的输出,所有事件均支持以下通用流程控制字段:
{
"continue": true,
"stopReason": "string"
}
|
字段 |
类型 |
默认值 |
描述 |
|---|---|---|---|
|
|
|
|
智能体是否在 Hook 执行完毕后继续执行。若设置为 |
|
|
|
— |
当 |
|
退出码 |
行为 |
|---|---|
|
|
正常退出。 |
|
|
阻断性错误。 |
|
其他 |
非阻断性错误。这类错误不会影响智能体的执行流程,其 |
Hook 命令会在系统默认 Shell 中执行:
Hook 命令执行时,可通过以下环境变量获取上下文:
|
环境变量 |
描述 |
|---|---|
|
|
当前 Hook 命令的工作区目录,与 |
|
|
兼容 Claude Code Hook 的工作区目录变量,与 |
SessionStart 事件会额外注入以下环境变量,用于向当前会话的后续执行环境写入变量:
|
环境变量 |
描述 |
|---|---|
|
|
TRAE 环境变量文件路径,仅在 |
|
|
兼容 Claude Code Hook 的环境变量文件路径,仅在 |
SessionStart 事件的 Hook 可以向 TRAE_ENV_FILE 指向的文件写入环境变量。写入的变量会在当前会话后续的 Hook 执行以及 RunCommand 工具调用中生效,但不会影响当前正在执行的 SessionStart Hook 进程。
支持以下三种格式:
export NODE_ENV=production
export PATH="/usr/local/bin"
$env:NODE_ENV=production
NODE_ENV=production
MY_VAR="hello world"
Hook 命令执行时的工作目录如下:
|
Hook 命令类型 |
工作目录 |
|---|---|
|
全局 Hook 命令 |
|
|
项目 Hook 命令 |
该 Hook 配置文件所在项目的根目录。 |
Hook 命令的实际权限和可访问范围取决于你所设置的运行方式:
关于如何设置 Hook 命令的运行方式,参考设置 Hook 命令的运行方式。
stdin:
{
"session_id": "...",
"hook_event_name": "SessionStart",
"source": "startup"
}
|
字段 |
类型 |
描述 |
|---|---|---|
|
|
|
会话的来源。目前仅支持 |
stdout:
{
"hookSpecificOutput": {
"hookEventName": "SessionStart",
"additionalContext": "文本内容"
}
}
|
字段 |
类型 |
描述 |
|---|---|---|
|
|
|
附加给模型的上下文。 |
$TRAE_ENV_FILE 文件写入键值对,可以为 Hook 后续的执行环境注入环境变量。2 的行为:不影响会话流程。stdin:
{
"session_id": "...",
"hook_event_name": "UserPromptSubmit",
"prompt": "用户输入的 Prompt"
}
|
字段 |
类型 |
描述 |
|---|---|---|
|
|
|
用户提交的 Prompt 文本。 |
stdout:
{
"decision": "block",
"reason": "该请求不被允许的原因",
"hookSpecificOutput": {
"hookEventName": "UserPromptSubmit",
"additionalContext": "附加给模型的上下文"
}
}
|
字段 |
类型 |
描述 |
|---|---|---|
|
|
|
该字段仅支持设为 |
|
|
|
当 |
|
|
|
附加给模型的上下文文本。 |
2 的行为:等价于 "decision": "block",直接禁止智能体执行该 Prompt,并将 stderr 内容展示给用户。matcher 字段配置:可通过 matcher 字段配置正则表达式,从而匹配特定的工具名。stdin:
{
"session_id": "...",
"hook_event_name": "PreToolUse",
"tool_use_id": "toolcall-id-string",
"tool_name": "RunCommand",
"tool_input": { ... }
}
|
字段 |
类型 |
描述 |
|---|---|---|
|
|
|
工具调用的唯一 ID。 |
|
|
|
标准化的工具名称。详见 PreToolUse 和 PostToolUse 事件支持的工具。 |
|
|
|
传递给大语言模型的原始工具名称。 |
|
|
|
工具输入参数。 |
stdout:
{
"hookSpecificOutput": {
"hookEventName": "PreToolUse",
"permissionDecision": "allow",
"permissionDecisionReason": "决策原因说明",
"updatedInput": { ... },
"additionalContext": "附加给模型的上下文"
}
}
|
字段 |
类型 |
说明 |
|---|---|---|
|
|
|
权限决策,用于决定是否执行本次工具调用。可选值包括:
特殊情况说明:
|
|
|
|
权限决策的原因。 |
|
|
|
修改后的工具输入参数,将整体覆盖替换原始参数(非合并更新)。 |
|
|
|
附加给模型的上下文文本。 |
2 的行为:等价于 "permissionDecision": "deny",拒绝让智能体执行本次工具调用,并将 stderr 内容作为原因附加给模型的上下文。matcher 字段配置:可通过 matcher 字段配置正则表达式,从而匹配特定的工具名。stdin:
{
"session_id": "...",
"hook_event_name": "PostToolUse",
"tool_use_id": "toolcall-id-string",
"tool_name": "RunCommand",
"llm_tool_name": "RunCommand",
"tool_input": { ... },
"tool_response": { ... }
}
|
字段 |
类型 |
描述 |
|---|---|---|
|
|
|
工具调用的唯一 ID。 |
|
|
|
标准化的工具名称。详见 PreToolUse 和 PostToolUse 事件支持的工具。 |
|
|
|
传递给大语言模型的原始工具名称。 |
|
|
|
工具输入参数。 |
|
|
|
工具调用的结果。 |
stdout:
{
"decision": "block",
"reason": "阻断原因",
"hookSpecificOutput": {
"hookEventName": "PostToolUse",
"additionalContext": "附加给模型的上下文"
}
}
|
字段 |
类型 |
描述 |
|---|---|---|
|
|
|
该字段仅支持设为 |
|
|
|
当 |
|
|
|
附加给模型的上下文文本。 |
2 的行为:将 stderr 传递给模型的上下文。stdin:
{
"session_id": "...",
"hook_event_name": "Stop",
"stop_hook_active": false,
"loop_count": 0,
"text_content": "大语言模型最终输出的文本内容"
}
|
字段 |
类型 |
描述 |
|---|---|---|
|
|
|
当前查询是否已经被 |
|
|
|
当前查询的 循环限制:你可以通过 |
|
|
|
大语言模型最终输出的文本内容。 |
stdout:
{
"decision": "block",
"reason": "请继续检查测试是否通过"
}
|
字段 |
类型 |
描述 |
|---|---|---|
|
|
|
该字段仅支持设为 |
|
|
|
当 |
2 的行为:等价于 "decision": "block",阻断智能体停止执行,并将 stderr 作为新的用户请求让智能体继续执行。Stop 事件的决策控制逻辑如下:
智能体准备停止
│
▼
检查 loop_count 是否大于等于 loop_limit?──── 是 ──► 跳过 Hook,允许智能体停止
│
否
│
▼
执行 Stop 事件的 Hook 脚本
│
├── 退出码为 0,且 decision 字段为空 ───────► 允许停止
│
├── 退出码为 0,且 decision 字段的值为 block ──► 阻断停止,将 reason 字段作为新 Query
│
├── 退出码为 2 ───────────────────► 阻断停止,将 stderr 作为新 Query
│
└── 其他退出码 ───────────────────► 忽略错误,允许停止
matcher 字段配置:基于通知类型(notification_type)匹配,而不是基于工具名匹配。未配置 matcher,或将其配置为空字符串或 * 时,表示匹配所有通知类型。{
"session_id": "...",
"hook_event_name": "Notification",
"notification_type": "idle_prompt",
"message": "智能体已完成任务",
"tool_use_id": "toolu_xxx"
}
|
字段 |
类型 |
描述 |
|---|---|---|
|
|
|
通知类别,用于标识通知场景,也用于匹配 |
|
|
|
通知的正文。 |
|
|
|
关联的工具调用 ID。 仅工具调用相关的通知类型携带该 ID,例如 |
notification_type 字段的值和相应触发时机如下:
|
值 |
触发时机 |
|---|---|
|
|
智能体完成当前任务。 |
|
|
工具调用需要用户确认后才能继续执行,例如当 |
|
|
Plan 或 Spec 工作流中的文档审阅流程。 |
|
|
智能体需要用户补充信息时,进行提问的通知。 |
|
|
浏览器交互等待通知。 |
stdout:该事件会忽略 Hook 进程的 stdout 输出。即使输出 JSON,也不会影响智能体的行为。stdout、stderr 和退出码不会改变智能体的执行流程。在 PreToolUse 和 PostToolUse 事件中,你可以通过 matcher 字段匹配 tool_name。
tool_name 为标准化工具名称,取值如下:
|
分类 |
工具名称 |
描述 |
|---|---|---|
|
文件读取 |
|
读取文件内容。 |
|
文件写入 |
|
写入文件。 |
|
文件编辑 |
|
单次查找并替换文件内容。 |
|
搜索 |
|
基于文件路径模式进行匹配搜索。 |
|
|
基于正则表达式进行内容搜索。 |
|
|
|
列出目录下的文件与子目录。 |
|
|
终端 |
|
执行终端命令。 |
|
网络 |
|
网络搜索。 |
|
|
获取网页内容。 |
|
|
交互 |
|
向用户提问。 |
|
Skill |
|
加载 Skill。 |
|
MCP |
|
MCP 工具。 MCP 工具匹配说明:在 Hook 中,MCP 工具的标准化名称格式为 |
本示例用于在会话启动时自动注入项目级上下文和环境变量,使智能体在开始处理任务前即可获取项目名称、运行环境、技术栈和代码规范等信息。
Hook 配置:监听 SessionStart 事件,并在事件触发时执行 setup_env.sh 脚本。
{
"version": 1,
"hooks": {
"SessionStart": [
{
"hooks": [
{
"command": "bash ./scripts/setup_env.sh"
}
]
}
]
}
}
{
"version": 1,
"hooks": {
"SessionStart": [
{
"hooks": [
{
"command": "powershell -ExecutionPolicy Bypass -File ./scripts/setup_env.ps1"
}
]
}
]
}
}
setup_env.sh 脚本示例:该脚本会向 $TRAE_ENV_FILE 写入环境变量,使其在后续 Hook 和 RunCommand 工具调用中生效;同时通过标准输出向模型补充项目背景信息。
#!/bin/bash
# 向环境变量文件写入项目配置
echo "export PROJECT_NAME=my-app" >> "$TRAE_ENV_FILE"
echo "export NODE_ENV=development" >> "$TRAE_ENV_FILE"
# 输出上下文信息给模型
echo "当前项目:my-app,技术栈:React + TypeScript,请遵循 ESLint 规范。"
# 向环境变量文件写入项目配置
Add-Content -Path $env:TRAE_ENV_FILE -Value "`$env:PROJECT_NAME='my-app'"
Add-Content -Path $env:TRAE_ENV_FILE -Value "`$env:NODE_ENV='development'"
# 输出上下文信息给模型
Write-Output "当前项目:my-app,技术栈:React + TypeScript,请遵循 ESLint 规范。"
本示例用于在终端命令真正执行前识别并拦截高风险操作,降低误删文件、执行破坏性命令或提交危险数据库操作的风险。
Hook 配置:监听 PreToolUse 事件,并通过 matcher 仅匹配 RunCommand 工具。只有当智能体准备执行终端命令时,才会触发该 Hook。
{
"version": 1,
"hooks": {
"PreToolUse": [
{
"matcher": "RunCommand",
"hooks": [
{
"type": "command",
"command": "python3 ./validate_command.py",
"timeout": 10
}
]
}
]
}
}
validate_command.py 脚本示例:该脚本从 stdin 读取工具输入,提取待执行命令,并检查命令内容是否包含预设的危险模式。若命中危险模式,脚本返回 "permissionDecision": "deny" 和拒绝原因,从而阻止该命令执行;若未命中,则正常退出并允许继续执行。
#!/usr/bin/env python3
import sys, json
input_data = json.load(sys.stdin)
command = input_data.get("tool_input", {}).get("command", "")
dangerous_patterns = ["rm -rf /", "DROP TABLE", "format C:"]
for pattern in dangerous_patterns:
if pattern in command:
result = {
"hookSpecificOutput": {
"hookEventName": "PreToolUse",
"permissionDecision": "deny",
"permissionDecisionReason": f"high risk command detected: {pattern}"
}
}
json.dump(result, sys.stdout)
sys.exit(0)
# 允许执行
sys.exit(0)
本示例用于在智能体准备结束当前任务前自动执行验收测试,并根据测试结果决定是否允许停止。如果测试未通过,Hook 会要求智能体继续修复问题,而不是直接结束任务。
提示
如需测试本示例,配置完成后,可向智能体发送消息 “测试 stop hook” 来验证效果。
Hook 配置:监听 Stop 事件,并设置 loop_limit 限制最多阻断次数,避免测试持续失败时造成无限循环。
{
"version": 1,
"hooks": {
"Stop": [
{
"loop_limit": 3,
"hooks": [
{
"command": "python3 ./check_tests.py",
"timeout": 60
}
]
}
]
}
}
{
"version": 1,
"hooks": {
"Stop": [
{
"loop_limit": 3,
"hooks": [
{
"command": "python ./check_tests.py", // 或使用 py ./check_tests.py 命令
"timeout": 60
}
]
}
]
}
}
check_tests.py 脚本示例:该脚本会运行 npm test 并读取测试结果。若测试失败,该脚本返回 "decision": "block" 和失败原因,并带上当前阻断次数,要求智能体继续修复;若测试通过,则正常退出并允许智能体停止。
#!/usr/bin/env python3
import sys, json, subprocess
input_data = json.load(sys.stdin)
loop_count = input_data.get("loop_count", 0)
# 运行测试
result = subprocess.run(["npm", "test"], capture_output=True, text=True)
if result.returncode != 0:
output = {
"decision": "block",
"reason": f"测试未通过(第 {loop_count + 1} 次检查),请修复以下失败:\n{result.stdout[-500:]}"
}
json.dump(output, sys.stdout)
else:
# 测试通过,允许停止
sys.exit(0)