首页
/ Gemini CLI 终端通知实战:配置与原理全解析(OSC 9 / OSC 777 / 终端铃声回退机制)

Gemini CLI 终端通知实战:配置与原理全解析(OSC 9 / OSC 777 / 终端铃声回退机制)

2026-09-04 23:16:53作者:齐冠琰

Gemini CLI 内置了一套实验性的系统通知能力:当会话结束、或 Agent 暂停等待你批准工具调用时,它可以通过终端转义序列触发操作系统级通知,让你可以放心切到别的窗口。本文以 docs/cli/notifications.md 为主线,完整覆盖启用方式、事件类型与终端兼容性要求,并深入 terminalNotifications.tsuseRunEventNotifications.ts,讲清“何时发、发给谁、发什么、发到哪个终端协议”这一整条链路。

功能定位与适用场景

Gemini CLI 可以发送系统通知来提醒你两类时机:

  • 会话成功完成(session complete);
  • 需要你的介入(action required),例如等待你批准一次工具调用、回答 Agent 的提问。

通知在两类场景下收益最大:运行耗时较长的自动化任务,以及使用 Plan Mode 让 Agent 在后台持续工作时——你只需瞥一眼桌面通知即可判断是否该回到终端。

注意:这是一个实验性功能,仍处于活跃开发阶段,默认关闭,需要手动在 /settings 中启用(详见下文)。

终端要求:OSC 9、OSC 777 与 BEL 回退

文档明确说明,CLI 使用 OSC 9\x1b]9;...BEL)终端转义序列触发系统通知,iTerm2、WezTerm、Ghostty、Kitty 等现代终端均支持该序列;当终端不支持 OSC 9 时,Gemini CLI 回退为终端铃声(BEL,\x07,多数终端会把它表现为任务栏闪烁或系统提示音。

从源码 terminalNotifications.ts 可以看到,除了 OSC 9 与 BEL,实现中还提供了一种更通用的 OSC 777\x1b]777;notify;标题;正文BEL,XDG 桌面通知协议,被 GNOME Terminal、Konsole、VTE 系终端广泛支持)。四种方法被统一定义在 TerminalNotificationMethod 枚举中:

方法 转义序列 说明
auto(默认) 按终端自动选择 见下方自动选择规则
osc9 \x1b]9;标题 | 副标题 | 正文\x07 iTerm2、WezTerm、Ghostty、Kitty 等
osc777 \x1b]777;notify;标题;正文\x07 GNOME/Konsole 等 XDG 桌面通知终端
bell \x07 通用回退,终端任务栏闪烁或响铃

auto 模式下的选择逻辑在 notifyViaTerminal 中,依据 TerminalCapabilityManager 探测到的终端能力:

  1. 检测到 iTerm2 → 发送 OSC 9;
  2. 检测到 Alacritty、Apple Terminal、VS Code 集成终端、Windows Terminal → 发送 BEL(这些终端没有可靠的桌面通知路径,铃声/任务栏闪烁更稳妥);
  3. 其余终端 → 发送 OSC 777。

此外,如果你在 tmuxGNU screen 里运行,转义序列会被包进 passthrough 透传封装,防止被多层终端吞掉(wrapWithPassthrough):

  • tmux:\x1bPtmux;(内部 ESC 双写为 \x1b\x1b)...\x1b\
  • screen:\x1bP...\x1b\

这解释了为什么在 tmux 会话中通知依然能到达最外层终端——对应的行为在 terminalNotifications.test.ts 中被显式验证。

启用通知:/settings 对话框或 settings.json

通知默认关闭。启用有两种等价方式。

方式一:交互式 /settings 对话框

  1. 在交互会话中输入 /settings 打开设置对话框;
  2. 进入 General 分类;
  3. Enable Notifications 开关切换为 On

方式二:直接编辑 settings.json

{
  "general": {
    "enableNotifications": true
  }
}

源码中的配置定义

这两个设置在 settingsSchema.ts 中有完整定义,可以据此核对取值范围与默认值:

配置项 类型 默认值 说明
general.enableNotifications boolean false 标签为 "Enable Terminal Notifications",控制 action-required 提示与会话完成两类运行事件通知;requiresRestart: false,即修改后无需重启会话即可生效
general.notificationMethod enum "auto" 取值 auto / osc9 / osc777 / bell,对应上表四种发送方式;同样无需重启

配置读取入口是 isNotificationsEnabled:只有当合并后的设置 general.enableNotifications === true 时通知才真正开启(严格等值判断,"true" 字符串等不会生效)。getNotificationMethod 则解析 notificationMethod,未知取值一律回落到 auto

因此如果你的终端是 WezTerm/Kitty/Ghostty 这类原生支持 OSC 9 的终端,但自动探测结果不理想,可以直接显式指定:

{
  "general": {
    "enableNotifications": true,
    "notificationMethod": "osc9"
  }
}

测试用例 explicit osc9 场景 验证了显式方法可以覆盖自动探测(例如在 Windows Terminal 中强制发送 OSC 9)。

通知事件类型详解

文档列出两类通知事件,源码给出了各自的精确触发条件与文案模板。

1. Action required(需要处理)

当模型在等待用户输入或工具批准时触发。触发判定集中在 pendingAttentionNotification.tsgetPendingAttentionNotification,它按优先级扫描六种等待状态,任何一种处于挂起状态都会构造一条 attention 事件:

  1. 工具确认tool_confirmation):若挂起工具是 ask_user,副标题为 “Answer requested by agent”,正文取第一个问题的题干;否则副标题为 “Approval required”,正文为 “Approve tool action: …”;
  2. 命令确认command_confirmation):某条命令正在等待确认;
  3. 认证确认auth_consent):认证流程等待确认;
  4. 文件系统权限确认filesystem_permission_confirmation):只读路径访问等待确认;
  5. 扩展更新确认extension_update_confirmation);
  6. 循环检测确认loop_detection_confirmation)。

最终渲染出的系统通知文案由 buildRunEventNotificationContent 组装:标题固定为 “Gemini CLI needs your attention”,副标题默认 “Action required”,正文默认 “Open Gemini CLI to continue.”。

防打扰逻辑(useRunEventNotifications.ts)保证了通知不会刷屏:

  • 焦点抑制:若终端当前持有焦点(且确实收到过焦点事件),则抑制通知——你既然在看屏幕,就不必再弹一次;
  • 状态变化驱动:仅在“刚进入等待状态”“终端刚失去焦点”或“等待项内容变化(key 改变)”时发送;
  • 冷却时间:同一等待项在 20 秒ATTENTION_NOTIFICATION_COOLDOWN_MS = 20_000)内不重复发送;
  • 自动清除:等待状态解除后,冷却记录立即重置。

2. Session complete(会话完成)

会话成功结束时触发。从 useRunEventNotifications.ts 看,触发条件是三者的精确交集:

  1. 流式状态发生 Responding → Idle 的迁移(即一轮回复刚刚完成);
  2. 终端不处于“有焦点”状态(焦点抑制同上);
  3. 当前没有挂起的 action-required 项——否则会改发 attention 通知,避免“完成”与“请处理”两条通知同时出现。

文案模板为:标题 “Gemini CLI session complete”,副标题 “Run finished”,正文默认 “The session finished successfully.”(实际调用时传入 “Gemini CLI finished responding.”)。

这个设计与 Plan Mode 或长任务自动化天然契合:后台跑一个多步骤任务,结束瞬间收到一次通知,且不会与“需要批准”类通知互相干扰。

通知内容的清洗与安全边界

通知正文最终要写进终端转义序列,源码对内容做了严格约束(terminalNotifications.ts):

字段 上限 默认回退
title 48 字符(MAX_NOTIFICATION_TITLE_CHARS 截断后为空则用 “Gemini CLI”
subtitle 64 字符(MAX_NOTIFICATION_SUBTITLE_CHARS 为空则省略
body 180 字符(MAX_NOTIFICATION_BODY_CHARS 为空则用 “Open Gemini CLI for details.”

具体处理包括:

  • 转义序列剥离:正文中的 ANSI 颜色/控制序列与换行会被 sanitizeForDisplay 移除,测试 strips terminal control sequences 验证了 \x1b[32m\n 不会泄漏进 OSC 负载;
  • OSC 777 分号转义:OSC 777 协议本身以 ; 分隔字段,因此标题与正文中的 ; 会被替换为 :,避免截断序列(emitOsc777Notification,对应测试见 semicolon 用例);
  • 写入失败静默降级notifyViaTerminal 捕获写入异常并仅记一条 debug 日志返回 false,通知失败绝不影响主会话运行。

完整调用链与验证

整条链路在代码中的走向是:

  1. AppContainer.tsx 启动时通过 isNotificationsEnabled(settings)getNotificationMethod(settings) 读取配置,连同焦点状态、流式状态、各类挂起确认请求一起传入 useRunEventNotifications Hook;
  2. Hook 内按上文规则判定“是否需要发”;
  3. 命中后调用 notifyViaTerminal(notificationsEnabled, content, method),按方法选择 OSC 9 / OSC 777 / BEL 序列,必要时加 tmux/screen passthrough 封装,经 writeToStdout 写向终端;
  4. 终端把序列交给操作系统/桌面环境呈现为系统通知。

可运行与可验证的依据集中在:

  • 单元测试 terminalNotifications.test.ts:覆盖“关闭时不写输出”“iTerm2 走 OSC 9 且以 \x07 结尾”“Windows Terminal/Alacritty/VS Code 走 BEL”“未知终端走 OSC 777”“tmux/screen 透传封装”等 15+ 个断言;
  • UI 层测试 AppContainer.test.tsx:在多种挂起确认场景下断言 notifyViaTerminal 被调用;
  • 集成入口测试 gemini.test.tsx:验证通知模块的接线与关闭时的静默行为。

推荐配置与使用建议

结合文档与源码行为,给出几条实用配置:

{
  "general": {
    "enableNotifications": true,
    "notificationMethod": "auto"
  }
}
  • 在 iTerm2 / WezTerm / Ghostty / Kitty 中可保持 auto(前两者会被探测并选择 OSC 9 / OSC 777 路径);若想强制走 OSC 9 桌面通知,显式设置 "notificationMethod": "osc9"
  • 在 tmux / GNU screen 中使用时无需额外配置,passthrough 封装会自动处理;
  • 通知只在你不看终端时才弹出(焦点抑制),所以测试时请切到别的窗口再触发等待批准的操作;
  • 配合 Plan Mode 或长任务运行时开启,完成即收到 “session complete” 通知;
  • 更多体验定制可参考 settings 文档,其中 enableNotificationsnotificationMethod 均标记为无需重启(requiresRestart: false),改完立即生效。
登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.12 K
2.72 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
528
588
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
906
1.83 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
854
1.34 K
docsdocs
暂无描述
Markdown
891
5.78 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.53 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.34 K
1.45 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
987
506
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
540
384