# Claude Code Notify > 为 Claude Code 提供原生 Windows 通知:任务完成或需要你输入时弹出 toast,**点击即可跳回原终端 / 编辑器窗口**(并能切回正确的 Windows Terminal 标签页)。 原版 Rust 项目的 **C# / .NET 10 + Avalonia 12** 重写版,采用「CLI 子命令 + 常驻 Host」进程模型,由 Claude Code 的 hook 驱动。仅支持 Windows 10 / 11 (x64)。 ## 功能 - 任务完成 / 需要输入时弹出原生 toast,可堆叠、自由定位(水平 × 垂直 + 留白)、跨虚拟桌面显示 - 点击 toast 跳回发起请求的窗口,并能切回原 Windows Terminal 标签页 - 自动识别并显示调用方 App 图标(VSCode / Cursor / JetBrains / 终端…) - 输入类通知常驻、完成类自动消失(正盯着目标窗口时停留更短) - 非阻塞投递,钩子毫秒级返回,不拖慢 Claude Code - NativeAOT 单文件、无运行时依赖 ## 架构 ```mermaid flowchart LR CC[Claude Code] -->|UserPromptSubmit| SAVE["notify save"] CC -->|Stop| NOTIFY["notify notify"] CC -->|Notification / PreToolUse| INPUT["notify input"] CC -->|SessionEnd| CLEAN["notify cleanup"] SAVE --> ST[(状态文件)] CLEAN -.删除.-> ST NOTIFY --> SP[(spool 队列)] INPUT --> SP SP --> HOST ST -.读取.-> NOTIFY ST -.读取.-> INPUT subgraph HOST["notify host (Avalonia 常驻)"] W[FileSystemWatcher] --> T1[Toast] W --> T2[Toast] end T1 -->|点击| ACT[激活窗口 + 切 WT 标签] ``` - **CLI 子命令**(`save` / `notify` / `input` / `cleanup`):纯 Win32 互操作 + 落盘,不加载 Avalonia,做完即退,毫秒级返回。 - **Host**:Avalonia 单例常驻,仅托盘存在,监视 spool 目录弹通知。 详见 [docs/architecture.md](docs/architecture.md)。 ## 时序 ### 整体生命周期 ```mermaid sequenceDiagram autonumber actor User as 用户 participant CC as Claude Code participant Cli as notify (CLI) participant State as 状态文件 participant Spool as spool 队列 participant Host as notify host participant Win as 目标窗口 User->>CC: 发送消息 CC->>Cli: notify save (stdin: session_id + prompt) Cli->>Cli: 抓前台窗口 / 进程树取图标 / WT 标签 Cli->>State: 写入状态 Cli-->>CC: 立即退出 Note over CC: Claude 处理中… alt 任务完成 CC->>Cli: notify notify else 需要输入 / 提问 / 出 Plan CC->>Cli: notify input end Cli->>State: 读取状态 Cli->>Spool: 原子写入 NotifyMessage Cli->>Host: 不在则拉起(不等待) Cli-->>CC: 立即退出(~100ms) Host->>Spool: FileSystemWatcher 消费 Host-->>User: 弹出 toast User->>Host: 左键点击 toast Host->>Win: 抢前台激活 (+ 切回 WT 标签) Win-->>User: 回到原窗口 User->>CC: 结束会话 CC->>State: notify cleanup 删除状态 ``` ### 非阻塞投递 CLI 写完 spool 即走、不等 Host,因此钩子毫秒级返回。 ```mermaid sequenceDiagram autonumber participant Cli as notify notify/input participant Spool as spool 目录 participant Mtx as 单例互斥量 participant Host as notify host Cli->>Spool: 写 tmp → 原子改名 json Cli->>Mtx: TryOpenExisting? alt Host 已在跑 Mtx-->>Cli: 存在 → 不拉起 else Host 未运行 Cli->>Host: Process.Start("host", UseShellExecute=true) end Cli-->>Cli: 立即返回(~100ms) Host->>Spool: 启动 DrainExisting + Watcher 增量 Host->>Host: 读取并删除文件 → UI 线程弹 toast ``` ### 点击 toast → 激活原窗口 ```mermaid sequenceDiagram autonumber actor User as 用户 participant Toast as ToastWindow participant Act as WindowActivator participant WT as WinTerminalTabs participant Win as 目标窗口 User->>Toast: 左键点击主体 Toast->>Act: Activate(targetHwnd) Act->>Win: ALT 模拟 + AttachThreadInput + SetForegroundWindow 组合技 Win-->>User: 窗口回到前台 opt 目标是 Windows Terminal 且有 RuntimeId Toast->>WT: SelectTab(hwnd, runtimeId) WT->>Win: UIAutomation 找到标签 → Select() end Toast->>Toast: 淡出关闭 ``` ## 安装 ```bash claude plugin marketplace add https://git.pchuan.top/cc-tools/notify.git claude plugin install claude-code-notify@claude-code-notify ``` 重启 Claude Code 后即生效。首次触发钩子时,`scripts/notify.cmd` 会自动从 Release 下载单文件 `notify.exe`,之后常驻。 - 托盘**左键单击**打开设置,**右键**退出。 - 从源码构建见 [docs/build-and-install.md](docs/build-and-install.md)。 ## 文档 | 文档 | 内容 | |------|------| | [architecture.md](docs/architecture.md) | 进程模型、组件、目录结构 | | [hooks-and-cli.md](docs/hooks-and-cli.md) | hook 事件、子命令、stdin、状态文件 | | [interop.md](docs/interop.md) | 原生互操作与 AOT 说明 | | [build-and-install.md](docs/build-and-install.md) | 构建、安装、排错 | ## 许可 [MIT](LICENSE)