Tower Island:macOS动态岛AI编程助手统一控制中心
1. 项目概述一个为AI编程助手打造的macOS动态岛控制塔如果你和我一样日常开发中同时开着Claude Code、Cursor、Codex等多个AI编程助手那你一定经历过这种混乱每个助手都运行在独立的终端标签页或IDE窗口里当它们需要你批准文件权限、回答提问或者查看执行计划时你得像个救火队员一样在十几个窗口之间来回切换手忙脚乱。更别提有时候某个助手在后台默默报错了你却浑然不知直到最后才发现代码生成了一堆垃圾。这种碎片化的体验严重打断了我们作为开发者的心流状态。Tower Island就是为了解决这个痛点而生的。它本质上是一个macOS上的全局控制中心灵感来源于iPhone上的“动态岛”Dynamic Island设计。它会以一个悬浮在屏幕顶部的“小药丸”形式常驻实时聚合并展示你所有AI编程助手的运行状态。哪个助手正在工作、哪个完成了任务、哪个在等待你的输入、哪个遇到了错误一目了然。当你需要与助手交互时只需将鼠标悬停上去这个“小药丸”就会优雅地展开成一个功能完整的控制面板让你无需离开当前窗口就能完成所有的审批、问答和监控操作。这个工具非常适合重度依赖AI编程的开发者无论是全栈工程师、数据科学家还是任何希望提升与多个AI助手协作效率的人。它不绑定任何特定的编程语言或框架只要你的AI助手支持基本的钩子hook机制就能被Tower Island统一管理起来。2. 核心功能与设计思路拆解Tower Island的设计目标非常明确非侵入式的全局状态监控与交互。它不希望成为另一个需要你主动去打开的“应用”而是像一个智能的桌面配件安静地待在屏幕边缘只在需要时出现。这种设计哲学直接决定了其技术架构和功能边界。2.1 统一仪表盘告别窗口切换的混乱传统的多AI助手工作流是线性的、割裂的。你启动Claude Code它在一个iTerm2标签页运行然后你切换到Cursor它在另一个窗口Codex可能又在VS Code的集成终端里。每个助手都是信息孤岛。Tower Island的核心价值在于将这些孤岛连接起来形成一个统一的运行上下文。它的实现思路是“事件驱动”的。每个被支持的AI助手如Claude Code、Cursor都提供了某种形式的钩子API允许在特定事件如开始执行、请求权限、完成、报错发生时执行外部命令。Tower Island的“零配置”引擎ZeroConfigManager会在首次启动时自动扫描你的系统找到这些AI助手的配置文件如Claude Code的settings.json、Cursor的hooks.json并为其注入一个轻量级的桥接命令。这个命令指向Tower Island附带的一个独立CLI工具——di-bridge。当AI助手触发事件时di-bridge会被调用它接收JSON格式的事件数据将其编码为统一的DIMessage协议格式然后通过一个本地Unix Domain Socket发送给主应用。主应用的SocketServer监听这个SocketSessionManager负责解析消息、更新对应的AgentSession模型最后SwiftUI视图层实时响应这些变化并更新UI。设计考量为什么用Unix Socket而不是其他IPC这里的选择非常务实。Unix Socket是macOS以及所有Unix-like系统上进程间通信IPC的基石它高效、稳定、轻量。相比于HTTP服务器它没有额外的协议开销相比于管道Pipe它支持全双工通信和更灵活的消息边界处理。对于Tower Island这种需要高频率、低延迟通信的桌面应用来说Unix Socket是最佳选择。di-bridge作为独立的二进制文件通过Socket与主应用通信也实现了很好的解耦即使主应用崩溃重启di-bridge也能独立运行并尝试重连。2.2 实时状态可视化一目了然的运行健康度状态可视化是Tower Island的“门面”。在收缩的“小药丸”状态下空间极其有限如何有效传达信息是关键。它采用了颜色编码的状态点系统蓝色圆点表示助手正在工作中例如正在生成代码、执行命令。这是最常看到的状态。绿色圆点表示任务已成功完成。看到这个你就知道可以放心进行下一步了。橙色圆点表示助手需要你的输入。这可能是权限请求、问题等待回答或计划等待审核。这是需要你立即关注的信号。红色圆点表示执行过程中发生了错误。这是最高优先级的警报。这个设计借鉴了监控系统的仪表盘理念让你在瞥一眼屏幕顶部时就能对整个“AI助手舰队”的健康状况有一个全局认知。如果所有点都是绿色或蓝色说明一切顺利如果出现了橙色或红色你就知道该把鼠标移过去了。2.3 无缝交互在上下文中决策不打断心流这是Tower Island最提升效率的部分。当AI助手需要与你交互时传统方式会弹出一个模态对话框或者你必须切回终端去输入。Tower Island将这些交互直接嵌入到了展开的面板中。权限审批当Claude Code想读取/etc/passwd或者Cursor想执行rm -rf时di-bridge会发送一个permission_request消息。Tower Island展开面板显示一个清晰的审批卡片列出请求的类型读/写/执行、目标文件或命令。你点击“批准”或“拒绝”这个决定会通过di-bridge写回标准输出stdout被等待中的AI助手读取。整个过程你的视线和焦点无需离开当前的代码编辑器。问题回答AI助手有时会提问以澄清需求。同样问题会以卡片形式呈现在展开面板中你直接输入答案并提交即可。这比在终端里打字要直观和快速得多。计划审核一些高级的AI助手如Claude Code在执行复杂任务前会先输出一个步骤计划。Tower Island可以展示这个计划让你在它开始“大兴土木”之前把把关避免它跑偏。所有这些交互的核心在于di-bridge进程的生命周期管理。当它发送一个需要响应的消息如权限请求后它不会立即退出而是会阻塞并等待主应用通过Socket传回用户的决定。主应用处理完用户交互后会将响应指令发送给对应的di-bridge进程该进程再将响应写入stdout最后才退出。这保证了交互的同步性和可靠性。3. 核心组件与架构深度解析要真正理解Tower Island并能进行二次开发或深度定制我们需要深入其代码骨架。它的项目结构清晰遵循了macOS应用和模块化CLI工具的最佳实践。3.1 主应用SwiftUI与AppKit的融合主应用位于Sources/DynamicIsland/目录下是一个标准的SwiftUI macOS应用但有一个关键特殊点它的主窗口是一个NSPanel。// NotchWindow.swift 简化示例 class NotchWindow: NSPanel { override init(contentRect: NSRect, styleMask style: NSWindow.StyleMask, backing backingStoreType: NSWindow.BackingStoreType, defer flag: Bool) { // 配置为浮动面板无标题栏、总在最前、忽略鼠标事件除非悬停 let panelStyle: NSWindow.StyleMask [.nonactivatingPanel, .titled, .fullSizeContentView] super.init(contentRect: contentRect, styleMask: panelStyle, backing: .buffered, defer: false) self.level .floating self.collectionBehavior [.canJoinAllSpaces, .stationary, .ignoresCycle] self.isMovable false // 但支持沿顶部边缘水平拖动 self.backgroundColor .clear self.hasShadow false } }为什么用NSPanel而不是普通的NSWindow.nonactivatingPanel这是关键。它允许面板显示而不激活应用即不会把焦点从你当前的编辑器或终端抢走。这完美符合“非侵入式”的设计目标。.floating级别确保它始终显示在其他常规窗口之上。.canJoinAllSpaces让它出现在每一个桌面空间Space中无论你怎么切换。透明与无阴影为了视觉上更贴合“动态岛”的沉浸感。视图层Views/目录完全采用SwiftUI构建响应SessionManager发布的Published数据变化。CollapsedPillView负责显示收缩状态SessionListView管理展开后的会话卡片列表而PermissionApprovalView等则是特定的交互组件。3.2 通信枢纽DIBridge与共享协议Sources/DIBridge/和Sources/DIShared/是两个独立的模块体现了关注点分离。DIShared (Protocol.swift) 这个模块定义了DIMessage枚举和Socket配置常量被主应用和di-bridge共同引用。这是确保两端能正确理解彼此的关键。// 简化的协议示例 public enum DIMessage: Codable { case sessionStart(agent: AgentType, sessionId: String, metadata: [String: String]) case sessionUpdate(sessionId: String, status: SessionStatus, output: String?) case permissionRequest(sessionId: String, requestId: String, type: PermissionType, target: String) case question(sessionId: String, questionId: String, text: String) // ... 其他消息类型 } public struct SocketConfig { public static let socketPath /tmp/com.towerisland.socket }DIBridge (DIBridge.swift) 这是一个独立的命令行工具。它的工作流程非常清晰从标准输入stdin读取AI助手钩子传来的原始JSON数据。根据命令行参数如--agent claude-code确定消息来源。将原始JSON解析并封装成标准的DIMessage。尝试连接SocketConfig.socketPath指定的Unix Socket。将编码后的DIMessage发送给主应用。如果是需要响应的消息如permissionRequest则阻塞等待主应用返回的DIResponse然后将其打印到stdout。退出。这种设计使得添加对新AI助手的支持变得相对简单你只需要知道如何配置该助手的钩子让其调用di-bridge --agent agent-name并传递约定格式的JSON即可。di-bridge负责将各种助手的“方言”翻译成Tower Island的“普通话”。3.3 大脑与感官Manager们各司其职Managers/目录下的几个核心管理器共同构成了应用的大脑SessionManager单例是应用的状态中心。它维护着一个AgentSession字典以sessionId为键。它处理来自Socket的消息更新会话状态并触发UI更新。它还负责会话的生命周期管理比如根据设置清理已完成completed的会话。SocketServer负责启动一个Unix Socket服务器监听di-bridge的连接。它使用Swift的Foundation框架中的FileHandle和NotificationCenter来处理异步的Socket通信将接收到的数据流解析为完整的DIMessage后交给SessionManager。ZeroConfigManager实现“零配置”魔法的关键。它包含一个已知的“Agent配置器”列表。每个配置器知道特定AI助手如Claude Code的配置文件的可能路径、格式以及如何安全地插入钩子命令。首次运行时它会遍历这些配置器进行检测和配置。TerminalJumpManager实现“点击跳转到对应终端”功能。这比听起来复杂。它需要解析会话元数据中的processId和tty信息然后使用AppleScript或NSWorkspaceAPI来定位并激活对应的终端模拟器如iTerm2或Terminal的特定标签页或窗口。这里涉及到与不同终端应用的私有API或脚本接口打交道是项目中一个技术难点。AudioEngine一个有趣的组件使用AVFoundation框架合成简单的8-bit风格音效为不同事件开始、完成、错误等提供听觉反馈。音效是可配置的可以在设置中关闭。4. 从安装到配置完整实操指南4.1 安装方式选择与避坑指南Tower Island提供了三种安装方式各有适用场景。方式一直接下载DMG推荐给绝大多数用户这是最省心的方式。从GitHub Releases页面下载最新的.dmg文件打开后将应用拖入“应用程序”文件夹即可。但这里有一个所有未经过苹果官方公证Notarized的macOS应用都会遇到的坎Gatekeeper拦截。当你第一次尝试打开时macOS会弹出警告阻止运行。这是因为应用没有苹果开发者签名。解决方法有两种命令行去除隔离属性推荐在终端执行sudo xattr -cr /Applications/Tower\ Island.app这个命令清除了应用包的“扩展属性”extended attributes其中包含Gatekeeper添加的隔离标识quarantine。执行后即可正常打开。系统设置中手动放行进入系统设置 隐私与安全性滚动到最下方通常会看到关于Tower Island的警告点击“仍要打开”即可。但有时这个选项不会立即出现可能需要多尝试打开几次触发警告。重要提示xattr -cr命令是安全的它只删除文件系统扩展属性不会修改应用本身的代码。这是开发者社区处理未签名应用的通用方法。方式二使用CLI升级面向高级用户Tower Island安装时会在~/.tower-island/bin/目录下放置一个名为tower-island的伴侣CLI工具。如果你将这个目录添加到了系统的PATH环境变量中就可以在终端里直接使用tower-island upgrade命令来检查并安装新版本。这个功能依赖于GitHub CLI工具gh。你需要先安装并认证gh。升级命令本质上是通过ghAPI获取最新的Release信息下载新的DMG并自动完成替换安装。这对于喜欢保持在最新版的用户非常方便。如果安装后找不到命令记得将路径添加到你的shell配置文件中如~/.zshrc或~/.bash_profileexport PATH$HOME/.tower-island/bin:$PATH然后执行source ~/.zshrc或重启终端。方式三从源码构建面向开发者或定制者如果你想研究代码、修改功能或为项目做贡献就需要从源码构建。前提是准备好macOS 14.0系统和Swift 5.9工具链。git clone https://github.com/g535879/TowerIsland.git cd TowerIsland bash Scripts/build.sh构建脚本build.sh会执行swift build、处理资源文件、并将最终产物打包成.appbundle。完成后你可以在.build/目录下找到应用并打开。从源码构建绕过了签名问题但Gatekeeper可能仍会警告处理方法同上。4.2 代理配置详解与故障排查Tower Island标榜“零配置”这主要归功于ZeroConfigManager。首次启动时它会进行以下操作扫描检查常见的AI助手Claude Code、Cursor等是否已安装。通常通过查找特定的应用支持目录或配置文件路径来实现。注入如果找到配置它会备份原文件然后在适当位置插入一行钩子配置。例如对于Claude Code它会在~/Library/Application Support/Claude/claude_desktop_config.json路径可能变化中添加一个指向di-bridge的postMessageHook。验证注入完成后它可能会启动一个轻量级的测试确保钩子能被正确调用。如何手动验证或管理配置打开Tower Island点击菜单栏图标或设置齿轮图标进入“代理”Agents标签页。这里会列出所有它支持的AI助手并显示检测和配置状态。你可以手动开关某个助手的监控功能。关闭开关Tower Island会尝试移除对应的钩子配置。常见配置问题排查问题某个AI助手的事件没有在Tower Island上显示。排查步骤首先检查Tower Island的“代理”设置中该助手是否已启用。检查该AI助手自身的配置文件中钩子命令是否正确注入。例如查看Cursor的hooks.json看是否有调用~/.tower-island/bin/di-bridge的命令。可以手动测试钩子。在终端中模拟钩子调用echo {\status\:\testing\} | ~/.tower-island/bin/di-bridge --agent cursor观察Tower Island是否有反应。如果没有可能是di-bridge没有执行权限尝试chmod x ~/.tower-island/bin/di-bridge。查看系统日志。Tower Island和di-bridge在遇到严重错误时会向系统日志Console.app输出信息。搜索“TowerIsland”或“di-bridge”关键词。问题钩子配置被AI助手更新或重置了。解决方案有些AI助手在更新时会重写配置文件覆盖掉Tower Island的钩子。只需重新打开Tower Island的设置进入“代理”页先关闭再重新打开对应助手的开关强制重新注入一次即可。4.3 个性化设置让工具更贴合你的习惯Tower Island的设置项不多但都很实用自动折叠延迟默认3秒。指的是展开的面板在失去鼠标焦点后多久会自动收缩回“小药丸”状态。如果你需要长时间参考面板信息可以把这个时间调长或者设置为“永不自动折叠”如果支持。已完成会话显示时长默认2分钟。完成后绿色状态的会话卡片会保留一段时间再消失方便你回顾。你可以根据自己需要调整从10秒到5分钟或者选择“永不隐藏”。智能抑制这个功能非常贴心。当它开启时如果检测到某个AI助手的关联终端窗口正处于激活状态即你正在看它那么即使这个助手有新事件比如完成Tower Island也不会自动展开面板打扰你。这避免了不必要的干扰让你能专注阅读终端里的输出。音效你可以为不同事件会话开始、完成、错误、需要输入单独开关提示音。8-bit风格的音效能提供非视觉的即时反馈尤其在你不盯着屏幕顶部时很有用。5. 高级使用技巧与场景案例掌握了基础我们来看看如何用它来真正提升日常开发效率。5.1 多会话并行处理工作流假设你正在开发一个Web应用的后端API。你让Claude Code在终端A里为你生成用户认证模块的代码同时让Cursor在终端B里优化数据库查询。突然Claude Code请求读取一个外部配置文件而Cursor遇到了一个模糊的需求需要提问。传统模式下你的屏幕会轮流弹出两个模态对话框或者你需要切来切去。使用Tower Island屏幕顶部的“小药丸”会同时显示一个橙色点需要输入和一个蓝色点工作中。你将鼠标悬停面板展开里面并排显示着两个会话卡片一个是Claude Code的权限请求一个是Cursor的问题。你可以从容地先批准Claude Code的权限然后在同一个面板里回答Cursor的问题。处理完毕后两者继续并行工作。你自始至终没有离开过你正在编写前端代码的编辑器窗口。5.2 利用“窗口跳转”功能快速上下文切换这是Tower Island一个容易被忽略但极其强大的功能。每个会话卡片上都显示了会话标题通常是第一条用户提示和副标题工作空间路径。直接点击这个卡片Tower Island会尝试使用TerminalJumpManager自动将你带到运行该AI助手的精确终端标签页或IDE窗口。这意味着当你看到某个助手报错红色时你不需要回忆它是在哪个iTerm2窗口的哪个标签页直接点击卡片瞬间就能跳转到问题现场进行调试。这大大减少了管理多个终端会话的认知负担。5.3 水平拖动与屏幕空间管理默认情况下“小药丸”会出现在屏幕顶部中央。但有时它会挡住菜单栏的某些项目。你可以用鼠标拖动它沿着屏幕顶部边缘左右移动找到一个不碍事的位置。这个设计既保持了动态岛“附着于边缘”的特性又给了用户一定的灵活性。6. 测试、贡献与扩展开发6.1 运行测试套件确保稳定性项目包含一个用Bash编写的集成测试套件Scripts/test.sh这很特别。它不测试单元逻辑而是模拟真实用户场景测试整个应用与di-bridge的集成和交互。运行测试前必须确保Tower Island主应用正在运行因为测试脚本会启动di-bridge进程并与主应用通信。# 运行完整的测试套件提交代码前必做 bash Scripts/test-all.sh # 运行特定模块的测试 bash Scripts/test.sh M1 M5 M10 # M1: 消息编码解码 # M5: 权限请求与响应流 # M10: 多会话并发处理为了方便开发项目提供了Git钩子安装脚本Scripts/install-git-hooks.sh。安装后每次执行git commit时会自动运行test-all.sh确保提交的代码不会破坏核心功能。6.2 如何为新的AI助手添加支持如果你想让Tower Island支持一个新的AI编程助手比如一个新兴的、本地运行的模型客户端你需要做以下几件事在AgentType枚举中添加新类型修改Sources/DynamicIsland/Models/AgentType.swift增加你的助手类型例如case myNewAgent。实现一个配置器在ZeroConfigManager相关的代码中添加一个新的配置器类或结构体。这个配置器需要知道新助手的配置文件路径例如~/Library/Preferences/com.mynewagent.plist。配置文件的格式JSON, Plist, YAML等。如何安全地将钩子命令注入到该配置中。钩子命令的模板通常是~/.tower-island/bin/di-bridge --agent my-new-agent。如何验证注入是否成功。定义事件数据格式你需要研究新助手的钩子API看它能在哪些事件触发时调用外部命令以及它传递的数据格式。然后确保di-bridge能够解析这个格式并将其映射到标准的DIMessage枚举变体上。这可能需要在DIBridge中添加新的命令行参数解析和JSON转换逻辑。更新UI和文档在设置界面的代理列表中增加新选项并更新README中的支持列表。这个过程的核心是适配器模式将不同助手的私有事件协议通过di-bridge适配成Tower Island内部的统一协议。6.3 架构的优缺点与潜在优化方向优点解耦清晰主应用、桥接器di-bridge、共享协议分离使得各部分可以独立开发和更新。资源占用低主应用作为UIdi-bridge作为轻量级进程按需启动整体对系统资源消耗很小。扩展性强通过添加新的配置器和di-bridge参数可以相对容易地支持新的AI助手。用户体验聚焦非激活面板、智能抑制、一键跳转等设计都紧紧围绕着“不打断开发者”的核心目标。潜在挑战与优化点依赖钩子稳定性功能深度依赖于第三方AI助手的钩子API。如果某个助手大幅修改或移除了钩子支持Tower Island的对应功能就会失效。需要社区持续维护。终端跳转的兼容性TerminalJumpManager需要针对不同的终端应用iTerm2, Terminal, Warp, VS Code集成终端等编写特定的激活脚本。支持所有终端是一个持续的过程。安全性考虑di-bridge作为一个具有执行权限的二进制文件被注入到各种AI助手的配置中。虽然项目本身是开源的但用户需要信任它不会做恶意操作。从技术上讲它可以被设计成以沙盒模式运行或者对接收的JSON数据进行更严格的验证。状态持久化目前会话状态是内存态的应用重启后历史会话会丢失。对于需要复盘或审计的场景可以考虑将会话日志持久化到本地文件或数据库中。Tower Island代表了一种工具设计的新思路在AI辅助编程日益普及的今天我们需要的不仅仅是一个更强大的AI更需要一个能优雅管理多个AI、让它们协同为我们服务的“总控台”。它巧妙地将移动端“动态岛”的交互理念移植到桌面生产力场景用精湛的工程实现解决了真实存在的效率痛点。无论是直接使用还是借鉴其架构思想这个项目都为我们提供了宝贵的参考。