Liu Terminal 通知。当 AI 代理完成任务时收到通知,支持可配置钩子和声音提醒。
liu-notify 是一个可选的独立进程,但 Liu GUI 也可以在进程内托管同一服务器。它通过本地套接字接收 24 字节的 v1 标头或带可选元数据的 28 字节当前 v2 标头,使用令牌桶限流,对相同事件去重,并为每个(代理,事件)对路由声音或语音。
# 与主应用一起构建
cmake --build build --target liu-notify
# 启动守护进程
./build/liu-notify daemon
# 发送一次性事件
./build/liu-notify send --tool=claude --event=stop
配置文件位于 ~/.config/liu/notify.conf —— 与主应用的 config.json 分离,因此即使 Liu 本身未运行,守护进程仍可保持可用。
When Liu is running, its GUI hosts the notification server in-process; the CLI does not need to start a second daemon. If no server is listening, send exits without delivering an event. Use the standalone daemon only when notifications must work without Liu.
Liu 可以在应用运行期间为以下代理安装和移除生命周期钩子。钩子写入代理自己的配置,承载服务的 Liu 实例退出时会删除由其管理的条目。
| 代理 | 钩子位置 | 信号 | 说明 |
|---|---|---|---|
| Claude Code | ~/.claude/settings.json | start · notify · complete | UserPromptSubmit drives the working state; Notification and Stop can alert you. |
| Codex | ~/.codex/config.toml | complete | The Stop hook reports a completed turn. Run /hooks in Codex once to trust it. |
| Grok | ~/.grok/hooks/liu-notify.json | notify · complete | Notification and top-level Stop events are handled; sub-agent completions stay silent. |
| OpenCode | ~/.config/opencode/plugins/liu-notify.js | complete | The managed plugin listens for top-level session.idle events. |
| Antigravity | ~/.gemini/config/hooks.json | complete | A named Stop hook reports when the top-level execution loop ends. |
| Command Code | ~/.commandcode/settings.json | complete | Its Claude-compatible settings schema is wired to the top-level Stop event. |
Copilot 和 custom 可由底层通知协议和声音矩阵接受,但 Liu 目前尚未为它们安装自动生命周期钩子。其他代理仍可在 Liu 标签页中正常运行,只是不会收到自动钩子通知。
为任何组合配置声音规则。未设置的单元格将回退到通用规则。
| start | stop | notify | error | complete | |
|---|---|---|---|---|---|
| claude | · | · | · | · | · |
| copilot | · | · | · | · | · |
| codex | · | · | · | · | · |
| custom | · | · | · | · | · |
v1 标头为 24 字节;当前 v2 标头为 28 字节,因为增加了 meta_len。完整帧上限为 4096 字节。tests/fuzz_notify_validate.c 对校验进行了模糊测试,格式错误的帧会安全拒绝,不会导致服务器停止。
offset size field
0 4 magic ('N','T','F','Y')
4 2 version (1 or current 2)
6 2 flags (speak=1, bell=2)
8 1 tool_id (claude=1, copilot=2, codex=3, custom=255)
9 1 event_id (start=1, stop=2, notify=3, error=4, complete=5)
10 1 priority (reserved)
11 1 source (cli=0, stdin=1, test=2)
12 4 seq (client nonce — for dedup)
16 4 title_len (<= 256)
20 4 body_len (<= 3072)
24 4 meta_len (v2 only, <= 512)
payload title, body, then metadata key=value lines
total frame <= 4096 bytes
v2 元数据部分目前包含 cwd=、session= 和 agent= 行。钩子发送方用它将事件归因到正确面板;未知键会被忽略以保持向前兼容。
相同的帧,不同的扬声器。macOS 使用 AVSpeechSynthesizer,Linux 调用 notify-send。每个后端都驻留在自己的文件中(platform_notify_macos.m、platform_notify_linux.c),因此更换或存根其中一个只需修改一个文件。
English · Türkçe · 한국어 · Español · Deutsch · Italiano · Français · 日本語 · العربية