Files
notify/README.md
T

5.0 KiB
Raw Blame History

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 单文件、无运行时依赖

架构

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

时序

整体生命周期

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,因此钩子毫秒级返回。

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 → 激活原窗口

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: 淡出关闭

安装

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,之后常驻。

文档

文档 内容
architecture.md 进程模型、组件、目录结构
hooks-and-cli.md hook 事件、子命令、stdin、状态文件
interop.md 原生互操作与 AOT 说明
build-and-install.md 构建、安装、排错

许可

MIT