# Hook 与 CLI ## Codex notify 在用户级 `~/.codex/config.toml` 中配置: ```toml notify = ["E:\\notify\\scripts\\notify.cmd", "codex"] ``` Codex 调用 `notify codex `。程序处理 `agent-turn-complete` 事件,使用 `thread-id` 或 `turn-id` 标识通知,以 `last-assistant-message` 作为正文。 ## Hook 与子命令映射 | 事件 | 子命令 | 作用 | |------|--------|------| | `UserPromptSubmit` | `notify save` | 记录前台窗口、prompt、WT 标签、调用方图标路径 | | `Stop` | `notify notify` | 弹"任务完成"通知(自动消失,聚焦时更短) | | `Notification` | `notify input` | 弹"需要输入"通知(常驻),按类型分标题 | | `PreToolUse`(`AskUserQuestion`/`ExitPlanMode`) | `notify input` | 提问 / 出 Plan 时弹常驻通知 | | `SessionEnd` | `notify cleanup` | 删除该会话状态文件 | 客户端可调用 `notify.exe <子命令> [来源]`。来源为 `codex` 时固定显示 Codex 图标。 ## stdin JSON 外部 hook 通过 **stdin** 把事件数据以 JSON 传入。`HookInput` 使用以下字段: | 字段 | 用途 | |------|------| | `session_id` | 状态文件隔离;为空则忽略本次 | | `prompt` | UserPromptSubmit 的用户输入,用作"完成"通知正文 | | `notification_type` | Notification 类型:`permission_prompt` / `idle_prompt` / `elicitation_dialog` / … | | `message` | Notification / 提问的文本 | | `tool_name` | PreToolUse 工具名:`AskUserQuestion` / `ExitPlanMode` | > **注意**:stdin 用 `OpenStandardInput()` 读**原始字节**再按 **UTF-8** 解码。不能用 `Console.In`——WinExe 下它不可靠,且会用控制台代码页(中文系统是 GBK)把中文解成乱码。 ## 标题分流(input) | 条件 | 标题 | |------|------| | `tool_name == AskUserQuestion` | Input Required | | `tool_name == ExitPlanMode` | Plan Ready for Approval | | `notification_type == permission_prompt` | Permission Required | | `notification_type == idle_prompt` | Application is Waiting | | `notification_type == elicitation_dialog` | MCP Asks | | 其它 | Input Required | 被**过滤**(不弹)的类型:`auth_success` / `elicitation_complete` / `elicitation_response`。 ## 状态文件 路径:`%TEMP%\notify-{session_id}.json`(`session_id` 做了文件名安全过滤)。 ```jsonc { "Hwnd": 329712, // 触发时前台窗口句柄 "Prompt": "重构通知模块", // 完成通知正文 "WtRuntimeId": "42.288...",// WT 当前标签 RuntimeId(非 WT 为空) "CallerExePath": "...\\WindowsTerminal.exe" // 调用方 App,用于取图标 } ``` - `notify`/`input` 读它来填 `NotifyMessage`(含点击要激活的 `TargetHwnd`、要切的标签、要显示的图标)。 - `cleanup` 删它。若 `SessionEnd` 没触发(崩溃等),文件会残留在 `%TEMP%`,无害。 ## 消息清洗 `notify`/`input` 投递前会把正文里的换行 / 制表 / 多余空格折叠成单行,避免撑乱 toast 布局;超长部分由 toast 的两行省略号截断。