162 lines
5.0 KiB
Markdown
162 lines
5.0 KiB
Markdown
# 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)
|