别再盯着那一行 (1) 了:Hermes 现在让标签页闪、任务栏跳、浏览器弹通知


下午四点,你把 Hermes 丢在一个标签页里跑施工,自己切到另一个窗口改代码。它中途停下来等你批准一条 rm -rf 命令,标签标题悄悄从 “Hermes” 变成了 “Hermes (1)”。这个 (1) 混在十几个标签里,你根本没看见。两个小时后你切回去,发现它一动不动地等了你两个小时,什么活都没干。

这不是 Hermes 独有的问题,是所有“跑在后台的助手”的通病:它有事找你的时候,用的信号太弱了。弱到你需要主动去看它,而主动去看它这件事,恰恰是你忙起来最先放弃的。

现在 Hermes 把这件事当成一个正经的注意力问题来做了:Webapp 会闪标签标题、给 favicon 点上一个琥珀色圆点;桌面端会在窗口不在前台时闪任务栏(macOS 是 Dock 跳一下,Linux 是 urgent hint);你允许之后,浏览器还会弹出真正的系统通知,点一下直接回到那条对话。

以前只有一个 (1),现在有三层信号

先看清楚这套信号是怎么分层的,因为它设计得很克制——每一层都在解决“我有多确定用户不在看屏幕”这个问题。

层 出现条件 具体表现 停止时机
标签标题闪烁 Webapp 标签隐藏或失焦 标题每秒在通知标题(如 Approval needed — <对话名>)和正常标题之间切换 你切回标签
favicon 圆点 同上 图标上叠一个琥珀色(#f59e0b)小圆点 你切回标签
浏览器通知 你亲手点过 Allow 系统级弹窗,点击后聚焦标签并打开对应会话 你自己关掉或点击
任务栏闪动 桌面端窗口失焦时收到系统通知 Windows 任务栏闪烁 / macOS Dock 弹跳 / Linux urgency hint 窗口获得焦点

注意两层之间的分工:标签闪烁不需要任何授权,只要事件发生、标签不在前台就会闪;浏览器通知需要你明确授权,因为浏览器对“没有用户手势就申请权限”的弹窗会直接忽略甚至惩罚。所以在没授权之前,闪烁是唯一的信号;授权之后,两者一起工作。

浏览器通知为什么必须你亲手点一次 Allow

这一条值得单独说,因为它是很多人“配了通知却从来没收到过”的真正原因。

以前的做法是:事件来了,Hermes 顺手调一次 Notification.requestPermission()。问题是浏览器(Chrome、Safari、Firefox 都是)要求权限申请必须由用户手势触发——一次点击、一次按键。由一个后台事件发起的申请,浏览器要么直接忽略,要么静默拦掉,你连拒绝的机会都没有。

现在的做法是:权限只在两个地方申请,都在设置页里、都由你点击触发:

  • 设置 → 通知 → 浏览器通知 → Allow
  • 或者旁边的 Send test notification 按钮

Hermes 不会在页面加载时问,也不会在事件到达时问。你不点,它就只闪标题,不会弹窗——这是个明确的取舍:宁可少打扰一次,也不去撞浏览器的规则。

还有一个坑:浏览器的 Notification API 只在安全上下文里可用。http://localhost 和 http://127.0.0.1 算安全,Tailscale serve 那种 HTTPS 地址也算;但如果你是用 http://192.168.x.x:8317 直接从另一台机器打开 Webapp,那就是普通 HTTP,通知不可用。这种情况下设置页那一行会直接告诉你“需要 HTTPS,例如 Tailscale serve”,而标题闪烁依然有效——这也是为什么闪烁被设计成不依赖任何授权。

桌面端:任务栏闪一下,苹果是 Dock 跳一下

桌面端走的是另一条路:它本来就有系统原生通知,缺的是“窗口在后台的时候,除了弹一个可能被勿扰模式吞掉的通知,还能做什么”。

现在当一条系统通知在窗口失焦时发出,Electron 主进程会调用 BrowserWindow.flashFrame(true):Windows 上任务栏图标闪,macOS 上 Dock 图标跳,Linux 上给窗口发 urgency hint。窗口一获得焦点,闪动立刻清掉(flashFrame(false))。这个能力的原始补丁来自社区贡献者,被 cherry-pick 时保留了署名。

关键设计是它不会抢焦点:闪动只是“喂,有事”,不会把你的窗口拽到前台,也不会自己跳到某条对话。切换只发生在你点击通知之后。

怎么开、怎么关:跟着已有的通知开关走

这套新信号没有引入一套新的配置体系,它复用桌面端已有的通知设置(设置 → 通知,Per device,即跟着设备走):

  • Enable notifications 总开关:关掉之后,下面所有类型都静音,也就不会有任何信号。
  • 七类事件各自一个开关:审批需要你(Approval needed)、需要输入(Input needed)、回复就绪(Response ready)、回合失败(Turn failed)、后台任务完成(Background task finished)、额度提醒(Credit alerts)、插件通知(Plugin notifications)。
  • 某一类关掉,它就不会触发闪烁,也不会发通知。 换句话说,不想被“任务完成”打扰,就把那一类关掉,而不是关掉整个能力。
  • Send test notification 用来验证链路:桌面端会走原生通知,Webapp 会先申请权限、再发一条 “Notifications are working.”。

如果你在 Webapp 里,命令是 hermes webapp;想确认网关到底有没有在服务 Webapp、以及它用的是哪个地址,用 hermes webapp --status。这两条命令输出的地址就是你判断“是不是安全上下文”的依据。

什么时候它还是不会提醒你

几个诚实的边界,免得你配完发现“怎么还是没反应”:

  • 窗口在前台时不闪。 完成类通知本来就只在你不在的时候发;如果你正盯着那个窗口,Hermes 认为你已经在看了。
  • 普通 HTTP 的局域网地址没有浏览器通知,只有标题闪烁。
  • 勿扰模式 / 专注模式会吞掉系统通知,但不会吞掉任务栏闪烁和标签闪烁——这也是分层设计的价值。
  • 浏览器被系统挂起(比如笔记本休眠)时它不会在睡梦中弹出来,醒来后标签重新可见,闪烁会补上。
  • 点击通知只会切到对应会话,不会自动替你批准任何东西。 审批仍然要你自己点。

现在能用吗

这套改动在 2026-10-30 合入 main(PR #146882,一次社区请求的实现,原始补丁 #146542 被 salvage 并保留作者署名),并已随 v0.22.6(2026-11-02 发布) 进入正式发行版——从安装包或 hermes update 升到 v0.22.6 就有了。

想现在就试的话,需要跟 main 跑(源码安装),或者等下一个版本。等它进 release 之后,升级完记得去设置页把浏览器通知的 Allow 点一次——不然你只会看到标题闪,看不到弹窗,然后又以为功能没做。

顺带一提,如果你被“后台任务完成”这一类通知烦过,我们之前写过一篇讲 Hermes 如何把多个已完成的后台任务合并成一次通知的说明,可以配合这篇一起看:/zh/blog/hermes-background-notification-batching/。一个解决“通知太多”,一个解决“通知太弱”,是同一件事的两端。