Repository navigation
Releases: hxddh/Pulse
Release list
Pulse 29.0.1
29.0.1
两处修正,都来自 29.0 的代码评审:
- 横幅一次只发一条。 同一次扫描里出现好几个等待时,以前会同时弹出多条横幅和提示音,违反了“两条横幅至少间隔 3 秒”的规则。现在先发第一条,其余排队,每 3 秒一条;间隔从横幅交给通知中心那一刻算起,不等它回复。
- 托盘和详情页的“停滞”灯补上缺口。 以前只有菜单栏的停滞灯有右上角缺口,行旁和详情页只靠橙色和绿色区分。现在三处都用菜单栏那一套画法,不看颜色也能认出停滞。
仍是 ad-hoc 签名、未公证的 preview 包,没有在真机上验证过。
Gatekeeper
This build is ad-hoc / unnotarized (no Apple Developer ID in CI).
About stays preview — it is not Gatekeeper-ready and must not be
described as notarized stable. First open: drag Pulse to Applications and
open it once; when macOS blocks it, go to System Settings → Privacy &
Security, scroll to Security and click Open Anyway. Or, in Terminal:
xattr -dr com.apple.quarantine /Applications/Pulse.app.
(macOS 15 removed the Control-click → Open shortcut.)
Download verification
37b2d591463ab40c0c84ab73b9eabb74175c258fd0fbbc936761173ed26614f3 pulse-29.0.1-macos-PulseBar.dmg
Pulse 29.0.0
29.0.0 — Lean(减)
维护者的原则:简洁、优雅、易用;不考虑旧版本。 这一版几乎只做减法 —— 一个状态灯不该有那么多开关。
能交给 macOS 的交给 macOS,能删的删掉,留下的每一样都更好用。
删掉的
- 更新检查 → 设置页脚只剩「版本发布…」,在浏览器里打开 Releases 页。Pulse 不再发起任何网络连接(门禁把守)。
- 全局快捷键 → 在 Spotlight / Raycast 里再打开 Pulse 就是打开托盘;想要按键,用启动器给它设。
- 按 Agent 静音、通知开关 → 交给 macOS 的通知设置与专注模式。
- 语言选择器 → 界面语言跟随系统。
- 终端自动化开关与「开启」按钮 → 总是尝试确切落地;第一次前往时 macOS 自己的「自动化」询问就是同意。
- 「卸载 Pulse…」按钮 → 卸载步骤写在 README;逐个 Agent 的安装 / 移除按钮 → 只留「全部安装」「全部移除」。
- 汇总横幅 → 一个等待一条横幅,按会话归入各自的通知线程。
- 「Dismiss / Ignore」 → 处处统一为「忽略」。设置卡上的「登录时打开」复选框也删了(登录项只在设置里)。
- 所有旧版本兼容:旧 LaunchAgent 的迁移、设置迁移、旧 hook 标记的识别、旧文件清理,全部删除。
改了的
- 托盘是系统的
NSPopover:系统材质、箭头指着按钮、点外面就关,不再自己画面板。 - 一种灯:菜单栏、托盘行、计数与提示用同一个
Lamp。 - 时长交给系统格式化:一个单位、向下取整;不到一分钟一律写「刚刚」。
- 事件日志协议 v6(10 列,去掉保留的空列)。表头不是 v6 的旧日志不读、不迁移:首次启动时清空,从新日志开始。
- 文档、门禁与测试只留守住真事实的部分:删除场景表与它的门禁、changelog 归档;观测矩阵并入 EXPERIENCE,
安装政策并入 vendor-formats,落地说明并入 architecture;删掉只钉实现的测试(尺寸预算、夹具清单、历史标签)
并合并重复的,每张行为真值表都保留。
数字
| 28.0.0 | 29.0.0 | |
|---|---|---|
PulseApp 代码行 |
12,735 | 10,253 |
PulseApp 源文件 |
48 | 33 |
文案键(L10n.Key) |
196 | 133 |
文档(.md,不含 CHANGELOG) |
11 个 · 6,923 行 | 6 个 · 1,056 行 |
| 测试代码行 | 7,925 | 7,590 |
已知限制 / 注意
- 没有在真机上跑过。 只在 CI(macos-26)上编译和测试。弹出框在配件型 App 里能否拿到键盘焦点、关掉后焦点
是否交还给原来的 App、行的高亮、弹出框的尺寸,都需要一台真的 Mac 确认。 - 升级的人请注意:
- 旧的
events.tsv会在首次启动时被清空:已经开着的等待、上一步与标题从新事件重新开始。 - 很老的 Pulse 用旧标记写下的 hook 条目不再被认出,「全部移除」不会动它们 —— 请在各 Agent 的配置里手动删掉。
- 用过全局快捷键、按 Agent 静音或语言选择器的,这些设置没有了。
- 旧的
- 仍是 ad-hoc 签名、未公证的
preview包。
Gatekeeper
This build is ad-hoc / unnotarized (no Apple Developer ID in CI).
About stays preview — it is not Gatekeeper-ready and must not be
described as notarized stable. First open: drag Pulse to Applications and
open it once; when macOS blocks it, go to System Settings → Privacy &
Security, scroll to Security and click Open Anyway. Or, in Terminal:
xattr -dr com.apple.quarantine /Applications/Pulse.app.
(macOS 15 removed the Control-click → Open shortcut.)
Download verification
7e365b788e6e56c8e7eb6632f68b7f14a0ea6a221279dd9e260edf8ad1772e90 pulse-29.0.0-macos-PulseBar.dmg
Pulse 28.0.0
28.0.0 — Reach(触手可及)
这一版让托盘里的每件事用鼠标也够得着。之前点一行永远是去终端,详情页唯一的鼠标入口是一个只在
悬停时出现、14 pt 宽的「›」——看不见就点不着;列表过了 12 行要再点「另有 N 个」;终端自动化的提示只能
告诉你去设置里找开关;横幅只能「前往」;全局快捷键只有两个预设。现在:点行身前往,点行尾常驻的「›」
(或 ⌥-点)看详情,指针指到哪行就选中哪行;列表列出每个会话并在面板里滚动;「开启」就在提示旁边;
横幅能直接「忽略」;快捷键自己录。另外修了 27.0 留下的七个问题。
它是一个大版本:事件日志 tool 列的保留值变了——Pulse 自己的标记以 : 开头(:status、
:dismiss),这是一次协议变更(旧的裸 status 只在读 Copilot / OpenCode 的旧行时认)。
读对(修复)
- 只有 Pulse 里的忽略会吞掉回声。 「同一次提问 20 秒内的补发不重新变红」只在 Pulse 自己写的忽略
(done行 tool 列为:dismiss)之后生效;厂商自己说「已回答」(OpenCodepermission.replied/
question.replied、Piui_prompt_end、Claudeelicitation_complete)之后又问同一件事,是真的又问了
一次,照常变红、发横幅——之前它会被当成回声吞掉。 - 登录项先注册,再卸旧的。 旧版本写的 LaunchAgent 只在 macOS 接受了登录项(开着或待批准)之后才卸掉、
删除;注册失败就留着它、设置不动,开关旁说 macOS 没有接受——人的选择从不丢。 - 卸载总是注销登录项。 「卸载 Pulse…」不再依赖可能过时的读数,总是向 macOS 注销(本来关着的注销
什么都不做)。 - 右键菜单不会自己套自己。 菜单开着时再点状态项,不会在菜单里面再弹一次菜单。
- ⌘W 关托盘。 托盘开着时 ⌘W 是托盘自己的键(列表上同 Esc,详情页上也直接关),不再落到无边框面板
上响一声。 - 主菜单跟着语言。 在设置里换语言,隐藏的主菜单立刻按新语言重装,不等下次打开设置。
- 保留标记不撞工具名。 事件日志 tool 列里 Pulse 自己的标记是
:status(只说还在干活)与:dismiss
(Pulse 里的忽略);接收端去掉厂商工具名开头的:,所以厂商工具名永远拼不出标记,一个真叫status
的工具不再被读成状态行。为了重放旧日志,Copilot / OpenCode 行里的裸status仍按:status读(只有这两个
Agent 的旧接收端这样写过)。
够得着(新的)
- 点一行去哪儿,一眼就知道。 点行身(两行都算)= 前往(没有终端可落就打开详情);行尾一列「›」
约 28 pt 宽、与整行等高,始终画着、始终能点,点它 = 详情;⌥-点行上任何地方 = 详情。键盘不变:
↩ 前往,→ / 空格 详情,← / Esc 返回。行上 Agent 名的 tooltip 去掉了(VoiceOver 标签里仍有)。 - 指针指到哪行,哪行就是选中。 只剩一个高亮,像菜单:指针和键盘移动同一个选中;只有键盘的移动会让
列表滚动。VoiceOver 里行的默认动作仍是前往,「›」是它自己的「详情」按钮。 - 详情页每件事只说一次。 主行成了页面头部的标题(至多两行、可选中),下面不再重复;只留一个时钟
「本回合」(去掉头部的「状态 · 时长」和「开始于」);停滞行的「为什么」就是行的第二行,不再说第二遍。
问题全文、最近 5 步、最后的消息、错误、目录、落地提示与前往按钮都在。 - 列表不再折叠。 去掉 12 行上限和「另有 N 个… / 收起」:每个会话都列出,在面板原有的高度上限内滚动;
打开期间顺序照旧冻结,新行追加在末尾。 - 「开启」就在提示旁边。 前往只落到 App、而挡在确切落地前的正是关着的终端自动化时,行上和详情页上的
那句提示旁有一个「开启」:它改的就是设置 → 通用里同一个开关,需要的那一刻征得同意;下一次前往时 macOS
仍会弹出它自己的「自动化」询问。带按钮的提示停留 20 秒。 - 横幅上的「忽略」。 「需要你」横幅除了「前往」多了「忽略」:与托盘的 ⌘D 走同一条路(Pulse 自己的
done,tool 列:dismiss,横幅撤回),只忽略横幅点名、仍开着的等待;从不回答厂商的提示,也不把
Pulse 带到前台。 - 快捷键自己录。 设置 → 快捷键从两个预设换成录制器:点它,按下一个带 ⌘、⌃ 或 ⌥ 的组合(Esc 取消,
Delete 清除),按 macOS 的写法显示(⌃⌥⇧⌘ + 键);存成 key code + Carbon 修饰键(settings.json的
globalShortcut),用RegisterEventHotKey注册,不需要任何隐私权限。macOS 自己占着的(⌘Space、⌘Q、
系统键盘快捷键里开着的那些)或注册不上的,直说「不能使用这个快捷键」,旧的保留。旧设置里的 ⌃⌥Space、
⌥⌘P 读作同样的按键;默认仍是关闭。
删掉的
- 托盘底部的「另有 N 个… / 收起」、
TrayState.maxVisibleRows、showAllAgents与它们的文案。 - 详情页的「开始于」和它唯一的用户
LogClock(按区域格式化时刻的三个测试随之删除)。 - 悬停才出现的 14 pt「›」、单独的悬停底色、行上的 Agent 名 tooltip。
- 快捷键的两个预设(
HotkeyChoice)与设置里的「关闭」选项。
已知限制 / 注意
- 这一版没有在真机上验证过。 代码只在 CI(macos-26)上编译和测试:行尾「›」的点按区域、⌥-点、
指针选中、横幅的「忽略」、快捷键录制器、「开启」按钮,都没有在一台真的 Mac 上和真的 Agent 一起跑过。 - 仍是 ad-hoc 签名、未公证的
preview包。 Developer ID 还没到位。 - 27.0 写下的忽略没有标记。 27.0 的忽略行 tool 列是空的:升级后启动重放日志时,它们读作厂商的
「已回答」。于是一个极窄的情况会重新变红:27.0 里忽略了一个等待、Claude 随后对同一次提问的补发也已在
日志里、而那之后这个会话再没有别的行——重放后它亮红(是启动基线,不发横幅),直到被回答或再忽略一次。 - 不是每个被占用的全局快捷键都能事先看出来。 Pulse 读 macOS 自己开着的键盘快捷键并拒绝一小份保留
组合;别的 App 占着的组合只有注册失败时才知道,某些 App 用别的方式截键时 Pulse 看不出来。 - 快捷键的键名按美式键盘写。 录下的是物理按键(key code);非美式布局上显示的字母可能与键帽不同。
Gatekeeper
This build is ad-hoc / unnotarized (no Apple Developer ID in CI).
About stays preview — it is not Gatekeeper-ready and must not be
described as notarized stable. First open: drag Pulse to Applications and
open it once; when macOS blocks it, go to System Settings → Privacy &
Security, scroll to Security and click Open Anyway. Or, in Terminal:
xattr -dr com.apple.quarantine /Applications/Pulse.app.
(macOS 15 removed the Control-click → Open shortcut.)
Download verification
f2a9e0d51b927aa7234f856af73a49167574daa788a40871f26e9b6ffcd37902 pulse-28.0.0-macos-PulseBar.dmg
Pulse 27.0.0
27.0.0 — Craft(匠)
这一版把 Pulse 做成一个像 Mac 应用的 Mac 应用,同时把它读错的地方一一修好、把不再需要的东西删掉:
八个会让托盘说错话的问题各有一个钉住它的测试;再打开 Pulse 就是打开托盘,登录项交给 macOS,菜单栏的灯
清楚、跟着菜单栏着色;设置里能一键卸载 Pulse。它是一个大版本:hook 接收器不再接受协议词
(permission、turn、done… 作为事件名,或纯文本载荷)——只读每个 Agent 自己的厂商事件;事件日志的
kind 只认 v5 的十个词、不认别名;tool 列的 status 成为保留值;托盘上的「终端自动化」提议没有了,
改为设置里的一个开关。
这一版先以 GitHub 预发布发出,随后按维护者的决定直接转为正式版(Latest),没有等真机冒烟。
读对(修复)
- 一行只应用一次。 一次读取落地前又被要求读一次时,两次读到的同一批行不会被应用两遍(工具步骤
不再重复、回合时钟不再被第二遍推后);落地时只应用游标之后的行,来自旧一代日志的读取什么都不应用。 - 忽略就是忽略。 在 Pulse 里忽略一个等待后,Claude 约 6 秒后对同一次提问补发的
Notification permission_prompt不再让它重新变红、再发横幅(同一种阻塞、离那次提问 20 秒内、
忽略之后没有提示或工具行、话没说出新东西)。 - 压缩不丢标题。 日志压缩时,每个会话总留下它第一条不是阻塞的行、标题出自的那条提示与最新的
一条提示——重放之后标题、开始时间与本回合时长都不变。 - 解析不了的 payload 一行都不写。 被截断(1 MiB 上限)或坏掉的 JSON 不再变成一个把原始 JSON
当问题的幽灵等待。 - 上一回合的错误不留到下一回合。 新的提示(或回合结束后的工具行)清掉上一回合的错误。
- 状态行从不回答等待。 Copilot 的可恢复
errorOccurred、OpenCode 的session.status
忙碌 / 重试写成tool行、工具列为保留值status:它让会话保持在跑,但不是一步、也不熄灭红灯。 - 先脱敏、再截断。 凭据从整段值里抹掉之后才截到行的长度——一个跨在截断处的 token 不会留下开头几位。
- 重写后的日志按位置认行。 以最后应用的那一行为锚:锚之后的都是新的,即便文本和之前的某行相同;
压缩没留下锚时,才逐行对上下一个同文的已应用行。
- 从 hook 到横幅的端到端测试:七个 Agent 各自的厂商载荷 →
pulse-hook写行 → 引擎按游标读入 →
灯 → 欠的横幅 → 厂商的回答 → 灯熄、横幅撤回;Codex 与 Cursor 的「像授权的」事件从不让它们变红。
像 Mac 应用(新的)
- 再打开一次就是打开托盘。 在访达或 Spotlight 里再打开 Pulse、或启动第二份副本:托盘打开并选中
最久的等待,不造窗口;第二份副本只发一个不带内容的分布式通知就退出。 - 登录项交给 macOS。 「登录时打开」是
SMAppService.mainApp,出现在系统设置 → 登录项;开关显示
macOS 的回答(待批准时给「打开登录项」)。旧版本自己写的 LaunchAgent 启动时卸掉,并改为向 macOS
注册,你的选择保留。设置卡多一个「登录时打开」复选框,默认不勾。 - 菜单栏的灯清楚了。 按按钮自己的尺寸绘制(不再先画 16 再缩到 15 发虚);灰灯是 template、跟着
菜单栏着色,红 / 绿 / 橙保留颜色;托盘开着时按钮保持按下;按下鼠标就打开;右键是「打开 Pulse ·
设置… · 退出 Pulse」。 - 隐藏的主菜单:⌘W 关设置、⌘C / ⌘A 作用于可选文字、⌘, 与 ⌘Q。
- 整行都能点。 托盘行整行是一个按钮;Agent 名挪进悬停提示与 VoiceOver。
- VoiceOver 只报新的等待,并把时间说全(「4 minutes」「4 分钟」),不念画出来的「4m」。
- 跟随区域。 详情页的时刻用区域自己的格式(「3:04 PM」/「15:04」);带数量的话分单复数;英文用
「Gray」;语言选择器照实写「简体中文」。 - 横幅按会话成线程。 标题「Agent · 项目」、副标题是会话的任务;每个会话一个通知中心线程;只有
macOS 说可以时才标为时间敏感。 - 逐个 Agent 安装 / 移除 hook。 设置 → Hooks 每行有自己的「安装」或「移除」,只动那一个 Agent。
- 终端自动化是设置 → 通用里的一个开关(默认关);行上不再有提议。
- 卸载 Pulse。 设置底部「卸载 Pulse…」先确认、逐条说出要移除的:装着 Pulse hook 的 Agent(经安装器
逐字节还原)、登录项、~/Library/Application Support/Pulse;确认后先移除全部 hook,一个都不剩才注销
登录项、删文件夹、退出,并在访达里显示 Pulse.app 由你拖进废纸篓。有 hook 移除失败就停下,别的都不删。
README 新增「卸载」一节。 - 右键菜单写着按键。 托盘底部那行静态的按键说明删了;行的右键菜单每一项旁边写着同一件事的键
(↩ 前往、→ 详情、⌘D 忽略、⌘M 静音)。
分发
- 首次打开的说明改了。 macOS 15 起按住 Control 点「打开」不再能放行未公证的 App:DMG 里的说明、
Release 说明与 README 先写「系统设置 → 隐私与安全性 →『仍要打开』」,终端里的
xattr -dr com.apple.quarantine /Applications/Pulse.app作为另一种方式。 - 每个 Release 附 DMG 的
.sha256文件,shasum -a 256 -c即可校验。 - 预发布闸门。 提交标题带
[release] [prerelease](scripts/release.sh X.Y.Z --commit --prerelease)
时,CI 构建同一个 DMG、同一份说明,但在 GitHub 上发成 pre-release、不设为 Latest;维护者真机验证后在
GitHub 上把它转为正式版。 - 更新检查只读一个地址:GitHub 的
/releases/latest。列表 feed、「预览版也看预发布」的分支都删了,
所以预发布对应用内检查不可见——这正是闸门要的。 - 分发通道两态:没有公证的构建都是
preview,公证并 staple 成功才是stable;CI 从来产不出的
signed一档删掉了。未公证的包永远不会自称 stable。
删掉的
- 协议词输入:
pulse-hook <agent> permission|question|turn|done|…与纯文本载荷不再被接受,只有每个
Agent 的适配器读它自己的厂商事件;事件日志的读取也不再认stop、idle_prompt、agent-turn-complete
这类别名。docs/samples/attention-bridge/与「手动上报」一节一并删除。 - 托盘底部两行:「N 个较早的会话未显示」(连同
staleHidden计数与它的单复数文案)和静态按键说明。 - 没人加载的资源:
pulse-app-icon-1024.png、pulse-idle/pulse-running/pulse-waiting(PNG、@2x、SVG)、
openai图标、所有 SVG 副本;Agent 图标只读 PNG(make_agent_icons --check保证每个 Agent 都有),
字母标的退路与AgentSpec.monogram删掉。App 图标AppIcon.icns移出资源包,只拷进Contents/Resources。 - 出厂 App 里的 QA 开关:
--appearance=/--language=挪进PulseQA;package_check.py在出厂
二进制里发现它们就失败。 - 两个截图脚本合成一个
scripts/qa_captures.sh(surfaces/status两种模式);CI 只把截图上传为
这次运行的产物,从不写进仓库或 Release。 script/build_and_run.sh(重复package.sh、带一段失效的 os_log 遥测)与指向它的.codex环境。- 文档:每个 Agent 的事实只在
docs/vendor-formats.md(与vendor-formats.json)里写一遍,其余文档
链接过去;docs/architecture.md缩成几段英文,数据流只在AGENTS.md;attention-bridge.md改为英文;
17.0.0 及以前的 CHANGELOG 段落移到docs/changelog-archive.md。
已知限制 / 注意
- 这一版没有在真机上验证过。 代码只在 CI(macos-26)上编译和测试:再打开、登录项、菜单栏的灯、
右键菜单、VoiceOver、横幅线程、卸载,都没有在一台真的 Mac 上和真的 Agent 一起跑过;维护者决定
不等真机冒烟,直接作为正式版发布。 - 仍是 ad-hoc 签名、未公证的
preview包。 Developer ID 还没到位:公证、Sparkle 自动更新、时间敏感
通知需要的 entitlement、跨更新稳定的隐私授权(每次更新 macOS 可能重新询问),都要等它。 - 繁体中文系统显示简体。 只有一张中文表,语言选择器照实写「简体中文」。
- 一个真叫
status的厂商工具会被当成状态行读:它不算一步、也不熄灭红灯。 - 从旧版本升级:旧日志里用别名写的行(只有外部脚本会这样写)不再被读;Pulse 自己写的行不受影响。
Gatekeeper
This build is ad-hoc / unnotarized (no Apple Developer ID in CI).
About stays preview — it is not Gatekeeper-ready and must not be
described as notarized stable. First open: drag Pulse to Applications and
open it once; when macOS blocks it, go to System Settings → Privacy &
Security, scroll to Security and click Open Anyway. Or, in Terminal:
xattr -dr com.apple.quarantine /Applications/Pulse.app.
(macOS 15 removed the Control-click → Open shortcut.)
Download verification
dc4bd2caaf2b70b4e45f3cf274c3ef4604b6cb14c047971932a07fa7599f0bc6 pulse-27.0.0-macos-PulseBar.dmg
Pulse 26.0.0
26.0.0 — Step(一步)
这一版的目标是简化、聚焦:一行说清一个会话在做什么——上一步是什么、这一回合跑了多久——而且只凭
Agent 自己的 hook 事件。 Pulse 不再读任何厂商文件(没有 transcript),Codex 只装 hooks.json;
同时合并了行的几层中间值、一处计数,删掉详情页里给开发者看的块和一个门禁。源码从 15.2k 行降到 14.8k 行。
这是一个大版本:事件日志第 9 列不再是 transcript 路径(写空、永不读),「读 transcript 拿标题与最后的
话」这项能力删除了;25.0 写下的日志照常能读,但第 9 列被忽略。
新的
- 上一步回来了。 会话簿按会话记下最后 5 个工具步骤(工具、目标、时间,来自 v5
tool行)和本回合
开始的时间,启动时从日志重放重建,不另存。运行中的行第二行安静地写「Bash · swift test · 12 分钟前」
——说的是已经发生的一步,从不写「正在」;时间位是本回合时长「14 分」。停滞的「为什么」点名上一步
(「已经 23 分钟 没有新动静——上一步:Bash · swift test」);详情页列最近 5 步和「本回合」。
Copilot 的toolArgs读出命令或路径,Pi 扩展转发工具名与一个参数。 - 标题来自提示事件本身:提交提示的那条 hook 事件带着原文(剥掉厂商信封、脱敏、至多 200 字写进日志),
第一条说了事的提示(至多 120 字)就是标题;回合以错误结束时,hook 报的错误写进详情页。 - 为什么还是不显示 token。 步骤、标题、最后的话都来自 hook 事件;token、上下文、费用、模型与套餐
不是「需要你吗」这个问题的答案,而且要拿到就得读各家的会话文件或用量接口——那是另一个产品。
catalog_check仍然拒绝任何读usage/token_count/rate_limits/cost的代码。 - 「复制报告」多一节「sessions」:每个列出的会话一行——状态、事实来自 hook 还是只有进程、前往是否精确、
进程是否在盯、最近事件多久前;不含路径、提示、会话 id 或项目。
删掉的
- 读 transcript:标题与最后的话不再从厂商的会话文件里读,只来自事件;日志第 9 列写空、不读。
- Codex 的
notify与config.toml:Codex 只装~/.codex/hooks.json,config.toml一个字节都不动。 - 详情页的「来源」一行与折叠的「Pulse 如何读取这个会话」:这些信息搬进了「复制报告」;对应文案
(中英)一并删除。 appearance_check门禁,以及catalog_check里的 README 矩阵核对与「按 Agent 的表又长出来」的
正则——它们守的是文字,不是事实。名册、只经 libproc 的进程规则、隐私与不读 token、拦截类事件、
hook 出处这些检查照旧。- 中间层与死代码:
Explain并进TrayRowModel(行的每一句话是它上面的纯函数,详情页说同样的话;
灯的一句规则在TrayState);Census、sectionTotals与托盘头部各自数一遍,合成投影里只数一次的
TrayState.Counts;随 transcript 与 Codex notify 一起走的代码。
修复
- 安装失败的 Agent 不会再在设置卡里被当作「连接」重新提供(同样会失败),而是单独一条提示说明原因、给出「打开设置」;
- 设置卡只列这台 Mac 上装了的 Agent,不再因为一个进程在跑就列出;
- 找不到属于 Agent 的祖先进程时,
pid写空,不再误记成 hook 的直接父进程(通常是随 hook 退出的sh -c); - 事件日志读失败会重试,从 5 秒起翻倍、最长 1 分钟,只排一个定时器;读失败不清空已应用的状态;
- 行只在
0x0A字节处断开:字段里的 U+2028、NEL 或单独的\r不再把一条记录切成两半;写入时
NEL、U+2028、U+2029 与其他换行一样被压平成空格; - 压缩日志时,正在追加的那一行一定保留——追加只在这一行真的进了文件时才算成功;
- 没有会话 id 的忽略(
done)按 Agent + 目录认领,不再清掉同一 Agent 所有无会话的条目; docs/samples里的示例桥接脚本改为调用pulse-hook,不再自己拼日志行;- 被压缩重写的日志按位置认出已应用的行,同一文本写了两次就应用两次,不再只按文本去重;
- 语言选项里的「跟随系统」在中文界面下不再写成英文 System;
- 改一项设置只执行它需要的副作用(例如改语言只重注册横幅按钮并重新投影,不再重装快捷键、重设登录项、重启更新检查)。
已知限制 / 注意
- 这一版没有在真机上验证过。 代码只在 CI(macos-26)上编译和测试;上一步、本回合时长、设置卡、
横幅撤回与补发、落点,都没有在一台真的 Mac 上和真的 Agent 一起跑过。 - Pi 与 OpenCode 没有提示事件,所以没有标题,主行退回最后的话或项目。
- Cursor 与 OpenCode 的 hook 不报工具名,所以没有上一步,它们的行始终一行、不会停滞变橙。
- 事件日志现在存提示原文(脱敏、至多 200 字),文件仍是 0600、只在本机。
- 从 25.0 升级:25.0 写进
~/.codex/config.toml的notify一行,26.0 不再管理——卸载 hook 也不会
还原它。需要的话,升级前在 25.0 里先卸载 Codex 的 hook,或手动删掉那一行。 - 没有 Apple Developer 账号时,发布的包是
preview、ad-hoc 签名、未公证;第一次打开要按住 Control
点按 Pulse.app →「打开」。
Gatekeeper
This build is ad-hoc / unnotarized (no Apple Developer ID in CI).
About stays preview — it is not Gatekeeper-ready and must not be
described as notarized stable. First open: Control-click → Open, or
xattr -dr com.apple.quarantine /Applications/Pulse.app.
Download verification
dadcb9dcda184f9745aff64db4532768f9f8326e4751bf8f9f8302e25e78e7d7 zig-out/package/pulse-26.0.0-macos-PulseBar.dmg
Pulse 25.0.0
25.0.0 — Reach(抵达)
这一版只做一件事:每一个真正的「需要你」都到达你一次,回答了就消失,一个键就回到提示前。
为此先做减法(Pulse 自己的记录、诊断窗口、过滤框都删了),再把 hook 事件收成一个追加式事件日志并修掉
审计出的 16 个问题,最后把「抵达」这条路从第一次打开到按下 ↩ 逐段补齐。源码从 17.5k 行降到 15.2k 行。
不兼容旧版本:旧的 attention.tsv、活动目录与 session-log.json 在启动时删除,不读、不迁移。
减法
- Pulse 不再存自己的记录。
SessionLog(session-log.json)、会话时间线、活动日志、通知审计都删了;
横幅记账改为只在内存里的WaitLedger,重启从零开始,启动时已经在等的等待是基线、不补发。 - 诊断窗口删了:设置 → Hooks 就是诊断(每个在这台 Mac 上的 Agent 一行,不在的合成一行,
「复制报告」)。托盘头部的「新鲜度」、过滤框、设置里的「终端」一节也删了。 - 一个投影:
SessionProjection与SnapshotBuilder合成一个纯值TrayState.project——
行、灯、标题、计数、新等待的边沿一次算出。 - QA 代码不进产品:夹具、截图与预览窗口搬进独立的
PulseQA可执行目标;发布的 app 只有PulseBar。 - AGENTS.md 与代码注释改为只说现在的事实;版本号只写在 CHANGELOG。
一个事件日志(Attention Protocol v5)
- 所有 hook 事件(包括每次工具运行)按顺序追加到一个文件
events.tsv:十一列 v5 行(多了tool),
只追加、0600、超过 1 MiB 按会话压缩(开着的阻塞与回答它的行永不丢)。 - 启动时先整份重放再画第一次托盘;之后按字节偏移读新行,日志被压缩重写(新一代)时整份再读、
只应用没应用过的行;读失败或读到空不重置任何状态。 - 审计修掉的 16 个问题:
- 失败的工具(Claude
PostToolUseFailure)也算回答了它的权限请求; - 重启后已回答的等待不再变红(回答它的那次工具运行也在日志里、按顺序重放);
- 答案前后的并行工具不再把答案盖掉(旧的活动文件每会话只留最后一次);
- 进程号被别的程序复用即算会话结束;
- 一个 Cursor / OpenCode 进程一整天跑着很多会话:活着的进程只留住工作中与需要你的会话,空闲、
过期的照常离开列表; - 中途被打断、永远不报 Stop 的回合不再无限橙:两小时无消息转为「最近」;
- Claude 的 AskUserQuestion 显示问题本身、ExitPlanMode 显示计划第一行,不再是工具名;
- Pi 的提示没有标题时不再显示字面的
ui_prompt; - pid ≤ 1 永不写进事件;
- Pulse 的安装标记只认整段
pulse-hook命令(impulse-hook.sh不是); - 带注释(JSONC)的设置文件拒绝改写并说明原因;
- CRLF 换行原样保留;
- BOM 原样保留;
- 空的用户 hook 数组(
[])逐字保留; - Codex 的
notify按整条 TOML 语句识别与移除(跨行也一样); - Pi 的排除词只看程序本身,
pi ./pipeline.ts仍是 Pi。
- 失败的工具(Claude
- 另外:只提交了 prompt、还没跑过工具的会话不算停滞(停滞要有工具事件为证)。
抵达
- 横幅随等待撤回。 等待被回答、被忽略或会话结束时,它的横幅从通知中心撤走(已送达与排队中的都撤);
汇总横幅在它点名的最后一个等待关上时撤走;送达途中就被回答的,一送达就撤。点一条等待已经不在的横幅
只打开托盘,不再跳到一个已经没有的提示。 - 在眼前的等待补发一次。 提示窗口当时就在最前的阻塞先只亮灯;30 秒后它还开着、而它的 App 已不在
最前,补发一次横幅(从那时起每一拍沿会话进程的父链看一次前台 App,App 还在最前就继续等)。启动时重放出的等待永不补发。 - 第一次打开有一张设置卡。 这台 Mac 上有没连接的 Agent 时,托盘唯一的提示是「在这台 Mac 上找到
Claude、Codex——连接」,排在通知授权之前,空托盘里也有。一次点击:装上 hook、请求通知授权,然后列出
剩下的事——「Codex:在 Codex 里运行 /hooks 并信任 Pulse」「已在运行的会话会在它们的下一步之后出现」,
直到「知道了」。空态改为照实的一句「已连接的 Agent 开始工作时,会话会出现在这里」。 - 一个手势。 点菜单栏与全局快捷键都打开托盘并选中最久的等待(没有就第一行),一个 ↩ 就到提示。
快捷键只提供编辑器不占用的 ⌃⌥Space、⌥⌘P,仍默认关闭;存下的 ⌘⇧P、⌘⇧U、⌃⌥P 读作关闭,需要重新选(⌘⌥P 原样保留,现在写作 ⌥⌘P)。 - 一次性的自动化提议。 第一次因终端自动化关着而只落到 App、而打开它本可以确切落到 iTerm 会话或
Terminal 标签时,行上问「下次直接跳到那个标签页——macOS 会询问你一次」[允许] [暂不]。回答过就不再问
(记在settings.json的automationOfferAnswered)。 - 文案一遍:一个概念一个词(设置、需要你、运行中、轮到你、最近、仅进程、停滞),「」引号与不带空格的
「——」;「为什么」说人话、不提 hook——「Claude 请求权限 · 4 分钟前」「在 Pulse 之前启动——下一步之后
显示详情」;汇总横幅「N 个 Agent 需要你」;preview 包写「ad-hoc 签名 · 未公证」,不再写「未签名」;
版本不一致的提示不再让用户去跑打包脚本。surface_check.py拒绝任何含 hook 的explain*文案。 - 「复制报告」多写两件事:全局快捷键与它是否注册成功、自动化提议是否已回答。
已知的不确定
- 没有在真机上验证。 这一版的横幅撤回、30 秒补发、设置卡与自动化提议都只有单元测试与截图夹具,
没有在一台真的 Mac 上跑过 Notification Center、TCC 自动化询问与各家终端。 - Cursor 的 hook 形状最不确定:它对照的是文档而不是源码,而那份文档在构建环境里打不开,事件名与字段
是按第三方的类型绑定核对的;漂移时它最可能先坏。 - 20 秒宽限:阻塞后 20 秒内结束的回合先暂存;拒绝后灯会多红到宽限期满,才落到「轮到你」。
- 30 秒补发靠时钟一拍:30 秒内的等待让时钟每 5 秒走一拍(省电模式 10 秒),补发最多晚几秒;
如果 App 一直在最前而你早已离开座位,它就一直不补发——Pulse 只知道前台是谁,不知道你在不在看。 - 启动前就在跑的会话在它的下一个事件之前只显示为「仅进程」,没有标题、问题与时间。
- 自己写的桥接脚本必须往
events.tsv一次追加整行 v5(十一列);v4 行与半行都不读。
Gatekeeper
This build is ad-hoc / unnotarized (no Apple Developer ID in CI).
About stays preview — it is not Gatekeeper-ready and must not be
described as notarized stable. First open: Control-click → Open, or
xattr -dr com.apple.quarantine /Applications/Pulse.app.
Download verification
808c960aa0f943f30d32090006e6b442a22fac72b022e02fa12719163be5a8c4 zig-out/package/pulse-25.0.0-macos-PulseBar.dmg
Pulse 24.0.0
24.0.0 — Exact(准确)
这一版做了取舍:只支持 7 个主流 Agent,而且只听它们自己说的话。Pulse 不再翻各家的会话文件去猜状态,
每一盏灯都来自 Agent 官方 hook 推送的事件。源码从 25.5k 行降到 17.5k 行,测试从 12.7k 行降到 7.1k 行。
不兼容旧版本。
7 个 Agent
- 能变红(需要你)的 5 个:Claude Code、Gemini CLI、Copilot CLI、OpenCode、Pi —— 它们的官方 hook
会在请求权限或向你提问时通知 Pulse。 - 只显示「运行中 / 轮到你」的 2 个:Codex(它的权限事件在自己的自动审核之前触发,会假红)和
Cursor(没有这个事件)。界面上直接写「不会告诉我们它在等你」,不再假装。 - 其余 26 个 Agent 移除:它们要么没有官方事件,要么只能靠解析文件猜。
事件驱动
- hook 是唯一的状态来源。 每个 Agent 装的都是厂商文档里的事件,只装不会影响 Agent 决定的那些
(不装 PreToolUse 一类会返回决定的 hook;Claude 的 hook 全部async)。OpenCode 和 Pi 各装一个
几十行的插件 / 扩展。安装可完全撤销:Pulse 记下原文件,卸载时逐字节还原;只改配置里的hooks
一段,其余内容和格式一字不动。一个 Agent 的配置坏了,不影响其他 Agent 安装。 - 整个文件扫描层删除(约 9k 行):目录遍历、20 多种格式解析、SQLite 读取、新鲜度窗口、
ps/lsof轮询、「读取受保护的应用数据」开关都没了。 - 一个会话状态机。 事件按顺序归约成每个会话的状态:空闲、运行中、需要你、轮到你、已结束。
回答了请求(对应工具的下一个事件、新的提问、忽略)红灯就灭;别的并行工具的活动不会把它误灭。 - 进程只用来判断「还在不在」。 用 libproc 找没有事件的 Agent 进程(Pulse 启动前就在跑的会话,
先显示「仅进程」),用 kqueue 监听进程退出来结束会话。没事时不轮询,扫描间隔从 30 秒退到 5 分钟。 - 标题和最后的消息只在需要时读:这一轮结束、等待或打开详情时,读 hook 告诉我们的那一个会话文件。
一键到提示符
- hook 触发时记下终端位置(tmux pane、iTerm 会话、tty、终端程序),↩ 直接落到那个 pane 或标签页。
- 能精确落点时按钮写「前往终端」,只能打开应用时写「打开应用」,并在行上说明。VS Code / Cursor 里
会打开会话所在的文件夹,但不能选中具体终端 —— 界面会照实说。
修复(发布前审计出的 19 项,择要)
- Gemini、Copilot 回答权限请求后红灯不灭 —— 现在装了它们的工具完成事件。
- 没有工具级事件的 Agent(如 Cursor)长时间工作不再被误判为停滞。
- 同一会话里并行的其他工具不会让真实的等待消失。
- Claude 的
idle_prompt不会让已看过的「轮到你」重新出现;第二个权限事件不会覆盖更具体的请求内容。 - 进程匹配只看可执行文件本身(
pinentry-mac不再被当成 Pi)。 - OpenCode 的子 Agent 并入父会话,不再单独成行。
- 安装和卸载不会并发;安装记录文件从一开始就是私有的;错误信息翻译成当前语言。
诚实说明
- 开发环境没有 Mac 和编译器:代码只在 CI(macos-26)上编译和测试过。各 Agent 的 hook 是否按文档
触发、落点是否精确,都还没在真机上验证过。 - Cursor 的 hook 格式来自第三方类型定义(官方文档站被代理拦截),是 7 个里最不确定的。
- Pulse 启动前已经在跑的会话,要等它的下一个事件才显示任务名和状态。
- 一个请求如果在 20 秒内紧接着这一轮结束,红灯会在宽限期结束后熄灭。
Gatekeeper
This build is ad-hoc / unnotarized (no Apple Developer ID in CI).
About stays preview — it is not Gatekeeper-ready and must not be
described as notarized stable. First open: Control-click → Open, or
xattr -dr com.apple.quarantine /Applications/Pulse.app.
Download verification
acc02ea6cef722aa848518e1a60a225e2f7fc53dd29f69165542484d28ca332b zig-out/package/pulse-24.0.0-macos-PulseBar.dmg
Pulse 23.0.0
23.0.0 — Essence(本质)
这一版继续做减法,并且把剩下的部分按「一盏灯」重新搭了一遍。不兼容任何旧版本:旧的设置、历史文件和
协议写法都不迁移,直接丢弃。源码从约 34.7k 行降到 25.5k 行,测试从 18k 行降到 12.7k 行。
删掉的
- Respond 删除。 Pulse 不再替你回答任何权限请求,hook 也不再等待裁决:它写一行事件就退出。
回答永远在 Agent 自己的提示里给出。 - Python hooks 整套删除,只保留原生
pulse-hook。hooks 安装器仍只装 Claude 和 Codex。 - 更新只检查、不安装。 有新版本时打开 Release 页;下载、校验、原地安装、回滚、重复安装检测、
崩溃恢复提示全部删除 —— 没有公证版本,这些路径从来没有被用户走到过。 - 「稍后」删除。 只剩两个动词:忽略这条等待,静音这个 Agent。
- 空闲通知、实时更新开关、按 Agent 的应用数据授权删除(合成一个开关);Attention 桥工具包移出
app,只在文档里给命令;多机残留(PULSE_HOST、主机列、v1 协议)删除,attention 行必须是 8 列。 - 离开期间的变化提示、等待历史、会话摘要(
SessionDigest) 删除。 - 格式未核实的 11 个 Agent 不再推断「需要你」(Cursor、Cursor Agent、Amp、Amazon Q、Cascade、
Windsurf、Augment、Zed、Kiro、Droid、Command Code):它们只显示在跑。等格式核实后再逐个打开。
重新搭的
- 一个事件簿。
session-log.json取代原来的 ledger、hook 历史、时间线和忽略列表四份文件;
时间线、通知去向、活动记录都是它的视图。安静的扫描不写盘;重启后正确闭合会话,不把停机时间算进去。 - 状态分三块。
ScanEngine负责扫描,WaitNotifier负责通知,界面只观察 17 个属性的
StatusStore。设置是一个settings.json,9 项。 - 会话身份稳定。 一行的 key 从出现到消失不再变化(
RowIdentity);只看到进程的行在会话出现后
直接消失,不再「升级」。所有 remap 代码删除。 - 一个解释。
Explain给每一行一句「在做什么」和一句「为什么是这个状态」,托盘行、详情页、
菜单栏提示都说同一句话。原来的RowNarrator、行卡片、Why 卡、诊断卡等 8 个模块删除。
界面与交互
- 灯按「需要什么」分形状:实心 = 需要你,圆环 = 在跑,空心灰 = 轮到你 / 最近,虚线 = 只看到进程。
橙色只留给停滞和出错;只看到进程不再变橙。菜单栏和托盘用同一套图形。 - 菜单栏只在需要你时出字,例如「2 · 4 分钟」;提示框只有一句:灯为什么是这个颜色。
- 头部一行说清「为什么」和「多新」:「2 个需要你 · 3 个运行中 · 3 秒前更新」;扫描停了会变橙说出来。
刷新按钮删除(⌘R)。同一时间最多一条提示,每条一个动作。 - 一行只有一行:灯、Agent、项目、正在做的事、时长;只有等待(问题)和停滞/出错(原因)才有第二行。
去掉整行底色、「新」蓝点和重复的时间。托盘打开时行顺序冻结,不会在鼠标下移动。 - 键盘:打字就是过滤(有可见的输入框,⌫ 只删字);↑↓ 选择,↩ 前往,→ 详情,⌘D 忽略,⌘M 静音,
Esc 逐层退出且在任何状态下都有效。全局热键永远是开关托盘。点横幅只聚焦终端。 - 详情页每件事只说一次:问题和动作、原因、带刻度的 60 分钟时间条、最后的消息、计划、错误、
通知去向、几项事实;读取方式默认折叠。 - 「健康」改为「诊断」窗口:先列问题,再每个 Agent 一行,活动记录单独一页并带日期,一键复制报告。
- 设置一页 7 组;文案一个概念一个词(需要你 / 运行中 / 轮到你 / 最近 / 仅进程 / 停滞)。
修复
- 在终端里批准了权限请求后,红灯不再一直亮到这一轮结束。
- 同一会话的第二个请求会重新通知;忽略之后的新请求不再被当成已忽略。
- 打字过滤不会再误触忽略或静音。
- 没有会话 id 的 hook 等待能正确忽略,也不会清掉同一 Agent 其他会话的等待。
- 已经解决的等待不再弹横幅,积压的通知队列不再无限增长;点旧横幅不会记到新的等待上。
- 等待期间每轮扫描不再重绘界面;只看到进程和「轮到你」的会话不再拖住高频扫描。
- hook 不会因为 stdin 没关而卡住;空事件类型不再变成红灯;一个坏字节不再让所有等待消失。
- hooks 自检不再和扫描抢同一个文件路径。
- 已完成但进程还在的会话显示灰色,不再亮绿。
- 打开托盘时头部不再闪橙;提示出现或消失时面板会重新贴合;超过当天的时间带日期。
工程
- gate 合并:四个目录检查合成一个
catalog_check.py;删除只守护已删代码的检查。 - 测试按组件重组:47 个按版本命名的文件合成 13 个(核心、采集、转录、厂商格式、attention、构建、
解释、事件簿、通知、托盘、设置、诊断、引擎)。
诚实说明
- 开发环境没有 Mac 和 Swift 编译器:所有代码只在 CI(macos-26)上编译和测试过,新界面没有在真机上看过。
- 「批准后红灯熄灭」依赖同一会话随后出现的活动事件;如果 Agent 并行调用工具,灯可能提前熄灭。
- attention 协议有一处行为变化:没有会话 id 的
done只清掉没有会话 id 的等待。依赖旧行为的第三方
桥接需要带上会话 id。 - 格式未核实的 11 个 Agent 在这一版不会变红,这是有意的取舍。
Gatekeeper
This build is ad-hoc / unnotarized (no Apple Developer ID in CI).
About stays preview — it is not Gatekeeper-ready and must not be
described as notarized stable. First open: Control-click → Open, or
xattr -dr com.apple.quarantine /Applications/Pulse.app.
Download verification
67c373bd53193c8ade7e483595c1e7b5e96dd00b456a03bc5eed37b3ae8a1358 zig-out/package/pulse-23.0.0-macos-PulseBar.dmg
Pulse 22.0.0
22.0.0 — Lamp(一盏灯)
这一版是减法。Pulse 回到它最初的样子:菜单栏里一盏灯,告诉你哪个 Agent 在跑、哪个在等你。
13.0 以来加上的编排能力(Mission、候选方案、检查、派发、工作树、终端操作)、跨机器的 Respond 和
Workbench 窗口全部删除,不保留开关。留下的部分重做成一行一个会话、键盘可达,并且每一个颜色、每一条
通知都能说清来历。
删掉的
- 编排整体删除:
PulseManaged目标(Pulse 自己启动的会话)、Mission 与候选方案对比、
EvidenceBook检查与证明卡、派发与 worktree、终端输入、工作区冲突提示。Pulse 看着编排器,
自己不再是编排器 —— 这些能力和「一盏灯」是两个产品,放在一起让两边都平庸。 - 跨机器 Respond 与 fleet 广播删除。Respond 只在本机:批准仍然只出现在完整请求旁边
(canOfferAllow),横幅仍然只有「拒绝」;不再有远端密钥、远端裁决目录和主机列。 - Workbench 窗口删除。它的检查器、摘要和展开卡片合并成托盘里的一个详情页。
- 设置里删掉了分组、提示音、静默时段、按 Agent 静音列表、停滞阈值、推迟时长和历史保留 ——
静默和声音交给 macOS 的专注模式与通知设置;静音改在行菜单里做。 - 迁移:第一次启动 22.0 时一次性删除
evidence/、managed/、missions/、fleet.d/
以及respond.d/下的远端请求、裁决和密钥(标记文件.cleanup-22.0)。本机 Respond 的
请求文件和 attention 记录不受影响。 pulse_hook.py只在这台 Mac 空闲超过离开阈值时才为 Respond 暂停请求;有人在用就直接放行给
Agent 自己的提示 —— 以前远端能答时它会等。
一行一个会话
- 托盘每行只有一行:灯的形状、Agent、项目、任务、时间。等待行多一行问题;停滞 / 失败多一行
橙色原因。其余动作都在右键菜单和详情页里。 - 灯有形状,不只靠颜色:实心(在跑、等你)、半实心(停滞、出错)、虚线(只看到进程,
没有会话数据)、空心(轮到你、最近、空闲)。色弱和灰度下也分得开。 - 详情页(→ 或行菜单「详情」):任务、为什么是这个状态、最近一小时的时间条、完整的
Respond 请求(批准就在旁边)、Agent 最后说的话、计划、事实、这条通知发生了什么、读取诊断。
← 或 Esc 返回。 - 键盘优先:打开托盘直接打字就是过滤;↑↓ 选择,↩ 聚焦终端,→ 详情,⌫ 拒绝或忽略,Esc 先清
过滤再关面板。底部一行写着这些键。 - 头部一行彩色计数,「⋯」里是健康、设置、退出;同一时间最多一条提示(维护 / 扫描不完整 /
已暂停)。 - 设置是一页:通用、快捷键、通知、hooks、控制、数据访问、更新、关于;Attention 桥的开发者
工具在「高级」折叠区里。从别处跳进设置会滚到对应的那一节。
看得见(可观测性)
- 每个会话有时间线:Pulse 每次扫描记下状态变化(在跑 / 数据少 / 停滞 / 等你 / 轮到你 /
最近)和依据(hook、会话文件里的待答、claude agents、会话文件、进程),保存在
session-timeline.json(最多 128 个会话、每个 48 段、24 小时)。详情页把最近一小时画成一条
时间条,并写出每种状态各几分钟。 - 灯为什么是这个颜色:鼠标停在菜单栏图标上,提示里写出决定颜色的规则、最多三个驱动它的会话,
以及没算进去的(已推迟、较早隐藏的)。 - 每条通知有去向:发了、合并进汇总、被系统拒收、没发以及为什么(在最前面、已静音、已确认、
等待中、通知关了、没授权、刚启动)、什么时候点了、确认了、推迟了、解决了。写在详情页里。 - 活动记录(健康 → 活动):所有会话的状态变化和通知去向,按时间倒序、可按 Agent 过滤,
不用再翻 debug.log。 - debug.log 里每轮扫描的「apply」行只在内容变化时写,安静时不再刷屏。
修复
- 「N 个较早的会话未显示」只算最近 24 小时里停下的会话,不再把一个月前的记录都算进去。
- 等待通知的标题规则统一,第二轮扫描不再重写 ledger。
- 后台更新检查失败不再把「已是最新 / 有新版本」改成「检查失败」,也不再闪「正在检查」;只有手动检查
才显示进行中。 - 下载更新失败按原因说:网络、HTTP 状态、校验失败、需要公证版本、没有可校验的安装包、系统不支持,
不再一律说「校验失败」。 - 卸载 hooks 后,「Claude 在跑但没装 hooks」的提示不再每次都回来;重新安装会重新打开它。
- 只写了
~/.codex/hooks.json的 Codex 也算已安装 hooks。 - 本机 Respond 读取请求时先读最新的,过期文件不再占用 32 个的读取额度 —— 以前一堆过期请求能把
真正在等的那个挤出去。 - 托盘面板动画缩放后阴影和圆角会重新贴合;点菜单栏图标能正常开关面板,不会被关闭又立刻打开;
菜单栏图标按菜单栏自己的明暗绘制。 - hooks 配置文件写出时不再把
/转义成\/。 - 诊断里的相对时间和「会话」标签跟随应用语言;健康页的「上次读取」用真实的扫描时间。
诚实说明
- 这台开发环境没有 Swift 编译器,也没有 Mac:代码只在 CI(macos-26)上编译和测试过,托盘的新
外观(一行行、灯的形状、详情页、时间条)没有在真机上看过。 - 时间线从 22.0 开始记录,升级前的历史没有。
- Respond 的 P0-0 真机确认(决策格式被接受)仍未完成;格式不对时会被忽略并回落到 Agent 自己的提示,
不会误批。
Gatekeeper
This build is ad-hoc / unnotarized (no Apple Developer ID in CI).
About stays preview — it is not Gatekeeper-ready and must not be
described as notarized stable. First open: Control-click → Open, or
xattr -dr com.apple.quarantine /Applications/Pulse.app.
Download verification
6e150ae843ad539ca2c160c2fa69e5472782a4ef5e24e2bb10e77f62caf009ed zig-out/package/pulse-22.0.0-macos-PulseBar.dmg
Pulse 21.0.0
21.0.0 — Clarity(清晰)
这一版不加新能力,只做六件事:修 bug、界面现代和一致、细节、看得见、好用、简洁。依据是三路
源码审计(bug / 界面 / 可观测与易用),发现的问题逐条修掉,每一条都有测试或截图夹具。
修复(审计出的 21 项)
- 红灯不再自己回来或自己消失。 忽略一条
claude agents报告的等待后,下一轮扫描又把它点亮;
「清除等待」对它不起作用 —— 都修了。Claude 在权限请求后立刻写出 Stop 的乱序情况,宽限期现在用
两条事件各自的时间比较,不再用 Pulse 读文件的时间,所以请求没答时红灯不会在 20 秒后熄灭。
claude agents超时或失败一次,不再清空全部等待(也不再在恢复时重复弹通知)。 - 行上的内容对了。 Claude 子代理的记录不再并进主会话、抢走它的任务和最后一句话;Pi 只读当前
分支(/tree回退后不再显示已放弃分支的话);同一会话多个文件合并时,模型、工具、token、计划
都取最新的那个文件;Pi 不再把事件数显示成「完成 0/523」。 - 「轮到你」清得掉了。 只有进程、还没读到会话文件的行接手了「轮到你」后,聚焦也清不掉,要等
30 分钟 —— 现在行带上会话 id,「已看过」和「忽略」都写在 hook 自己的会话名下。 - 文件里的陈旧等待会熄灭。 Cline 的未答提问、Goose 的 elicitation、Kimi 的审批请求、
OpenHands 的待确认:Agent 进程已经不在、记录又超过 30 分钟时,不再一直亮红。 - 聚焦终端不再替 iTerm 用户打开 Terminal.app,只对正在运行的终端发脚本,并有超时,不会把
菜单栏卡死在自动化授权弹窗上。 - 更新检查会重跑。 长期不关机的 Mac 以前永远看不到新版本;失败后一小时重试,而不是等一天。
更新失败的原因用你的语言说。原地安装后的重启不再卡在子进程上(该路径仅用于已公证版本)。 - 汇总通知的「稍后」推迟里面的每一个会话;热键优先跳到正在亮灯的等待,而不是已推迟的;按会话 id
聚焦时只在同一个 Agent 里找;hook 事件在节流窗口里的最后一次不再丢;ledger 只在真的变化时写盘;
attention 文件追加遇到坏字节不再清空整份文件;Goose 与 OpenHands 的读取不再吃光扫描预算。
一套视觉
PulseTheme是唯一的视觉来源:4 点网格的间距、三档圆角、几档填充、语义字号(跟随系统),
每个状态一种颜色 —— 红(需要你)、绿(在跑)、橙(停滞 / 失败 / 只有进程)、灰,全部用系统动态色,
暗色模式和「增强对比度」都会跟着变。审计时产品里有 7 种圆角、约 12 个字号、3 种红和 3 种绿。
surface_check.py之外,视图里散落的写死数值已经收回令牌。- 一行只有一处红。 等待行原来有左侧色条、红点、红色标签、红色问题文字、红框卡片五处红和六个
按钮;现在是整行一层淡红底 + 红点与标签,问题用正文色,下面至多两个按钮(回答或聚焦、忽略),
其余动作都在「⋯」和 VoiceOver 动作里,只出现一次。 - 不再抖。 展开箭头和「⋯」参与布局,不再盖住时间;悬停不再改变行高;面板只在高度真的变化时
调整、且带过渡;菜单栏标题用等宽数字;新等待只让灯暗一下(规格一直写的是「闪一次」,实际闪了
三次),开了「减少动态效果」就不闪。 - 头部是按状态计数的胶囊,分组标题不再重复同一个数;刷新按钮自己转圈,不再把计数换成「刷新中」。
- macOS 26 上托盘用 Liquid Glass,边缘有一条细线;更早的系统保持原来的菜单材质。
看得见
- 每个非绿色的行都说为什么:停滞「已经 23 分钟没有新动静,超过你设的 20 分钟」、失败的上一次
运行、只看到进程没有会话文件 —— 折叠状态下就显示,不用点开。 - 头部下面一行写着多久前更新、多久读一次;关掉实时更新时明确说关了,不再看起来像是最新的。
- 看不到的会话说出来:「3 个较早的会话未显示(Claude、Codex)」,原来只写进 debug.log。
- 「无法刷新」有自己的界面和重试按钮,不再同时说「无法刷新」和「未检测到 Agent」。
- 通知被系统拒收、导出报告失败、写 pulse-hook 失败,都会在界面上留下痕迹。
好用、简洁
- 第一次打开是一张清单,按这台 Mac 的真实状态打勾:通知、Claude/Codex hooks、受保护的应用
数据,没做的旁边就是按钮。不再把人带进 Attention 桥的开发者工具。 - Claude 或 Codex 在跑但没装 hooks 时,托盘有一行提示,一键安装(仍只装 Claude/Codex)。
- 设置分成五个面板:通用 / 提醒 / 连接 / 权限 / 关于。Attention 桥的工具收进「连接」里的折叠区;
「快捷键」不再装着五个不相干的授权开关。全局快捷键从「开关 + 选择器」合成一个带「关闭」的选择
(旧设置自动迁移,未开启的仍是关闭)。 - 「健康检查」一个窗口:自检在最上面,每条下一步旁边就是按钮;下面是每个 Agent 能读到什么,
格式漂移提到外面用橙色标出;报告与诊断收在一个菜单里;还写着上次读取的时间、频率和耗时。 - Details 窗口并入 Workbench:同一行原来有托盘卡片、Details、Workbench 三个检查器和两份
Respond 实现;现在「在 Workbench 打开」直接选中那一行,「为什么」和读取诊断都在那里。
Allow 仍只出现在显示完整请求的地方。 - 用词统一:中文界面不再混着
hooks/pending/Waiting;「判决」→「你的决定」,
「受管」→「由 Pulse 启动」,Mission / 候选 →「任务对比 / 方案」,验收 / 证据统一叫「检查」。
发布流程的一个修正
version_check.py --fix 会把 CHANGELOG 最新的标题直接改成新版本号。19.0.0 和 20.0.0 因此都把
18.0.0 的说明当成了自己的发布说明,这两节自己的内容也没有留在 CHANGELOG 里。现在 --fix 不再碰 CHANGELOG;下面的
18.0.0、19.0.0、20.0.0 三节已按原内容恢复。GitHub 上 v19.0.0 与 v20.0.0 两个 Release 的正文仍是
18.0 的文字,需要在网页上手动改。
为什么是大版本
删掉了 Details 窗口;设置里的全局快捷键从两个值合成一个(持久设置迁移);托盘的交互(可见动作、
提示、空状态)整体改变。Attention 协议与会话状态格式不变。
这一版不说的话
- 没有本地编译环境,所有改动靠 CI 的构建、测试和截图夹具验证;截图我看不到,Liquid Glass 与
新的托盘在真机上的观感需要你看一眼。 - 「子代理记录并入主会话」是按代码推断的,还没有用真实的子代理文件确认。
Gatekeeper
This build is ad-hoc / unnotarized (no Apple Developer ID in CI).
About stays preview — it is not Gatekeeper-ready and must not be
described as notarized stable. First open: Control-click → Open, or
xattr -dr com.apple.quarantine /Applications/Pulse.app.
Download verification
e74317afd7f9b7340f2308e38939c71c5239071cb814d02c13f8c7d8a7ccbd06 zig-out/package/pulse-21.0.0-macos-PulseBar.dmg