ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

CodeBurn Menubar(macOS)深度解析:用 Swift + SwiftUI 构建 AI 编码费用追踪的菜单栏应用

CodeBurn Menubar(macOS)深度解析:用 Swift + SwiftUI 构建 AI 编码费用追踪的菜单栏应用 【免费下载链接】codeburnFree, local tool to track AI coding token usage and cost across 37 tools and agents (Claude Code, Cursor, Codex, Gemini and more), by model, project, and task. npx codeburn项目地址https://gitcode.com/gh_mirrors/co/codeburn点击查看免费下载本指南围绕开源仓库codeburn的 mac/README.md 展开完整讲解 CodeBurn 的原生 macOS 菜单栏Menubar客户端从环境要求、codeburn menubar一键安装与升级到多语言本地化机制、codeburn status --format menubar-json数据刷新管线、常驻serve --stdio子进程以及暖陶土色系的设计令牌。读完本文你将掌握该菜单栏应用的安装、源码构建、开发调试与本地化扩展的完整实操路径并理解其 CLI 进程编排与安全设计的底层实现。CodeBurn 菜单栏应用整体形态一、定位与环境要求CodeBurn Menubar 是一个原生 Swift SwiftUI 菜单栏应用是 codeburn 项目在 macOS 上的菜单栏 surface用户无需打开终端或网页即可从系统菜单栏随时查看 AI 编码工具的 Token 用量与花费。与仓库中 app/electron 的 Electron 桌面端、dash 的 Web 面板形成互补。运行它需要满足三项前提见 mac/README.md 的 Requirements依赖要求说明macOS14Sonoma与 Info.plist 的LSMinimumSystemVersion14.0、CLI 安装守卫MIN_MACOS_MAJOR14保持一致Swift 工具链Swift 6.0随 Xcode 16 附带或使用独立工具链codeburn CLI全局安装npm install -g codeburn应用通过子进程调用它取数据部署目标在 mac/Package.swift 中声明为.macOS(.v14)同时开启StrictConcurrency特性、链接sqlite3。应用运行时把自己注册为菜单栏辅助程序LSUIElement true不出现 Dock 图标这与 mac/Scripts/package-app.sh 生成的 Info.plist 一致。二、一键安装、升级与卸载终端用户安装只需要一条命令codeburn menubar这条命令由 src/menubar-installer.ts 实现其完整流程包括记录 CLI 路径写入持久化的绝对路径文件详见下文数据源章节下载校验从最新的mac-v*GitHub Release 下载.app压缩包并用配套的 SHA-256 checksum 校验验证安装清除 Gatekeeper 隔离属性quarantine后启动应用就地替换如果/Applications或~/Applications中已有同名 bundle直接在原位置替换——不产生第二份副本也不会出现第二个登录项失败回滚旧 bundle 会被移到一旁任何失败都会恢复原状跨卷移动失败时回退为复制 用codesign重新验证不可写回退目标位置不可写时绝不提权不要求管理员权限而是改装到~/Applications遗留副本会以你的用户名命名中断恢复安装中途被杀掉下次运行会继续恢复并发安装会被拒绝。重复执行该命令时加--force会在原地升级否则直接启动已存在的副本。卸载则用codeburn menubar --uninstall从源码层面看安装器会校验 bundle id 必须是org.agentseal.codeburn-menubar对应 mac/Scripts/package-app.sh 中的BUNDLE_ID并在本地数据目录写入installed-by.json标记用于判断该菜单栏是否由codeburn menubar安装、以何种方式安装。此外安装器明确声明该功能仅支持 macOS非 macOS 平台会直接报错。三、从源码构建贡献者路径不想使用打包好的 Release可以在本机编译运行npm install -g codeburn # 应用 shell 出来取数的 CLI git clone https://github.com/getagentseal/codeburn.git cd codeburn/mac swift build -c release .build/release/CodeBurnMenubar # 启动3.1 在 macOS 14Sonoma且没有 Xcode 16 时上面swift build假设使用macOS 15 SDK其 SwiftUI 将View协议标记为MainActor而随 Command Line Tools 附带的 Sonoma SDK 缺少这一注解直接编译会报约 80 个main actor-isolated ... from a nonisolated context错误。需要区分两个不同的问题-10825启动失败由 mac/Package.swift 的.macOS(.v14)部署目标修复——ld64 会对任何以该目标构建的产物包括 CI 分发的 Release丢弃仅存在于 macOS 15 的libswift_errno.dylib依赖本机编译失败仅在Sonoma 机器 只有 Command Line Tools这一窄场景出现原因是 SDK 中未注解的View协议需要下面的MainActor补丁。此时改用仓库提供的辅助脚本mac/Scripts/build-local.sh # 然后: codeburn menubarbuild-local.sh会在本地 macOS 14 SDK 上用独立的 Swift 6.x 工具链构建并在临时副本中给视图显式加上MainActor仓库源码保持干净最终产出一个minos 14.0的 bundle 并安装到~/Applications。值得强调的是发布构建脚本 mac/Scripts/package-app.sh 内置了两道防回归检查用vtool -show-build确认每个架构切片arm64 x86_64 通用二进制的minos均为14.0并用otool -L确认可执行文件没有强链接libswift_errno.dylib任一不满足即构建失败——从 CI 侧保证了 Sonoma 用户不会踩到-10825。四、开发模式指向本地 CLI 构建针对同时开发 CLI 与菜单栏的场景README 提供了如下调试方式cd mac swift build # 让应用指向你的开发版 CLI而不是全局安装的 codeburn: npm --prefix .. run build CODEBURN_ALLOW_DEV_BIN1 CODEBURN_BINnode $(pwd)/../dist/cli.js swift run几点关键行为swift run或 Xcode 构建的进程会按可执行文件名与已安装的应用匹配作为最新启动的实例会在自己起来时让已安装副本退出想并排运行则加--keep-bothswift run CodeBurnMenubar --keep-both。CODEBURN_BIN是仅限开发的覆盖项且必须配合CODEBURN_ALLOW_DEV_BIN1才生效其值在真正使用前会经过严格的正则白名单校验。4.1 进程编排与防注入设计CLI 的调用全部收敛在 mac/Sources/CodeBurnMenubar/Security/CodeburnCLI.swift 中这是关闭 shell 注入攻击面的关键设计safeArgPatternCodeburnCLI.swift只允许[A-Za-z0-9 ._/\-]显式排除$、;、、|、引号、反引号和换行因此类似CODEBURN_BINcodeburn; rm -rf ~的恶意值会被拒绝并回退到已安装的 CLImakeProcessCodeburnCLI.swift通过/usr/bin/env --启动argv 直接传递、不经 shell且--防止参数被误解析为环境变量赋值子进程的qualityOfService被显式提升菜单栏是 accessory 应用macOS 会对后台应用及其子进程做节流不提升的话 codeburn 子进程解析大语料会比交互终端慢 5–10 倍进而饿死 30 秒刷新节奏。五、数据源与刷新管线5.1 status 命令与 JSON 载荷应用在启动时以及此后每 60 秒通过CodeburnCLI.makeProcess直接argv无 shell执行codeburn status --format menubar-json --no-optimize并把输出解码为MenubarPayloadmac/Sources/CodeBurnMenubar/Data/MenubarPayload.swift。--no-optimize表示不包含 optimize 发现项更快菜单栏底部的手动刷新按钮会去掉该参数把 optimize 结果一并刷新但耗时更长。从 CodeBurnApp.swift 可以看到更细的刷新控制基础定时器为 30 秒、手动刷新限流 5 秒、force 刷新看门狗 90 秒、状态载荷看门狗 60 秒。另外应用刻意不做全生命周期的 activity 断言让 App Nap 可以合并空闲 tick 以省电见 CodeBurnApp.swift 与 #647 注释同时用系统调度的NSBackgroundActivityScheduler180 秒周期作为打盹兜底保证休眠打盹时也能定时尝试刷新。5.2 载荷结构MenubarPayload是Codable类型主要包含字段含义current当前周期的用量块成本、调用数、会话数、输入/输出 token、缓存命中率、Codex credits、Top 活动/模型/项目、模型效率、重试税、路由浪费、工具/技能/子代理/MCP 服务器、工作流洞察、重复返工文件、PR 花费、未定价模型等optimizeoptimize 发现项数量、可节省金额与 Top findingshistory按天的历史记录含每日模型细分、有效 token 加权估算combined多设备合并用量perDevice 合计可选claudeConfigsClaude 配置选择器selectedId 选项列表可选liveSessions活跃会话块窗口秒数 会话列表provider、项目、分支、模型、上下文 token/窗口、空闲判定可选telemetrySnapshotCLI 侧的匿名日聚合快照原样透传、不在此处重算可选stale仅当载荷来自只读陈旧 serve 时为true缺失必须读作视为新鲜兼容旧版 CLI绝不会是false代码注释强调了一个兼容性原则大量可选字段对旧版 CLI 缺失字段与值为零做了刻意区分——例如hasUsage缺失按可见处理inputTokens缺失渲染为破折号而非伪造的 0。在真实数据到达前UI 使用的是严格全空的MenubarPayload.empty占位避免任何看起来像真的假数字泄漏进界面。5.3 常驻 serve 子进程请求并非每次现起一个一次性进程而是走常驻的codeburn serve --stdio子进程ServeConnection让解析好的语料库保持热空闲15 分钟900 秒后退役且退役不计入意外死亡下一次请求会启动新的常驻进程而不是一次性进程见 ServeConnection.swift空闲时长可通过UserDefaults键CodeBurnServeIdleSeconds调节或禁用应用退出时会同步回收所有 serve 子进程reapAllshutdown避免孤儿进程。5.4 CLI 定位与 PATH 增强Release 安装会把持久化的CLI 绝对路径记录在~/Library/Application Support/CodeBurn/codeburn-cli-path.v1对应源码中的persistedPathFilenameCodeburnCLI.swift随后才回退到常见 Homebrew 与 Node 管理器位置。对 GUI 启动的应用macOS 只给一个最小化 PATH会漏掉 Homebrew 与 npm 全局安装因此应用在 PATH 末尾追加 Volta~/.volta/bin、npm-global~/.npm-global/bin、asdf shims、mise shims、nvm 运行时目录以及 Nix 的若干 profile 目录/etc/profiles/per-user/$USER/bin、~/.nix-profile/bin等这样从 Spotlight 打开时持久化的 JavaScript 启动器也能工作。augmentedPath还有一个细节既然 CLI 的 shebang 要通过 PATH 解析node而待在 CLI 旁边的那个 node一定满足版本要求它会把这个binDir插到 PATH 最前面防止版本管理器默认的旧 node低于 CLI 要求的 22.13把错误伪装成Could not load Today。六、多语言与本地化应用出厂内置 6 种语言英语en、法语fr、日语ja、韩语ko、简体中文zh-Hans、繁体中文zh-Hant默认跟随系统语言。在Settings General Language中可以单独为 CodeBurn 覆盖语言默认是 System切换即时生效、无需重启。不重启是有原因的macOS 会在应用每次退出时重置访问其他 App 的数据权限如果切语言要重启Warp 用户每次切换都会被重新弹权限询问。实现上设置项把AppleLanguages写入 CodeBurn自己的偏好域——这与系统设置 通用 语言与地区 应用程序写入的是同一个键所以两个入口是同一个设置而非两套桌面端应用的语言设置也驱动同一选择。6.1 字符串表与查找字符串位于mac/Sources/CodeBurnMenubar/Resources/locale.lproj/Localizable.strings全部通过L(_:)/L(_:_:)访问见 mac/Sources/CodeBurnMenubar/Localization.swift。核心设计是键本身就是英文文案如Refresh Now、%lld sessions因此未翻译的字符串会显示为正确的英文而不是一个点号分隔的标识符en.lproj是一个恒等identity表仅用于让 bundle 对外宣称支持 en 并便于测试比对两份表。实现上查找必须走Bundle.module而不是Bundle.mainSwiftPM 会把 target 资源发射到兄弟 bundleCodeBurnMenubar_CodeBurnMenubar.bundle由打包脚本拷进应用的Contents/ResourcesBundle.main根本没有.lproj。L10n直接命名.lproj子 bundle还绕开了 CFBundle 只解析一次本地化的缓存这正是切换语言无需重启的机制基础语言变化时LanguageGeneration.shared.bump()会让长命的 SwiftUI 视图设置窗口、Capacity Dock 栏重跑 body。格式说明符是各语言表之间的契约%用于已格式化好的值货币、token 数、provider 名%lld用于纯IntL(_:_:)刻意不做本地化分组保证替换进去的值与旁边asCurrency()等格式化器的输出一致。6.2 添加一门新语言步骤如下复制en.lproj为locale.lproj翻译其中的 value在三处保持同步的地方登记该 localemac/Package.swift 的.process(Resources/locale.lproj)mac/Scripts/package-app.sh 的CFBundleLocalizationsbuild-local.sh中同样要改否则打包产物不会出现在系统设置的应用语言列表里L10n.supportedLocalizationsLocalization.swift。LocalizationCatalogTestsmac/Tests/CodeBurnMenubarTests/LocalizationCatalogTests.swift会在以下任一情况失败三处登记不一致、任一表中缺键、value 为空、或格式说明符不匹配。另外Provider 与模型名Claude、Codex、Gemini、Sonnet、单位tok/s、ACU、%、货币代码、shell 命令以及 CLI 自己产出的一切文案载荷标签、活动/项目名、转发的错误文本都保持原样不翻译。LanguagePreferencemac/Sources/CodeBurnMenubar/Data/LanguagePreference.swift从应用自身持久域读回当前值而不是UserDefaults.standard.array(forKey:)——后者会穿透到全局域把系统语言误报成应用覆盖值导致.system永远无法显示为选中态#1244。七、项目布局mac/ ├── Package.swift SwiftPM 清单部署目标: macOS 14 ├── Scripts/ │ ├── package-app.sh CI: 通用签名 .app zip checksum │ └── build-local.sh 本地 macOS 14 构建Sonoma SDK MainActor 补丁 ├── Sources/CodeBurnMenubar/ │ ├── CodeBurnApp.swift main MenuBarExtra 场景 │ ├── AppStore.swift Observable store 枚举 │ ├── Localization.swift L(_:) 查找针对模块 bundle │ ├── Resources/en.lproj/ Localizable.strings恒等表 │ ├── Resources/fr.lproj/ Localizable.strings法语 │ ├── Resources/ja.lproj/ Localizable.strings日语 │ ├── Resources/ko.lproj/ Localizable.strings韩语 │ ├── Resources/zh-Hans.lproj/ Localizable.strings简体中文 │ ├── Resources/zh-Hant.lproj/ Localizable.strings繁体中文 │ ├── Data/MenubarPayload.swift Codable 载荷类型 空占位 │ ├── Theme/Theme.swift 设计令牌暖陶土色系 │ └── Views/MenuBarContent.swift Popover 布局 底部操作栏 └── README.md 本文档实际源码比该布局更进一步Sources/CodeBurnMenubar下还有Security/CLI 启动、钥匙串凭据缓存、终端启动器、安全文件读写、Theme/配额告警配色、主题状态、Data/各 Provider 的订阅/配额服务、Capacity Dock 状态、更新检查、遥测以及大量Views/子视图覆盖了配额进度、Provider 连接目录、Sparkline、热力图等可视化组件。八、设计令牌设计令牌源自~/codeburn-menubar-mac-swiftui.html采用暖陶土-余烬warm terracotta-ember色系令牌浅色深色Accent#C9521D#E8774AEmber deep#8B3E13—Ember glow#F0A070—Surface#FAF7F3#1C1816这些值在 mac/Sources/CodeBurnMenubar/Theme/Theme.swift 中落地为brandEmber、warmSurface/warmSurfaceDark并衍生出分类色Claude 陶土橙、Cursor 蓝灰、Codex 绿与语义色危险砖红、警告琥珀、成功灰绿。字体约定货币数值用SF Mono开发者工具身份主视觉hero用SF Pro RoundedFont.codeMono(size:weight:)提供了等宽字体的统一入口。九、当前状态与后续迭代目前实时数据已接通live data wired。README 列出的后续迭代方向用 FSEvents 监听~/.claude/projects/变化真实编辑时做防抖刷新为 optimize 结果加持久化磁盘缓存让默认刷新也能带上 optimize 而不付出 30 秒代价在 JSON 载荷中加入货币元数据并在 Swift 侧格式化Sparkle 自动更新DMG 打包 Homebrew Cask tap。这些方向与桌面端 app/electron/optimize-store.ts、app/electron/updates.ts 的既有能力相呼应也说明菜单栏与桌面端在缓存与更新策略上共享同一套产品思路。整体而言CodeBurn Menubar 展示了原生 SwiftUI 菜单栏 Node CLI 子进程这一轻量组合如何实现进程级安全无 shell argv、白名单校验、PATH 增强、常驻子进程省时的刷新管线、无重启的热切换本地化以及可被测试锁定的多语言一致性——这些实现细节CodeburnCLI.swift、Localization.swift、MenubarPayload.swift都值得继续深入阅读。赞分享【免费下载链接】codeburnFree, local tool to track AI coding token usage and cost across 37 tools and agents (Claude Code, Cursor, Codex, Gemini and more), by model, project, and task. npx codeburn项目地址https://gitcode.com/gh_mirrors/co/codeburn点击查看免费下载相关推荐使用Menubar项目快速构建Electron菜单栏应用使用Menubar项目快速构建Electron菜单栏应用 什么是Menubar项目 Menubar是一个基于Electron的高层封装库专门用于简化创建系统菜桌面应用开发工具探索Menubar构建MacOS系统高效菜单栏应用的秘密武器探索Menubar构建MacOS系统高效菜单栏应用的秘密武器 是一个开源的Node.js库由Max Ogden开发专为创建轻量级、高效的MacOS菜单栏应桌面应用开发工具Menubar终极指南从零开始构建桌面菜单栏应用Menubar终极指南从零开始构建桌面菜单栏应用 Menubar是一个基于Electron的轻量级框架让开发者能够快速创建桌面菜单栏应用。它提供了简洁的AP桌面应用开发工具创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表