版权声明 本站原创文章 由 萌叔 发表
转载请注明 萌叔 | http://vearne.cc
1. 引言
随着本地AI编程助手如Codex、Claude Code和Cursor的普及,开发者开始习惯让AI长时间在后台执行复杂任务:读取文件、运行测试、修改代码、等待权限批准。在这些场景中,你不得不反复切回终端或编辑器确认进度——是否有更直观的方式了解Agent的状态?
你可能已经在朋友圈中看到,有人用类似信号灯的硬件,实时展示AI编程助手的状态。

AI编程助手的状态是如何采集并展示的呢?
最近萌叔发现了一个纯软件实现的vibe coding信号灯 vearne/vibecoding-signal-light,通过悬浮三色灯、菜单栏图标和Touch Bar实时展示AI Agent的工作状态。 本文将深入剖析其技术实现,特别是如何从Cursor编辑器获取状态并映射为灯语。
2. 整体架构:双Swift进程协作
项目采用了清晰的双进程设计,全部基于Swift构建:
- Swift CLI(
signal-light-cli):无状态命令行工具,由Cursor/Codex/Claude Code的hook调用。负责解析事件、更新状态文件、发送跨进程通知。 - Swift App(
signal-light-mac):macOS AppKit长驻应用。读取状态文件,通过动画定时器驱动三色灯UI渲染。

CLI写完状态后,并非只靠App轮询文件。它会双通道通知App立刻刷新:
- Darwin CFNotification(
com.vibecoding.signal-light.status-changed)——跨进程、低延迟 - DistributedNotificationCenter——同用户会话内的兜底通知
App侧同时监听这两种通知,并用文件系统监控作为最终兜底,因此灯语能接近实时变化。
2.1 配置Cursor Hook
应用安装时,会创建 ~/.cursor/hooks.json。
Cursor 的 hooks.json 是一套事件驱动的中间件机制,用来在 Cursor Agent(AI 助手)特定生命周期节点插入自定义脚本,从而观察、拦截、控制或扩展 AI 的行为。可以把它理解为挂在 AI 工作流流水线上的“钩子”。
内容大致如下:
{
"hooks": {
"afterAgentResponse": [{
"command": "\/usr\/local\/bin\/cursor-signal-hook",
"timeout": 5,
"type": "command"
}],
"afterAgentThought": [{
"command": "\/usr\/local\/bin\/cursor-signal-hook",
"timeout": 5,
"type": "command"
}],
"afterFileEdit": [{
"command": "\/usr\/local\/bin\/cursor-signal-hook",
"timeout": 5,
"type": "command"
}]
...
},
"version": 1
}
Cursor 侧注册了约 20+ 个 hook 事件(完整列表见附录);高频几个包括 beforeSubmitPrompt、preToolUse / postToolUse、afterFileEdit、permissionRequest、stop 等。
/usr/local/bin/cursor-signal-hook 指向 signal-light-cli。
注意:由于 signal-light-cli 是被 Cursor Hook 触发执行的,所以存在多个 signal-light-cli 并发执行的可能。(vibecoding-signal-light 使用了文件锁解决互斥问题)
2.2 事件到内部信号的映射
Hook 触发后,CLI 会把原始事件名规范化,再查表映射为内部 signal。Cursor 侧的几条典型链路如下:
| Cursor Hook 事件 | 内部 signal | 灯语含义(默认) |
|---|---|---|
beforeSubmitPrompt | thinking | 绿灯慢闪:开始思考 |
preToolUse / beforeShellExecution / beforeReadFile | working | 绿灯慢闪:正在干活 |
postToolUse / afterFileEdit / afterAgentResponse | tool_done | 绿灯慢闪:工具告一段落,Agent 仍活跃 |
permissionRequest | permission | 红灯闪烁:需要你授权 |
postToolUseFailure | blocked | 红灯闪烁:失败/卡住 |
stop | done | 绿灯常亮:本轮结束,回到空闲 |
Codex、Claude Code 也有各自的事件表,但最终都收敛到同一套内部 signal(如 thinking、working、permission、done),App 只消费这套统一状态,不关心事件来自哪个 Agent。
2.3 状态信息
/private/tmp/signal-light/sessions.json 按 session 记录各路 Agent 的最新信号,形如:
{
"sessions" : {
"27772c50-e0de-4fc7-a025-d5df4f04ac0d" : {
"model" : "default",
"signal" : "done",
"source" : {
"bundle_identifier" : "com.todesktop.230313mzl4w4u92",
"captured_at" : 1784008749.993353,
"localized_name" : "Cursor",
"process_identifier" : 48613
},
"updated_at" : 1784008749.9936671
},
"93b39e2b-b2ad-4824-b1a9-14b89b687c42" : {
"model" : "default",
"signal" : "session_start",
"source" : {
"bundle_identifier" : "com.todesktop.230313mzl4w4u92",
"captured_at" : 1784008238.4849172,
"localized_name" : "Cursor",
"process_identifier" : 48613
},
"updated_at" : 1784008238.485254
}
}
}
/private/tmp/signal-light/current_status.json 是聚合后的当前状态:
{
"aggregate" : "idle",
"updated_at" : 1784008749.994518
}
实际上影响信号灯显示的主要是这个文件。多会话并存时,会取 updated_at 最新的那个有效 session 作为 aggregate,避免旧会话把灯“卡住”在过时告警上。
2.4 规则判断与信号灯显示
各 Agent(Codex、Claude Code、Cursor)的 hook 事件 → 映射成内部状态 → 再按规则显示颜色/闪烁。

可以在 App 界面上配置内部状态 → 显示样式的映射规则:

3. 总结
整条链路可以压成一句话:
Hook 产出事件 → CLI(带文件锁)写成 session/聚合状态 → Darwin/Distributed 通知唤醒 App → App 按可配置规则渲染灯语。
纯软件信号灯并不神秘:关键是把各家 Agent 生命周期事件收敛成同一套内部 signal,再用跨进程通知驱动常驻 UI。映射规则可自定义,也因此容易扩展到更多本地 AI 编程助手。
附录:Cursor Hook 事件一览
安装时写入 hooks.json 的主要 Cursor 事件包括:
| 事件 | 典型用途 |
|---|---|
sessionStart / sessionEnd | 会话起止 |
beforeSubmitPrompt | 用户提交提示 |
preToolUse / postToolUse / postToolUseFailure | 工具调用前后 |
subagentStart / subagentStop | 子 Agent |
beforeShellExecution / afterShellExecution | Shell 执行 |
beforeMCPExecution / afterMCPExecution | MCP 调用 |
beforeReadFile / afterFileEdit | 读文件 / 改文件 |
preCompact | 上下文压缩 |
afterAgentResponse / afterAgentThought | Agent 回复与思考 |
beforeTabFileRead / afterTabFileEdit | Tab 相关读写 |
permissionRequest | 权限请求 |
stop | 停止/结束一轮 |
workspaceOpen | 工作区打开 |
以上事件最终都会经 CLI 映射表落到 thinking / working / tool_done / permission / blocked / done 等内部 signal,再驱动信号灯显示。
