Agent Island:打造悬浮AI助手状态栏,无缝衔接编程工作流
1. 项目缘起当AI助手遇上“刘海儿屏”最近在折腾一个挺有意思的玩意儿我把它叫做“Agent Island”。起因很简单作为一个重度依赖Claude Code或者更早的Codex这类AI编程助手的开发者我遇到了一个几乎所有同行都会碰到的痛点上下文切换的成本太高了。想象一下这个场景你正在VSCode里用Claude Code插件和AI助手就一个复杂的后端API设计聊得火热它已经理解了你的项目结构、业务逻辑甚至刚刚帮你重构了一段核心代码。这时产品经理突然丢过来一个紧急的前端Bug需要你马上看一眼。你不得不切换到浏览器或者另一个编辑器窗口。等你处理完Bug再切回来想继续刚才的对话时Claude Code的会话状态可能已经因为超时被重置了或者你不得不费力地重新描述一遍刚才的上下文“我们刚才在讨论什么来着那个用户鉴权的中间件第三个方案是啥”这种“断片”的感觉非常糟糕。AI助手的价值很大程度上在于它能在一个连续的会话中积累上下文理解你的意图演进。每一次中断都是智力的损耗。于是我就想能不能把Claude Code的“会话状态”——也就是那个包含了历史对话、当前上下文、甚至一些临时记忆的“大脑”——给独立出来像一个小岛Island一样让它始终悬浮在我的视野里随时可见随时可交互这就是“Agent Island”名字的由来。而“刘海儿屏”则是我为这个“悬浮岛”找到的一个绝佳载体。现在很多笔记本尤其是MacBook Pro都配备了所谓的“刘海儿屏”屏幕顶部中央有一块凹进去的区域用于放置摄像头。对于很多开发者来说这块区域除了显示菜单栏的时间、电量图标大部分时候是闲置的。为什么不把这寸土寸金的“刘海儿区”利用起来变成一个常驻的AI助手状态栏呢我的目标很明确开发一个轻量级的桌面应用它能作为Claude Code/Codex等AI编程助手的一个“状态外挂”。这个应用会常驻在屏幕顶部的菜单栏对于有刘海的电脑视觉上就像嵌在刘海两侧实时显示当前AI会话的关键状态如会话是否活跃、最近的主题、可用的Token数等并且点击后能快速唤出一个精简的交互面板进行快速提问或查看历史而无需切换回主编辑器窗口。这相当于给你的AI助手装了一个“第二块屏幕”专门用来维持它的“意识流”。2. 核心架构设计状态抽取与轻量UI要实现这个想法核心在于解决两个问题第一如何从Claude Code/Codex插件中安全、稳定地“抽取”出会话状态第二如何构建一个极致轻量、无干扰的常驻UI2.1 状态抽取与IDE插件的通信桥梁Claude Code或Codex这类VSCode插件其会话状态通常存储在插件的运行时内存中或者通过插件自身的API与后端的AI服务如Anthropic的Claude API或OpenAI的Codex API维持着一个连接。我们无法也不应该直接去侵入式地读取插件进程的内存。正确的方式是建立一个“桥接”。我调研了几种方案VSCode Extension API官方方案这是最理想的方式。理论上可以开发一个配套的VSCode扩展与Claude Code扩展通过VSCode内置的扩展间通信API进行数据交换。但这对普通用户来说门槛太高需要安装两个扩展且受限于VSCode的沙箱环境。进程间通信IPC通过监听本地Socket、命名管道或者使用WebSocket让一个独立的外部进程与VSCode插件通信。这需要修改原插件代码注入一个通信客户端可行性低。“刮取”UI与日志实用主义方案这是最终我采用的折中但有效的方案。既然无法直接获取内部状态那就获取它的“输出”——也就是插件在VSCode侧边栏或面板中渲染的UI内容以及它输出的日志信息。具体实现上Agent Island作为一个独立的桌面应用使用Electron或Tauri框架开发会做以下几件事监听系统活动窗口通过操作系统API如macOS的Accessibility或Windows的UI Automation检测当前活动窗口是否是VSCode并且其标题或特定UI元素是否包含“Claude”或相关标识。模拟读取与解析当检测到目标窗口时应用可以尝试以“辅助功能”的方式读取VSCode中特定侧边栏视图比如Claude Code的聊天面板的文本内容。更稳定的一种方式是引导用户开启Claude Code插件的“详细日志”功能然后Agent Island实时监控并解析VSCode的输出通道Output Channel或指定的日志文件。日志中通常会包含会话ID、消息片段、Token使用量等关键信息。建立轻量API代理进阶对于高级用户可以提供一种配置模式。让用户在Claude Code插件设置中将其API请求代理到Agent Island本地的一个小型HTTP服务器上。Agent Island作为中间人可以无损地获取到完整的请求和响应数据从而还原出最精确的会话状态。这需要用户手动配置API密钥和代理地址安全性需要仔细处理。注意方案3尤其是解析日志的方式高度依赖于具体插件的日志格式。Claude Code的更新可能会改变日志输出导致Agent Island解析失败。因此在代码中需要做好格式兼容和错误处理并提供一个日志格式适配的配置界面。2.2 轻量UI化身“刘海儿屏”上的状态栏UI设计的原则是“零干扰一眼知”。菜单栏图标核心应用启动后只在系统菜单栏屏幕顶部添加一个极简的图标。这个图标就是我们的“Agent Island”。图标本身可以设计成动态的静态/呼吸灯效果表示Agent Island正在运行但未检测到活跃的Claude会话。缓慢闪烁表示检测到VSCode中有Claude Code窗口且会话处于连接状态。快速闪烁或颜色变化表示AI助手正在思考生成回复或有新的消息到来。紧凑状态面板点击菜单栏图标下拉显示一个非常紧凑的面板。这个面板不是完整的聊天界面而是“状态仪表盘”包含当前会话主题从最近几条消息中提取的关键词如“用户认证模块重构”。上下文长度以进度条形式显示已用Token/总Token限制。快速操作按钮一个小的输入框用于快速追问输入后按回车问题会被发送到后台进程并通过模拟键盘输入等方式“注入”回VSCode的Claude聊天框一个“历史摘要”按钮点击后以弹窗形式展示本次会话的浓缩摘要。会话快照显示最近一次问答的简短预览最后一句用户问题和AI回复的开头。“刘海儿屏”区域适配对于有刘海的MacBook Pro应用会检测屏幕参数自动将菜单栏图标和下拉面板的渲染位置进行偏移确保内容显示在刘海左侧或右侧的有效区域视觉上形成“嵌入”感。对于没有刘海的屏幕则按常规菜单栏应用处理。这套UI的核心思想是你不需要一个完整的聊天窗口一直开着那太占地方。你只需要一个随时可以瞥一眼的“状态指示灯”和一个能快速发出指令的“对讲机”。3. 关键技术实现与踩坑实录把想法落地成代码过程充满了“惊喜”。下面分享几个关键模块的实现细节和我踩过的坑。3.1 跨平台窗口与内容侦测要实现“当Claude Code在VSCode中激活时我能知道”需要跨平台的窗口管理能力。我选择了Electron因为它生态成熟能方便地使用Node.js的本地模块。在macOS上我使用了electron结合node-mac-accessibility之类的库。核心代码如下所示用于获取当前最前方窗口的信息// 示例代码基于Electron和macOS Accessibility API const { systemPreferences } require(electron); const { exec } require(child_process); async function getActiveWindowInfo() { // 方法一使用AppleScript较通用 return new Promise((resolve, reject) { exec(osascript -e tell application System Events to get name of first application process whose frontmost is true, (err, stdout) { if (err) reject(err); const appName stdout.trim(); // 进一步获取窗口标题 exec(osascript -e tell application System Events to tell process ${appName} to get name of front window, (err, title) { resolve({ appName, windowTitle: title ? title.trim() : }); }); }); }); // 方法二使用Accessibility API更精准但需要权限 // 需要请求辅助功能权限然后可以遍历UI元素树查找包含特定标识的窗口和视图。 }在Windows上可以使用node-window-manager或active-win这样的npm包。active-win用起来比较直接const activeWin require(active-win); async function checkForVSCodeWithClaude() { const window await activeWin(); if (window window.owner.name.includes(Code) window.title.includes(Claude)) { return true; } return false; }踩坑一权限与性能。在macOS上使用Accessibility API需要用户在系统设置中手动授予辅助功能权限这是一个不小的用户体验障碍。而频繁轮询活动窗口比如每秒一次虽然简单但不够优雅且耗电。更好的方式是使用事件监听但跨平台的统一事件监听机制并不完善。我的解决方案是采用“混合策略”启动时和用户主动点击图标时进行精确检测在后台则采用较低频率的轮询比如每5秒一次并结合“应用切换”全局事件Electron的app模块相关事件来触发检测平衡了实时性和资源消耗。3.2 解析Claude Code插件日志这是获取会话状态最稳定的非侵入式方法。首先需要找到VSCode扩展的日志目录。日志路径通常在~/.vscode/extensions/目录下找到Claude Code插件的文件夹如anthropic.claude-code-*其日志可能输出在插件的子目录中或者更常见的是输出到VSCode的“输出”面板。我们可以引导用户将输出面板的内容重定向到一个文件。引导用户配置在Agent Island的首次设置向导中会给出明确的步骤在VSCode中打开命令面板CmdShiftP。输入并选择 “Preferences: Open Settings (JSON)”。添加配置claude.code.trace.server: verbose具体配置项需根据Claude Code插件实际设置名调整这里是示例。这会让插件输出详细日志。在VSCode的输出面板找到“Claude Code”通道点击右键选择“将输出保存为...”保存到一个固定位置例如~/Desktop/claude_code_log.txt。日志解析器Agent Island会使用Node.js的fs.watchAPI监听这个日志文件的变化。然后编写一个解析函数使用正则表达式匹配关键行。例如const fs require(fs); const tail require(tail); // 可以使用 tail 库更高效地跟踪文件尾部 function parseLogLine(line) { // 示例匹配类似 [INFO] Session “API Design” active, tokens used: 1200/4000 const sessionMatch line.match(/Session\s([^])\sactive.*tokens used:\s*(\d)\/(\d)/i); if (sessionMatch) { return { type: sessionUpdate, sessionName: sessionMatch[1], tokensUsed: parseInt(sessionMatch[2]), tokenLimit: parseInt(sessionMatch[3]) }; } // 匹配用户消息和AI回复 const userMsgMatch line.match(/\[USER\].*?:\s*(.)/i); const aiMsgMatch line.match(/\[ASSISTANT\].*?:\s*(.)/i); if (userMsgMatch) return { type: userMessage, content: userMsgMatch[1] }; if (aiMsgMatch) return { type: aiMessage, content: aiMsgMatch[1] }; return null; } // 监听文件 const tail new Tail(~/Desktop/claude_code_log.txt); tail.on(line, (line) { const event parseLogLine(line); if (event) { // 更新内部状态机并触发UI更新 updateAgentState(event); } });踩坑二日志格式的脆弱性。完全依赖日志解析就像在沙地上建房子插件版本一更新日志格式可能就变了。我的应对策略是“防御性编码”加“用户反馈闭环”。解析函数里每个正则匹配都加了try...catch匹配失败就降级为更宽松的文本匹配只提取可能的话题关键词。同时在UI上设置了一个“反馈”按钮当检测到长时间无法解析有效状态时提示用户“日志格式可能已变化点击反馈”引导用户提交当前的日志片段方便我后续更新解析规则。3.3 状态保持与快速交互抽取出状态后需要在Agent Island内部维护一个轻量化的会话模型。状态管理使用一个简单的状态对象存储在内存中并定期如每30秒序列化到本地文件~/.agent-island/state.json中防止应用崩溃丢失。状态对象包括{ isActive: true, vscodeWindowId: 12345, sessionName: 重构用户模块, tokenUsage: { used: 1500, limit: 4000 }, messageHistory: [ {role: user, content: 如何优化这个查询, timestamp: 1625097600000}, {role: assistant, content: 可以考虑添加索引..., timestamp: 1625097601000} ], lastActivity: 1625097601000 }快速提问的实现这是体验的关键。用户在Agent Island的下拉面板中输入问题并回车后Agent Island将问题文本暂存。通过前面提到的窗口管理API激活VSCode窗口并聚焦到Claude Code的输入框。这可以通过模拟快捷键如CmdShiftP打开命令面板输入“Focus Claude Chat”或更底层的UI自动化点击来实现。使用机器人自动化库如robotjs模拟键盘输入将暂存的问题文本“键入”到输入框。模拟按下“回车”键发送消息。最后再将窗口焦点切换回用户之前所在的窗口通常是浏览器或其他工具。这个过程要尽可能快感觉就像“嗖”的一下问题发出去了视线焦点没变。踩坑三焦点切换的“闪烁”与干扰。最初的实现粗暴地切换焦点导致屏幕一闪打断了用户的工作流。优化方案是“焦点借用”与“延迟恢复”。在模拟输入前记录当前活动窗口。模拟输入时采用“setTimeout”微调时序确保VSCode输入框完全准备好再输入。输入完成后不是立即切换回去而是等待一个非常短的时间如100毫秒再恢复原窗口焦点。对于macOS还可以利用AppleScript的tell application System Events在后台执行按键操作对前台干扰更小。最终效果是用户几乎感知不到VSCode被短暂激活了一下。4. 安全、隐私与未来可能的演进做一个处理AI会话数据的工具安全和隐私是绕不开的话题。数据本地化这是最重要的原则。Agent Island的所有数据解析的日志、会话状态、配置都只存储在用户本地电脑上绝不上传到任何远程服务器。状态文件甚至可以考虑用系统钥匙串Keychain或加密文件存储。API密钥处理如果用户启用了“高级API代理”模式那么Agent Island会临时持有用户的AI服务API密钥以转发请求。这个密钥必须以安全的方式存储在本地如使用keytar库存到系统钥匙串并且仅在内存中解密使用绝不记录在明文日志或普通配置文件中。在UI上要明确告知用户此模式的风险。权限最小化无论是读取日志文件还是监听窗口都需要向用户明确申请权限并解释用途。在macOS上辅助功能权限的申请是一个明确的系统弹窗无法绕过。关于未来这个“小岛”可以变得更智能多会话管理同时监控多个VSCode窗口或不同项目的Claude会话在菜单栏图标上通过数字或标签区分点击后可以切换关注的会话。“会话快照”与知识库允许用户手动保存某个有价值的会话状态包含上下文和对话为一个“快照”并打上标签。未来可以在新的项目中加载这个快照让AI助手快速进入之前的上下文实现知识的跨项目复用。集成更多AI助手不限于Claude Code。理论上只要插件有日志输出或提供API就可以适配GitHub Copilot、Cursor等任何IDE内的AI编程助手。Agent Island可以成为一个统一的“AI编程状态仪表盘”。规则与自动化设置规则例如当AI助手生成的代码片段包含“TODO”或“FIXME”时在状态栏高亮提醒或者当Token使用超过80%时自动发出警告。5. 从想法到可用的原型给尝试者的建议如果你也对这个小工具感兴趣想自己动手实现一个或者基于我的思路改进这里有一些实操建议技术栈选择前端/UI框架Tauri是比 Electron 更优的选择。它使用Rust构建核心应用体积小、内存占用低、启动速度快非常适合这种需要常驻后台、追求轻量的工具。Rust的强类型和安全性也对处理系统级API有帮助。UI可以用任何前端框架React, Vue, Svelte。日志解析不要写死正则表达式。设计一个可配置的“日志模式”规则允许用户通过JSON或简单的DSL来定义如何提取关键信息这样适配新插件会更灵活。自动化操作跨平台的自动化库各有优劣。robotjs不错但Windows上的支持有时会有问题。可以备选nut.js或playwright的桌面模式它们更现代但可能更重。对于macOS纯AppleScript有时是最可靠的。开发与调试先实现核心的“状态侦测”和“日志解析”功能用一个简单的命令行界面CLI输出结果验证可行性。UI部分最后做。先用原生系统托盘API做出一个能显示图标的菜单栏应用再逐步添加下拉面板。调试窗口焦点和自动化输入非常棘手。务必录制操作视频或制作详细的日志记录下每一步操作前后活动窗口的标题、类名等信息方便排查问题。发布与分享由于涉及系统权限和读取其他应用数据在应用商店如Mac App Store上架可能会遇到审核问题。考虑通过GitHub Releases直接提供下载。在README中必须清晰说明应用需要的权限辅助功能、文件访问等、工作原理、数据隐私政策并给出详细的故障排除指南。我自己在开发Agent Island的过程中最大的体会是工具的价值在于无缝融入现有工作流而不是创造新的流程。它没有改变我和Claude Code交互的本质只是把那个原本需要我主动去“找”的会话状态变成了一个随时待命、一眼可知的“环境信息”。这小小的改变带来的流畅感提升是巨大的。现在当我埋头在终端调试或者阅读文档时眼角余光瞥见菜单栏上那个缓缓呼吸的指示灯就知道我的AI伙伴还在那里保持着刚才的思考上下文随时准备接上我的话头。这种“持续在场”的感觉才是人机协同该有的样子。