菜单栏 (SwiftBar)
用于监控栈和切换工作树的 macOS 菜单栏集成。
hstack 提供了一款基于 SwiftBar 的 macOS 菜单栏插件。
SwiftBar 会按设定的时间间隔周期性运行脚本,并将其输出渲染为原生 macOS 菜单项。
功能特性
- 状态一目了然,配有动态图标(绿/橙/红)
- 服务器健康状况
- 守护进程状态(PID 及可选的控制服务器探测)
- 开机自启 LaunchAgent 状态
- Tailscale Serve 状态与 URL(若已配置)
- 便捷控制
- 启动、停止或重启栈
- 仅重启守护进程(不影响栈运行)
- 安装、启用、禁用或卸载开机自启
- 启用或禁用 Tailscale Serve
- 详细信息
- PID、CPU 占用率、内存使用量(MB)及运行时间(如可用)
- 常用 URL 和文件路径
- 栈运行时的聚合详情,包含 CPU 与内存总览(服务器 + 守护进程 + 自启服务)
- 在控制台(Console.app)中打开日志
- 刷新控制
- 手动即时刷新
- 菜单内切换刷新间隔(支持 10m/15m/30m/1h/6h/12h/1d 等长周期)
- 采用小型辅助脚本(
extras/swiftbar/set-interval.sh)规避 SwiftBar 的引号转义问题
- 栈与服务布局
- 主栈直接外显(无需展开多层嵌套)
- 每个栈均包含服务行(Server/Daemon/Autostart/Tailscale),并提供各服务的专属子菜单
- 组件(Git 与工作树)
- 收纳于顶层的 Components 子菜单下(保持主菜单整洁)
- 显示当前单体仓库代码检出(
⟦K13⟧/main、⟦K14⟧/dev或⟦K15⟧/{pr,local,tmp}/...下的工作树)的仓库及工作树状态 - 每个仓库条目均配有 Worktrees 子菜单,列出全部工作树并提供切换或打开操作
- 快捷操作:
wt status/sync/update、PR 工作树提示词、打开终端或编辑器(wt shell/code/cursor) - 对比仓库主分支与 origin 及 upstream 的状态(基于上一次
git fetch的数据) - 默认启用 Git 缓存,确保栈和工作树较多时 SwiftBar 刷新依然流畅
运行模式:自托管模式对比开发模式
菜单支持两种工作模式:
- 自托管模式(
selfhost):用于运行 Kaiwu 的轻量级“控制面板”。- 仅显示主栈核心信息(Server/Daemon/Autostart/Tailscale)及精简的 Maintenance 维护项。
- 隐藏栈枚举、Git/工作树和工作树工具等面向开发者的模块。
- 开发模式(
dev):全功能栈控制面板(涵盖所有栈与 Components Git/工作树)。
如何切换模式
- 在菜单顶部的 Mode 区域切换,或者
- 在终端中执行:
hstack menubar mode selfhost
hstack menubar mode dev栈(多实例)
如果创建了多个栈(参见 docs/stacks.md),插件会呈现:
- 主栈(默认栈,名称为
main) - Stacks 区域,列出在
~/.Kaiwu/stacks/⟦K16⟧/env下找到的每个栈
每个栈条目均呈现相同的“迷你控制面板”(包含服务器、守护进程、自启服务、日志及部分操作项),并针对各栈显示专属的端口、目录和 LaunchAgent 标识。
菜单还包含以下功能:
stack new --interactive(创建栈)stack edit ⟦K17⟧ --interactive(修改栈端口、服务器版本或仓库检出路径)stack wt ⟦K18⟧ -- use --interactive(切换栈绑定的仓库检出或工作树)- “PR worktree into this stack (prompt)”(在栈环境下创建
wt pr ... --use)
工作树(快捷入口)
菜单中还提供了工作树工具的快速跳转操作:
hstack wt use --interactivehstack wt new --interactivehstack wt sync-allhstack wt update-all --dry-run/hstack wt update-allhstack wt pr ...(通过菜单内弹窗操作)
若需指定某个栈使用的工作树,请使用:
hstack stack edit ⟦K19⟧ --interactive- 或
hstack stack wt ⟦K20⟧ -- use --interactive
- 或
注意事项(切换工作树)
Kaiwu 采用单体仓库架构,因此切换工作树始终是仓库级别的操作。请使用:
hstack stack wt ⟦K21⟧ -- use --interactive
实现细节
- 入口脚本:
extras/swiftbar/hstack.5s.sh(安装到 SwiftBar 中命名为hstack.⟦K22⟧.sh) - 共享函数:
extras/swiftbar/lib/*.sh(由入口脚本引入) - 辅助脚本:
extras/swiftbar/set-interval.shextras/swiftbar/set-server-flavor.sh
安装说明
1) 安装 SwiftBar
brew install --cask swiftbar2) 安装插件
hstack menubar install若栈作为独立服务运行且指定了名称,推荐以自托管模式安装该栈专属的插件:
hstack menubar install --stack=dev-built --mode=selfhost这样菜单栏将精准定位该栈的服务与运行时状态,而不是通用的主栈视图。
如需在安装时指定不同的默认刷新间隔:
Kaiwu_STACK_SWIFTBAR_INTERVAL=15m hstack menubar install3) 打开当前生效的 SwiftBar 插件目录
SwiftBar 支持自定义插件目录。若要打开当前生效的目录:
hstack menubar open卸载
移除已安装的 SwiftBar 插件文件(不会删除栈或工作区):
hstack menubar uninstall刷新机制(重要)
SwiftBar 的刷新周期由文件名后缀控制:
hstack.30s.sh→ 每 30 秒hstack.5m.sh→ 每 5 分钟hstack.1h.sh→ 每 1 小时
插件默认使用较长的刷新间隔(推荐设置),同时开启了:
refreshOnOpen=false(推荐启用),防止在操作菜单时发生突发刷新干扰使用。
你也可以直接在菜单中的 Refresh interval 项修改刷新间隔(它会自动重命名插件文件并重启 SwiftBar)。
Git 缓存(性能关键)
在栈数量较多时,检查 Git 与工作树是菜单中最耗时的操作。 插件默认运行在缓存模式下:
- 插件会从
~/.Kaiwu-stack/cache/swiftbar/git下的本地磁盘缓存中读取并渲染 Git 及工作树信息。 - 常规的菜单刷新不会调用 Git 命令,从而保持刷新响应敏捷。
- 缓存支持通过菜单操作手动刷新,也可以设置为到达 TTL 过期时间后自动更新。
控制与设置:
- 立即刷新:进入 Components → Git cache 并执行:
- “Refresh now (main components)”
- “Refresh now (all stacks/components)”
- 或在指定栈的 Components 菜单中点击 “Refresh now (this stack)”
- TTL(有效时长):
Kaiwu_STACK_SWIFTBAR_GIT_TTL_SEC(默认21600秒 = 6 小时) - 模式:
Kaiwu_STACK_SWIFTBAR_GIT_MODE=cached|live(默认为cached) - (可选)后台自动刷新:
Kaiwu_STACK_SWIFTBAR_GIT_AUTO_REFRESH_SCOPE=main|all|off(默认为main)
补充说明:
- 缓存的 Git 信息可能存在滞后,仅供快速概览使用。
- 切换工作树、构建或启动开发服务等具体操作始终实时执行(使用
hstack);只有界面展示的 Git 状态经过了缓存。
维护操作(自托管模式)
在自托管模式下,菜单包含一个 Maintenance 维护区域,支持:
- 显示是否有
hstack更新(读取缓存中的~/.Kaiwu-stack/cache/update.json) - 执行:
hstack self checkhstack self update
交互操作的终端偏好设置
许多菜单操作需要打开终端窗口(例如交互式向导、长时间运行的开发服务器等)。
插件借助辅助脚本在常用终端中运行这些任务,环境变量规则与 wt shell 一致:
Kaiwu_STACK_WT_TERMINAL=auto|ghostty|iterm|terminal|current
补充说明:
auto会依次尝试 Ghostty → iTerm → Terminal → 当前终端。- Ghostty 为尽力支持;若当前 Ghostty 版本无法自动执行传入的命令,脚本会将命令复制到剪贴板,并在仓库目录下打开 Ghostty。
开机自启 SwiftBar(可选)
SwiftBar 的启动与 hstack 的 LaunchAgent 或后台服务彼此独立。
- 可在 SwiftBar 偏好设置中勾选 Launch at Login,或
- 将 SwiftBar 添加至 macOS 系统的登录项中。
故障排查
菜单栏未显示插件
- 确认 SwiftBar 正在运行。
- 检查 SwiftBar 正在使用的插件目录:
- SwiftBar → Preferences → Plugin Folder
- 打开当前生效的目录:
hstack menubar open
守护进程显示“auth required”或“no machine”
当在全新设备(或新创建的栈)上运行时,守护进程在栈专属的 CLI 主目录下尚未生成凭据,就会出现此现象。
原因分析
- 守护进程将凭据保存在 CLI 主目录下的
access.key中。 - 对于各个栈(包含主栈),该路径通常为:
~/.Kaiwu/stacks/⟦K23⟧/cli/access.key
- 若缺少
access.key,守护进程会进入交互式认证流程;在认证完成前,它不会注册为“设备”。- 在
launchd(开机自启)管理下,这会表现为 no machine,守护进程看起来可能处于“已停止”状态。
- 在
若仍需完成认证
- 在 SwiftBar 中展开 Daemon 区域:
- 若显示
auth_required,点击 Auth login (opens browser)
- 若显示
- 或者手动执行:
hstack auth login对于指定名称的栈:
hstack stack auth dev-built login如果该指定栈配置为优先使用运行时快照,在快照有效时,引导登录会直接调起基于该运行时的栈 UI。
菜单栏显示的命名栈守护进程或自启状态异常
如果安装的是绑定特定栈的菜单栏插件,其显示内容应与该栈的服务状态保持一致:
hstack stack auth dev-built status
hstack stack service dev-built status如果使用新的运行时快照重新构建了栈,请重启服务,以便菜单栏能捕获到新运行的进程:
hstack stack build dev-built --activate-runtime
hstack stack service dev-built restart如果仅激活了新的前端 Bundle,服务会继续承载已更新的运行时 UI,菜单栏通常无需重启:
hstack stack build dev-built --web
hstack stack runtime dev-built activate --web守护进程明明在运行,却显示“Daemon stale”
插件通过两项指标进行检测:
daemon.state.jsonPID 进程处于活跃状态,且- (可选)守护进程控制服务器正常响应。
如果守护进程正在运行但菜单状态未更新,请手动刷新并查看 “Daemon” 下方的 PID 一行。