5ce2c8a982
为 Claude Code 提供原生 Windows toast 通知:点击跳回原窗口、切回 Windows Terminal 标签、跨虚拟桌面、调用方图标、非阻塞投递;NativeAOT 单文件分发。
61 lines
2.8 KiB
Markdown
61 lines
2.8 KiB
Markdown
# Hook 与 CLI
|
||
|
||
## Hook → 子命令映射
|
||
|
||
| Claude Code 事件 | 子命令 | 作用 |
|
||
|------------------|--------|------|
|
||
| `UserPromptSubmit` | `notify save` | 记录前台窗口、prompt、WT 标签、调用方图标路径 |
|
||
| `Stop` | `notify notify` | 弹"任务完成"通知(自动消失,聚焦时更短) |
|
||
| `Notification` | `notify input` | 弹"需要输入"通知(常驻),按类型分标题 |
|
||
| `PreToolUse`(`AskUserQuestion`/`ExitPlanMode`) | `notify input` | 提问 / 出 Plan 时弹常驻通知 |
|
||
| `SessionEnd` | `notify cleanup` | 删除该会话状态文件 |
|
||
|
||
`hooks/hooks.json`(插件形式)里命令为 `${CLAUDE_PLUGIN_ROOT}/bin/notify.exe <子命令>`;直连 `settings.json` 时可写 `notify <子命令>` 或绝对路径。
|
||
|
||
## stdin JSON
|
||
|
||
Claude Code 通过 **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` | Claude is Asking |
|
||
| `tool_name == ExitPlanMode` | Plan Ready for Approval |
|
||
| `notification_type == permission_prompt` | Permission Required |
|
||
| `notification_type == idle_prompt` | Claude is Waiting |
|
||
| `notification_type == elicitation_dialog` | MCP Asks |
|
||
| 其它 | Input Required |
|
||
|
||
被**过滤**(不弹)的类型:`auth_success` / `elicitation_complete` / `elicitation_response`。
|
||
|
||
## 状态文件
|
||
|
||
路径:`%TEMP%\claude-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 的两行省略号截断。
|