别人家的 AI 桌面端是这样工作的:ChatGPT 按 ⌥Space 弹出一条浮动输入框,问完 Esc 走人;Claude 直接双击 Option 就能说话,主窗口一辈子不用打开。WorkBuddy 是另一套动作——切到它、找到输入框、点新建,三个动作做完,刚才那个念头已经凉了。
数据取自本机 WorkBuddy 5.9.3 客户端:快捷键定义从 app.asar 内 main / renderer 产物解析,内存与进程数由 ps 实测,采集时间 2026-11-03 23:00(UTC-8)。
一句话结论
我用一个 29.5 MB 的后台进程,给 WorkBuddy 补上了它缺的那块:按 ⌘⇧K,窗口到前台、落在空白新对话、光标在输入框里,直接打字就行。
但这不应该是外挂能干的事。所以我顺手把它每个快捷键的作用域数了一遍,结果比预想的更直接——28 个快捷键,只有 1 个能在 WorkBuddy 之外生效,而那唯一的一个,在我这台机器上压根没注册成功。
| 指标 | 数值 | 说明 |
|---|---|---|
| 快捷键总数 | 28 | 全部可自定义,覆盖导航、编辑、窗口、通用四类 |
| 能在应用外生效 | 1 | 唯一的全局项 toggle-window,默认 Shift+Alt+W |
| 实测该全局项可用 | 0 | 两种方式触发均无响应,注册路径被跳过 |
| 补上这一步的代价 | 29.5 MB | Hammerspoon 常驻内存,空闲 CPU 为 0 |
省下的不是三秒,是那个念头
先算一笔小账:假定一天要问 30 次,每次切窗口、找输入框、点新建平均 3 秒,一天 90 秒,一年不到 9 小时。按这个口径,做不做这个优化都无所谓,谁都不缺这 9 小时。
真正的成本不在秒数。我在用 ChatGPT 和 Claude 的时候有个明显习惯:想到什么立刻按一下就能问,问题倾向于当场问完;换成要切窗口的工具,同一个问题会被我记成一句备忘,攒到晚上一起问。攒起来的那批问题,十个里有七个最后没问——不是不重要,是当时的上下文已经散了。
所以入口延迟影响的不是效率,是使用频率本身。一次交互超过两秒,人就会开始给自己找理由跳过它。这也是为什么 ChatGPT 和 Claude 都把这件事做成了系统级的默认能力,而不是藏在设置里的一个可选项。

ChatGPT 的入口是一条浮条。问完就走,主窗口可以一直不打开。

WorkBuddy 的入口是整扇窗。切过来、找到输入框,才轮到打字。
要点:把 AI 当工具用的人,衡量的是「这一次省了多少」;把 AI 当同事用的人,衡量的是「我愿不愿意随时开口」。前者看功能,后者看入口。
实测:28 个快捷键的作用域分布
WorkBuddy 的快捷键设置页分四类:窗口、编辑、任务、通用。看起来挺完整,但真正决定「能不能在任何地方按下就用」的不是分类,是作用域(scope)。
我把应用包里那份快捷键定义抽出来统计了一遍:app 作用域 21 个,context 作用域 6 个,global 作用域 1 个。也就是说,只要你不在 WorkBuddy 窗口里,27 个快捷键全部失效。
快捷键按作用域分布

28 个快捷键中只有 1 个(toggle-window)是 global 作用域,其余 27 个都要求 WorkBuddy 已在前台或输入框已聚焦。
三个关键项的实际表现
| 动作 | 默认按键 | 作用域 | 能不能在别的应用里按 |
|---|---|---|---|
| 新建对话 | ⌘N | app | 不能 |
| 新建快速问答 | ⌘⇧N | app | 不能 |
| 唤起/隐藏主窗口 | ⇧⌥W | global | 理论上能,实测未注册 |
那个 global 项就是 toggle-window。它的定义写得很清楚:窗口可见且聚焦时隐藏,其余情况恢复并聚焦。语义是对的,问题出在注册时机。
我把主进程代码翻出来看了一遍:注册函数被放在「主窗口尚不存在时才创建窗口」的分支里。而正常启动流程里,窗口在那之前就已经建好了,于是这个分支被短路,注册被跳过——不报错、不提示、设置页里照常显示快捷键已启用。
我用两种方式验证过:程序合成按键、系统级脚本发送。窗口都没有任何反应。这不是我按错了,是这个键从头到尾没注册上。

这是 5.9.3 里的真实代码。getMainWindow() 一旦有值就 return false,后面那串注册语句永远等不到执行。
三个方案,前两个都是我自己的错
既然自带的用不了,就自己补。我先想到的是对标 Claude 的手感:双击修饰键,不占字母键,肌肉记忆成本最低。
方案迭代记录
| 方案 | 结果 | 失败原因 |
|---|---|---|
| 双击 Option | 撞车 | WorkBuddy 把单独按 Option 绑成了语音输入,双击等于连发两次语音指令 |
| 双击 Command | 事件全丢 | 我拿按键码做过滤,但它在这类事件里恒为 0,自己把事件筛没了 |
| ⌘⇧K | 可用 | 与 WorkBuddy 现有快捷键零冲突,走系统级热键注册 |
第一个坑值得展开说,因为它不是我的问题。WorkBuddy 把「单独按 Option」的默认绑定给了语音输入——这跟 Claude 双击 Option 唤起输入框的设计直接对撞。两个功能抢同一个键,表现出来就是「偶尔能生效、偶尔逻辑很奇怪」,因为一半的事件被语音吃了。
第二个坑是我的:Hammerspoon 里监听修饰键变化的事件回调,返回的按键码在任何情况下都是 0。我用它区分左右 Command,等于给所有事件加了一个永远不成立的条件,于是监听器挂着,日志一条不进。这个 bug 掩盖得很好,因为热键列表里我的绑定看起来一切正常。
最后落到 ⌘⇧K。理由很朴素:系统级热键注册不依赖事件监听,不受语音快捷键干扰,也不会被输入法的组合键吃掉。查过 WorkBuddy 现有的 28 项,⌘K 是全局搜索、⌘⇧N 是快速问答、⌘N 是新建对话,⌘⇧K 空着。
注意:想在 macOS 上做「双击修饰键」触发,先查清楚目标应用有没有把这个修饰键单独绑走。修饰键双击天然脆弱:系统可能合并事件、输入法会抢、你自己的逻辑还容易写错。能用组合键就别用双击。
为什么是 Hammerspoon,不是 Raycast
补这个功能有两类工具可选:Hammerspoon 这种配置式脚本引擎,或者 Raycast 那种带界面的启动器。功能上都能做,差别在代价。
Hammerspoon 是原生 Objective-C 外壳 + Lua 脚本,实测常驻 29.5 MB,空闲 CPU 为 0,不建索引、不同步、不联网。Raycast 第一代是原生 Swift,现在已经重写成 WebView + Node 后端,官方拆解里光 WebView 就 120–200 MB、Node 后端 150–200 MB。为了一个快捷键装一个启动器,不划算。
WorkBuddy 自身的内存分布(前 8 大进程)

作为参照:WorkBuddy 单次运行 18 个进程、合计 1792 MB。最大的单个渲染进程 457 MB,已是 Hammerspoon 整个进程的 15 倍。
这不是说 WorkBuddy 内存占用有问题——Electron 应用多进程是这个量级,Chrome 也一样。问题是当它连「按一下就问」这种基础入口都要靠第三方补时,那 1792 MB 里有一块是白花的。
吐槽:不是没做,是没做完
把这件事归到「产品没做」并不准确。它做了:有快捷键设置页、有 global 作用域的字段、有 toggle-window 这个动作,代码里连「被其他应用占用时打警告日志」都写了。这是一个知道该做什么、并且动手做了的团队。
问题出在收尾。功能写完了,但没验证它在真实启动路径上是否生效;注册失败只写进日志,界面上照样显示「已启用」;用户按了没反应,唯一能得到的解释是自己去翻设置。这不是能力问题,是交付标准的问题。
三家 AI 桌面端的入口能力对照
| 产品 | 默认全局唤起 | 唤起后是什么 | 需要主窗口吗 |
|---|---|---|---|
| ChatGPT macOS | ⌥Space | 浮动输入条,可直接提问/截图/传文件 | 不需要 |
| Claude Desktop | 双击 Option | 快速输入框 | 不需要 |
| WorkBuddy 5.9.3 | ⇧⌥W(实测未注册) | 把主窗口切到前台,停在原对话 | 需要 |
三点具体差距,按严重程度排:
一是「唤起」和「新对话」被拆成了两个动作。竞品的全局唤起进去就是一个空白输入框,WorkBuddy 唤起的是你上次那个对话,要新开还得再按 ⌘N。这两个动作在产品逻辑上是独立的,但在用户意图上是一件事——我按快捷键的那一刻,想的是「我要问个新问题」,不是「我要看看上次聊到哪」。
二是快捷键的能力边界没有暴露。设置页列了 28 项,看不出哪些只在窗口内有效。用户很容易以为是自己设置错了,实际上那 27 项本来就不该期待跨应用生效。一个 scope 标签、一句「仅应用内生效」,能省掉用户半小时的困惑。
三是状态不可见。全局热键注册失败是硅谷式静默失败:日志里有 warn,界面上一切正常。这类失败必须让用户看见——设置页那一行应该直接标红「注册失败,可能被其他应用占用」。
要点:这三个问题指向同一个设计惯性:把 WorkBuddy 当成一个「应用」,而不是「随时可用的能力」。一旦按应用来设计,入口就自然长在窗口里;按能力来设计,入口必须先于窗口存在。ChatGPT 和 Claude 的差距不在模型,在这一层。
两边的护栏
如果你在做这类产品
全局入口不是锦上添花,是这类工具的第一优先级。判断标准很简单:用户在其他应用里想到要问的时候,能不能不离开当前窗口就问出口。做不到这一条,其余功能再强,使用频率也会被入口卡死。
另外两条:全局热键注册失败必须可见,不要只写日志;快捷键列表要标出作用域,别让用户猜。这两件事的开发成本都以小时计,但对信任的伤害是长期的。
如果你只是想自己补上
别碰修饰键双击,直接上组合键。选键之前先翻一遍目标应用已有的快捷键定义,避开它的保留键——尤其注意它有没有把某个修饰键单独绑给了别的功能(语音输入是重灾区)。
启动类操作要留出足够的等待时间。冷启动时窗口画出来了不代表界面准备好接快捷键,那中间还有一两秒,早发的按键会被吞掉,表现出来就是「有时候行有时候不行」。
核心逻辑(Hammerspoon,约 20 行)
-- 唤起 WorkBuddy 并落到空白新对话
local BUNDLE = "com.tencent.workbuddy.mac"
local function mainWindow()
local app = hs.application.get(BUNDLE)
if not app then return nil end
for _, w in ipairs(app:allWindows()) do
local f = w:frame()
-- 只认足够大的标准窗口,避开启动闪屏
if w:isStandard() and f.w >= 600 and f.h >= 300 then return w end
end
end
hs.hotkey.bind({ "cmd", "shift" }, "K", function()
-- 未运行:先拉起,轮询等窗口
if not hs.application.get(BUNDLE) then
hs.execute('open -a "WorkBuddy"')
end
local tries = 0
local timer
timer = hs.timer.doEvery(0.5, function()
tries = tries + 1
local w = mainWindow()
if w then
timer:stop()
w:raise(); w:focus()
-- 等渲染器挂稳,否则 ⌘N 会被吞
hs.timer.doAfter(2.5, function()
hs.eventtap.keyStroke({ "cmd" }, "n", 0)
end)
elseif tries > 120 then
timer:stop()
end
end)
end)
引用与来源
本文数据与事实出处
- ChatGPT 桌面版功能页(⌥Space 全局唤起) — 核对于 2026-11-03
- WorkBuddy 官方文档 — 核对于 2026-11-03
- Hammerspoon 官网 — 核对于 2026-11-03








评论前必须登录!
立即登录 注册