Skip to content
返回

让 cvox 支持 Claude Desktop

我写了个小工具叫 cvox(Claude Voice Notifications),通过 Claude Code 的 hooks 系统做语音提醒:Claude 需要权限、或者任务跑完的时候,用 TTS 念一句话给我听,这样我就能离开屏幕去干别的,到点了喊我一声。

最近我开始在 Claude Desktop(桌面 App,不是终端里的 CLI)里使用 Claude Code,然后发现一个问题:装了 cvox 的情况下,任务完成时会发声,但弹出权限确认框时却一点声音都没有

现象

先说清楚两端的区别:

cvox 在 CLI 上一直工作得很好,权限提示和任务完成都会有声音提示,但搬到 Desktop 上之后:

场景CLIDesktop
任务完成(Stop)✅ 有声✅ 有声
权限提示✅ 有声没声

任务完成有声、权限提示没声——这说明 cvox 的发声逻辑本身是好的(不然 Stop 也该哑),问题出在「权限提示」这个事件没被 cvox 接到。

排查:是 cvox 还是 Claude Desktop 的问题

cvox v1 的权限语音,挂的是 Claude Code 的 Notification hook(matcher 为 permission_prompt)。我最初的怀疑是 matcher 写错了,或者 Desktop 那边事件名不一样。

光靠耳朵猜是查不出来的——Desktop 改完配置要重启、改的 matcher 对不对、事件到底有没有来,全是黑盒。所以我给 cvox 加了个探针:往 Claude Code 的 settings 里注入一组「什么都不干、只把 hook_event_name + tool_name 记到日志文件」的 hook,覆盖所有事件、matcher 设成全匹配(空字符串),然后看日志。

结果很清楚:

Desktop 弹权限确认框时,Notification hook 一条都没记到。

即使把 matcher 放宽到全匹配,Desktop 这边的 Notification 依然是 0 条。同一时刻 Stop 事件是正常进日志的。

结论浮出水面:Claude Desktop 弹权限确认框时,根本不触发 Notification hook。有可能是因为我开启了它自带的会话提示功能、也有可能它本身有通知功能所以就不走 Notification hook 了,但我觉得这算是它的 bug。

那 Desktop 的权限事件走哪个 hook

Notification 不触发,但权限框明明弹出来了,总得有个 hook 能接到它吧?

继续看探针日志,这次盯着权限框出现的那一刻,看到的是:

[HH:MM:SS] PermissionRequest Bash

PermissionRequest 触发了。再回 CLI 上对照测一遍——CLI 弹权限时,PermissionRequestNotification 两个都会触发

把两端拼起来就清楚了:

HookCLIDesktop
Notificationpermission_prompt✅ 触发❌ 不触发
PermissionRequest✅ 触发✅ 触发

也就是说,PermissionRequest 是两端都有的那条公共路径,而 Notification 只有 CLI 才走。cvox v1 选的是那条 Desktop 没有的路。

顺带验证了一个之前的猜想:MCP 工具的权限框会不会绕过 hook?答案是不会。mcp__* 工具弹授权框时,PreToolUsePermissionRequest 照常触发,和内置工具走同一套权限管线。所以改挂 PermissionRequest 对 MCP 的权限框同样有效。

改造 cvox

修复思路就很直接了:把 hook 从 Notification 换成 PermissionRequest,因为后者是 CLI 和 Desktop 都会触发的。

hook 配置从原来的 Notification 改成 PermissionRequest(matcher 用空字符串匹配所有权限请求),任务完成继续用 Stop

return {
  hooks: {
    // 权限提示在 CLI 和 Desktop 上都触发 PermissionRequest,
    // 一个 hook 同时覆盖两端。
    PermissionRequest: [
      { matcher: "", hooks: [notifyHook] },
    ],
    Stop: [
      { matcher: "", hooks: [notifyHook] },
    ],
  },
};

最后顺手验证:lint / build 通过,往 stdin 喂各类事件,PermissionRequestStop 都映射正确、未知事件静默丢弃。发版 v2.0.0。

现在一句 cvox init,CLI 和 Desktop 两端的权限提示与任务完成都会念给我听了。

几个值得记下来的坑

排查过程里踩到的、以后还会用得上的经验:

  1. Desktop 的原生 UI 会绕过部分 hook。权限确认框走原生界面,不触发 Notification。要找「两端通吃」的事件,得挑那条公共路径(这里是 PermissionRequest)。
  2. 别用耳朵 debug,用日志。加一个只记事件名的探针 hook,比反复猜「到底响没响、是不是 matcher 错了」高效太多。
  3. 改 settings 里的 hook 必须重启 Desktop / 新开会话才生效。我有一次「没声音」其实是旧会话没加载新 hook,重启后就正常了——很容易误判方向。

分享这篇文章:

上一篇
Claude Desktop 使用体验
下一篇
开通 Stripe 收款 + 提现