ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

CodeBurn Menubar for Windows:基于 Tauri 2.x 的 AI 编码开销系统托盘应用开发指南

CodeBurn Menubar for Windows:基于 Tauri 2.x 的 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点击查看免费下载本文基于仓库内 windows/DEVELOPMENT.md 编写并结合windows/src-tauri下的 Rust 源码与前端页面做深度展开。文中出现的所有路径均以仓库根目录为起点。导读CodeBurn MenubarWindows是 CodeBurn 项目在 Windows 通知区域托盘上的常驻应用它以 Tauri 2.x 承载一个 React TypeScript 的弹出式popover界面把 CLI 采集的 AI 编码 token 用量与成本数据以今天花了多少、哪个模型、哪个项目、哪些 provider的形式呈现在托盘上。本指南面向想要理解、构建与二次开发该应用的开发者读完你将掌握Windows/macOS/Linux 三套开发环境的准备、dev server 的启动与CODEBURN_BIN定向、CLI 查找与版本门禁机制、后台刷新策略、Claude Plan/配额读取原理、MSI 打包、更新检查机制、遥测体系以及贯穿全程的安全模型。一、项目定位Windows 托盘上的 macOS Menubar 镜像CodeBurn MenubarWindows是原生 macOS 菜单栏应用mac/ 下的 Swift 工程在 Windows 上的对位实现二者遵循macOS 版本保持权威观感的原则Windows 版通过共享的 windows/tokens.json 在设计令牌层面颜色、字体、圆角等与 macOS 版保持一致。该 JSON 文件在构建期被 macOS 端读取以生成Theme.swift同时被 Windows 前端的 React 组件以 CSS 自定义属性的方式导入从而实现两张截图读起来像同一个产品。需要特别注意两点边界Linux 支持是编译期保留的实验特性项目仍会编译维护 ksni/AppIndicator 托盘路径但它未发布仓库从本目录产出的 release 只有 Windows 版。Linux 用户应使用 gnome/ 下的 GNOME Shell 扩展。跨平台不是全量平移典型例子是消费金额徽标spend badge。它依赖 Windows 通知区域独有的第二个托盘图标 位图数字能力因此tray_badge在 Linux 构建中被编译排除set_tray_badge命令在 Linux 上会报告不支持前端则通过 windows/src/lib/platform.ts 中的TRAY_BADGE_SUPPORTED隐藏对应控件。任何新增的 Windows-only 能力都必须以同样的方式做cfg门控否则 CI 的 ubuntu 分支会因死代码dead code告警失败。二、架构总览仓库内 windows/ 目录采用典型的 Tauri 双端结构windows/ ├── src/ React TypeScript popover UI运行在 Tauri webview 内 │ ├── components/ 数据区块组件Hero、Models、Findings、Activity 等 30 组件 │ ├── lib/ payload 解析、刷新、平台能力、遥测、货币等纯前端逻辑 │ └── settings/ About / General / Provider 设置面板 ├── src-tauri/ │ ├── src/ │ │ ├── main.rs binary 入口 │ │ ├── lib.rs tray、窗口生命周期、状态接线 │ │ ├── cli.rs 对 codeburn CLI 的 argv 校验式 spawn │ │ ├── config.rs ~/.config/codeburn/config.json 加锁读写 │ │ ├── plan.rs Claude OAuth 配额读取mac 端 ClaudeSubscriptionService.swift 的移植 │ │ ├── telemetry.rs 同意、事件队列与批量 POSTapp/electron/telemetry.ts 的孪生 │ │ ├── refresh.rs 刷新节流算术mac 端 RefreshCadence.swift 的移植 │ │ ├── fx.rs Frankfurter 汇率抓取 24h 磁盘缓存 [0.0001, 1e6] 钳制 │ │ ├── update.rs 版本检查mac 端 UpdateChecker.swift 的移植 │ │ └── tray_badge.rs / tray_linux.rs / dock.rs / glance.rs / session.rs 等 │ ├── capabilities/ Tauri v2 权限清单 │ └── icons/ tray 与打包图标 └── tokens.json 共享设计令牌构建期也被 mac/ 消费Rust 侧各模块职责单一、相互解耦lib.rs负责把窗口与命令command接起来前端页面完全不知道自己运行在哪个平台所有平台差异电量、省电模式、终端偏好、tray badge 能力等都由 Rust 侧通过命令暴露。这是贯穿全文的一个设计主线webview 保持哑平台能力全部下沉到 Rust。三、环境准备Prerequisites3.1 Windows 主机目标平台以管理员身份在 PowerShell 中执行# Rust winget install Rustlang.Rustup rustup target add x86_64-pc-windows-msvc # WebView2 RuntimeTauri 2.x 的 webview 载体 winget install Microsoft.EdgeWebView2Runtime # Microsoft C Build Tools随 Visual Studio Installer 提供勾选 Desktop development with CC Build Tools 是 Windows 上编译 Rust 原生依赖如windows-sys、reqwest的 TLS 栈所必需的链接器环境。3.2 macOS / Linux仅开发用Tauri 在 macOS 与 Linux 上仍可编译用于 UI 内循环迭代。注意正式发布的 macOS 产品是 mac/ 下的 Swift 应用本仓库不产出 Tauri 的 Mac release。# macOS brew install rust node # Ubuntu / DebianTauri 2.x 的系统依赖 sudo apt update sudo apt install -y \ build-essential curl wget file \ libwebkit2gtk-4.1-dev \ libayatana-appindicator3-dev \ librsvg2-dev \ libssl-dev \ libxdo-dev \ libgtk-3-devlibayatana-appindicator3-dev是 Linux 托盘ksni 之上的 AppIndicator 协议的运行时依赖这与 windows/src-tauri/Cargo.toml 及打包配置中 deb 包依赖libayatana-appindicator3-1对应。四、启动开发服务器cd windows npm install npm run tauri dev底层流程tauri dev先在localhost:1420启动 Vite dev server对应 windows/src-tauri/tauri.conf.json 中的beforeDevCommand: npm run dev与devUrl: http://localhost:1420然后构建src-tauri/target/debug/codeburn-menubar并打开一个连接到 dev server 的窗口——React 代码支持热更新托盘图标同时出现。4.1 用CODEBURN_BIN定向本地 CLI在 monorepo 中开发时全局codeburn可能不在 PATH 上。先构建仓库根目录的 CLI再通过环境变量把托盘应用指向本地产物npm --prefix .. run build CODEBURN_BINnode $(pwd)/../dist/cli.js npm run tauri devCODEBURN_BIN的校验逻辑在 windows/src-tauri/src/cli.rs只有当以空白分隔的每个 token 都通过严格白名单字母数字外加._/-与空格Windows 上额外允许\ : ( )以便C:\Users\...\codeburn.cmd这种路径通过时才被采用否则回退到自动解析。之所以如此严格是因为该值最终会以 argv 形式直接 spawn绝不允许任何可被 shell 重新解释的字符进入。4.2 CLI 查找顺序与版本门禁不设置CODEBURN_BIN时应用按以下顺序解析codeburnWindows 上对应codeburn.cmd/codeburn.exe继承的PATH常规 npm / node 前缀%APPDATA%\npm、%LOCALAPPDATA%\Programs\nodejs、pnpm、Volta、scoop shims、/opt/homebrew/bin、~/.npm-global/bin实现见cli.rs的extra_search_dirsWindows 上额外读取注册表中的用户与机器PATH通过reg.exe查询HKCU\Environment与HKLM\SYSTEM\...\Session Manager\Environment因此托盘启动后新安装的 CLI 也能被发现Windows 上最后回退到桌面应用在windows-settings.json中记录的desktopCliPathDESKTOP_CLI_KEY即机器上只装了 CodeBurn 桌面应用、从没跑过npm install -g codeburn时也能借到 CLI。安全细节查找时只考虑绝对路径目录项空项与相对项如;;或.;造成的空路径一律跳过防止从当前工作目录解析出被植入的可执行文件——托盘应用常由 Explorer 或登录时启动其 CWD 不可信。这一点有单元测试find_in_dirs_skips_empty_and_relative_entries直接钉住。如果什么都没找到或codeburn --version低于MIN_CLI_VERSION0.9.9popover 会显示设置界面给出安装命令和 Check again重新检查按钮。该门禁在挂载时、首次 payload 拉取前探测一次。0.9.9 是首个codeburn status --format menubar-json接受--no-optimize的版本quiet 后台刷新始终携带该参数且 popover 读取的所有字段current.providers、current.cacheHitPercent、history.daily[].topModels在该版本均已存在。门禁实现见 windows/src-tauri/src/cli.rs并有version_gate_rejects_only_older_clis测试佐证。4.3 CLI 子进程的看门狗watchdogcli.rs中对 CLI 的每次调用都会拉起一个带超时管制的子进程其边界并非总时长而是静默时长port of macOS 的CLIWatchdog.swift常量值含义SILENCE_SECS45 s已收到过 payloadwarm时子进程无任何输出的静默上限COLD_SILENCE_SECS10 min冷启动首个 payload 未回时静默预算覆盖大语料首次解析前的合法沉默CEILING_SECS15 min无论是否在输出总运行时间上限兜底KILL_GRACE_SECS5 s先请求停止、再强杀之间的宽限VERSION_SILENCE_SECS20 s--version探测的静默上限关键机制子进程 stdout 上限 20 MB、stderr 上限 256 KBMAX_PAYLOAD_BYTES/MAX_STDERR_BYTES两路管道并发排空以免死锁任何一端的输出字节都会刷新静默时钟所以一直有输出的慢解析不会被误杀而卡死不出声的进程会被先礼貌请求停止、再强杀。Windows 上请求停止通过AttachConsoleGenerateConsoleCtrlEvent(CTRL_BREAK_EVENT)发送 CtrlBreaknode 将其转为 SIGBREAKCLI 的清理处理器会因此解除自己的刷新锁拒绝停止的进程再用taskkill /T /F连树杀灭。CODEBURN_PROGRESS1环境变量会开启 CLI 解析器每 10 s 一次的心跳对应 src/parser.ts 的 keepalive心跳行以CODEBURN_PROGRESS前缀出现在 stderr 上报错展示前会被剥离without_progress_lines并有测试保证进度行永远不会变成错误信息。五、刷新策略Refresh Policy每次 CLI 拉取都是一次完整的 Node 进程因此刷新节奏必须跟随 popover 可见性而不是空转。这是对 mac/Sources/CodeBurnMenubar/RefreshCadence.swift 的镜像移植Windows 侧的算术实现位于 windows/src-tauri/src/refresh.rs。文档规定的三档节奏popover 可见60 s 一跳完整拉取含 optimize 发现项popover 隐藏120 s 一跳仅拉today/all携带--no-optimizeshow 事件若可见键数据已超过 60 s立即刷新。源码中interval_secs进一步细化出**自适应auto与手动manual**两种模式windows-settings.json中存原始秒数AUTO-1、MANUAL0两个哨兵值与 macOS 端一致MANUAL定时器永不自动 spawn只在 popover 打开、点Refresh Now、唤醒与首次启动时刷新AUTO默认popover 打开时 30 sACTIVE_SECS否则视电源状态递增——省电模式battery saver300 s、电池供电 150 s、插电 120 s用户自定义正数秒popover 打开时取min(用户值, 30)关闭时按用户值。电源状态通过 Win32GetSystemPowerStatus读取只有ACLineStatus 0明确离线才算电池供电SystemStatusFlag 1表示省电模式开启桌面无电池返回 255unknown时保持插电节奏避免被永久降频。另外机器无人值守时定时器继续走不花成本但会在屏幕上出现前先用会话/用量守卫判定skip如数据未变化这样锁屏归来第一眼看到的就是新鲜数字。refresh.rs内置了完整的节奏单测矩阵manual 永不 spawn、auto 按电源降频、打开的 popover 恒为活跃节奏等。六、Plan / 配额Claude OAuth 用量Plan 药丸在 Claude 标签页或 Claude 是唯一检测到的 provider 时显示读取 Claude Code 的 OAuth 凭据调用https://api.anthropic.com/api/oauth/usage把每个窗口周期的用量展示为百分比。其 Windows 实现 windows/src-tauri/src/plan.rs 是 macOS 端ClaudeSubscriptionService.swift的移植凭据来源~/.claude/.credentials.jsonclaudeAiOauth块中的accessToken、rateLimitTier、subscriptionType窗口维度five_hour5 小时窗口、seven_day7 天总额、seven_day_opus7 天 Opus、seven_day_sonnet7 天 Sonnet展示 0–100 的利用率与下次重置时间快照存储每个窗口在~/.cache/codeburn/subscription-snapshots.json可用CODEBURN_CACHE_DIR覆盖存一条窗口重置前的最终百分比新开的窗口仍能显示上一周期收尾值快照保留 30 天。文件格式与 macOS 端写入的完全一致凭证零日志credential blob 永远不会离开 Rust 侧。最值得注意的设计是401 处理遇到 401 时绝不调用 token 刷新端点。原因与 macOS 端ClaudeCredentialStore.refreshAfter401一致Claude 的 refresh token 是一次性且会轮换的若在这里花掉它会作废 Claude Code 自己正持有的 token、破坏用户的claude登录。正确做法是重新读取 Claude 自己的凭据文件采用一个它已轮换过的新 access token若尚未出现更新的 token则报告瞬时失败等下一次刷新自然恢复。七、生产打包Build a production package# Windows.msi必须在 Windows 主机上执行 npm run tauri build # Linux实验性产物 .deb / .rpm / .AppImage 位于 src-tauri/target/release/bundle/ npm run tauri build打包配置见 windows/src-tauri/tauri.conf.json弹窗窗口384×684、无边框、透明、置顶、跳过任务栏、默认不可见且不抢焦点visible: false、focus: falseCSPdefault-src self; img-src self data:; style-src self unsafe-inline; font-src self data:; connect-src self ipc:——webview 的网络权限只有自身与 IPC对外 HTTP 全部由 Rust 侧代劳打包目标deb、rpm、appimage、msiWindows 侧使用 WiXupgradeCode固定为cfe9191d-...并挂载 windows/src-tauri/wix/uninstall-cleanup.wxs 做卸载清理componentGroupRefs: [CodeBurnUninstallCleanup]deb 包声明依赖libwebkit2gtk-4.1-0与libayatana-appindicator3-1。八、安全模型这是整个应用工程投入最重的部分逐条对应源码进程 spawn对 codeburn CLI 的每次调用都走CodeburnCli::fetch_menubar_payload显式构造 argv 并直接运行二进制从不经过sh -c。CODEBURN_BIN使用前必须过白名单。Windows 系统工具reg.exe、cmd.exe一律以%SystemRoot%\System32下的绝对路径调用system32_path因为CreateProcess会先搜当前目录再搜 PATH——绝对路径调用杜绝了旁边放个同名 exe 顶替系统工具的经典攻击claude同样只从绝对 PATH 目录解析。subcommand 开放进终端展示还有一道白名单TERMINAL_SUBCOMMANDSreport/optimize/doctor/quota/models/sessions/compare只允许这些只读命令见is_allowed_subcommand及其测试。管道stdout 上限 20 MB、stderr 上限 256 KB、静默/总时长双重看门狗挂死的 CLI 无法钉住文件描述符或内存。配置写入~/.config/codeburn/config.json的写入在 POSIX 上用flock于~/.config/codeburn/.config.lock上执行Windows 无 flock用 create-new 锁文件等价实现写者读-改-临时文件-rename 覆盖读者永远看不到半截文件。注意文档明确说明该锁只在本应用的多个实例之间生效——codeburn CLI 并不取这把锁因此它收窄了并发写竞态但并未消除存活的持有者始终持有文件句柄、Windows 不会 unlink 打开中的文件所以 30 s 的陈旧锁清扫只能回收主人已消失的锁对应 windows/src-tauri/src/config.rs 的windows_lock模块。快照写入subscription-snapshots.json拒绝符号链接目标unix 上以 0600 权限写入镜像 macOS 端SafeFile.swift的临时文件 rename模式。凭证Plan 视图读取~/.claude/.credentials.json时设 64 KB 上限并拒绝符号链接access token 只通过 TLS 发给 Anthropic 用量端点refresh token从不被读取或发送。FX 拉取Frankfurter 响应按 JSON 解析汇率在接触任何展示数字前钳制到[0.0001, 1_000_000]新鲜数据若越界即丢弃宁可返回过期缓存也不接受被污染的新数据windows/src-tauri/src/fx.rs 的is_valid与缓存优先逻辑。更新检查GitHub releases 请求强制 HTTPS含重定向、30 s 超时、响应体上限 4 MB且在 Rust 侧执行——webview 永远不触达 api.github.comCSP 也无须放行。本应用不下载、不执行任何更新物安装由codeburn menubar --force完成它会校验 sha256。子进程 stderr 截断到 64 KB并在展示前清洗 API key、JWT 与 Bearer tokenscrub最长前缀优先顺序与 macOS 的sanitizeForDisplay一致。CSPconnect-src仅self与ipc:无内联脚本Frankfurter 与 GitHub 检查都在 Rust 侧完成webview 不需要也不被授予任何对外 host。九、CI 与发布标签.github/workflows/windows-menubar-ci.yml按文档所述路径任何windows/**变更触发在windows-latestubuntu-latest上跑tsc --noEmit、cargo clippy -D warnings与cargo test外加 Windows 上的 release 构建冒烟。windows-v*标签如windows-v0.9.20触发 release 工作流把.msi及其.sha256发布为 Windows Menubar vX release。目前未签名首次运行会触发 SmartScreen 提示直至签名证书就位见待办工作。codeburn menubar安装命令src/menubar-installer.ts把标签钉死在 CLI 自身版本上windows-vcliVersion失败时回退扫描同时携带 msi 与 sha256 两个资产的最新windows-v*releasesha256 校验通过后才执行任何文件随后以%SystemRoot%\System32\msiexec.exe /i msi /passive /norestart安装并按产品 Uninstall 注册表键启动 exe。重命名 bundle 或 MSI 资产会破坏该查找——安装器中的WINDOWS_RELEASE与WINDOWS_PRODUCT_NAME必须随之同步。十、更新检查Updateswindows/src-tauri/src/update.rs 是 macOS 端UpdateChecker.swift的移植但把 mac 的mac-v*发布线换成了windows-v*节奏每两天读一次 releases API查找同时携带CodeBurn.Menubar_version_x64_en-US.msi与其.sha256的最新windows-v*release以及标签为裸v*的最新 CLI release。结果缓存到%LOCALAPPDATA%\codeburn-menubar\update.json所以间隔内重开零请求检查失败则保留缓存里的旧答案徽标不会因网络抖动凭空消失。入口面头部更新徽标、footer 下的 CLI 更新横幅、托盘菜单与 About 里的 Check for Updates。托盘项打开about#check锚点那里展示 up to date / update available / check failed 三种结果也是安装按钮所在的位置。刻意没有安装按钮非 Store 包内应用只报告存在新版本、打开windows-v*release 页、给出手动命令codeburn menubar --force。原因模块文档有完整推理MSI 未签名其校验和与 MSI 本身出自同一个 release——能替换其一者即能同时替换二者自动化安装无从验证真实性手动安装至少经过 SmartScreen 告知用户即将运行之物由谁签署目前是无人。Store 包内检查器直接停工通过GetCurrentPackageFullName检测 MSIX/AppX 包is_packaged_app因为 Store 更新已覆盖它。另有MIN_CLI_VERSION_FOR_UPDATE0.9.21首个menubar子命令能安装 Windows 应用的 CLI——更旧的 CLI 会被提示先升级 CLI 本身。资产命名约束MSI 资产重命名同样会破坏这里的版本解析MSI_PREFIX/MSI_SUFFIX必须与安装器中的WINDOWS_RELEASE联动。十一、遥测Telemetrywindows/src-tauri/src/telemetry.rs 是 app/electron/telemetry.ts 在 Windows 上的孪生两者向同一端点投递同一信封桌面应用与托盘应用落进同一张表靠app.namecodeburn-desktopvscodeburn-menubar区分。改动任何行为前必须先读该文件的模块文档——其不变量即契约。同意Consent桌面应用的状态文件一旦存在即拥有决定权——%APPDATA%\codeburn-desktop\telemetry.v1.json提供installId、enabled、onboardedAt本应用从不写它一次决定覆盖两个应用、事件以同一 id 汇聚。独立安装时决定存于本应用自己的~/.config/codeburn/windows-settings.jsontelemetryEnabled、telemetryOnboardedAt、telemetryInstallId默认值按 Windows 用户区域设置EU/EEA/UK/CH 及未知区域默认关闭其余默认开启。独立安装会被 popover 通知与 Settings General Privacy 询问一次回答前不入队、不发送关闭开关会生成新 install id 并清空队列与桌面端行为一致。事件app_open/app_closesessionMinutes、popover_open、settings_openpane、update_clickaction、glance_open、dock_enabled/dock_disablededge、scaleBucket、dock_provider_switchprovider、dock_drag_endedge以及usage_snapshot——它把 CLI menubar payload 里的telemetrySnapshot对象每天至多转发一次且仅在桌面应用不是同意来源时桌面端会从同一 payload 发送同一聚合。未知事件名直接丢弃每个属性都过与桌面端相同的白名单清洗叶子只能是短字符串、有限数字或布尔嵌套深度5、键数16、数组长度12、叶子数1000全部封顶。传输队列每次变更后持久化到%LOCALAPPDATA%\codeburn-menubar\telemetry-queue.json崩溃或退出不丢事件上限 200 条、最旧让位每 5 分钟批量发送一次、退出时再发一次短超时4xx 丢弃该批5xx 或断网保留至下一拍。Debug 构建除非设置CODEBURN_TELEMETRY_DEV1否则绝不发送。页面接入页面经 windows/src/lib/telemetry.ts 调用telemetry_track自身没有任何门控——所有决定权在 Rust页面无需知道当前决定。例外是dock_enabled/dock_disabled它们来自lib.rs的set_dock_enabled是托盘项、设置开关与 Dock 自身 Hide 项三者共用的唯一漏斗。十二、待办工作Pending WorkWindows.msi代码签名消除 SmartScreen 首启警告并为未来一键安装按钮提供真实性基础详见更新检查模块的推理。Linux 去留决定是否正式发布当前该界面由 gnome/ 扩展覆盖还是把 ksni 托盘从实验状态提升为受支持路径。结语从这份开发文档与对应源码可以看出Windows Menubar 是一个把工程安全刻进每个角落的托盘应用argv 白名单与绝对路径系统工具杜绝注入静默看门狗驯服不可信的 CLI 子进程401 不花 refresh token 保护用户 Claude 登录未签名 MSI 时代刻意放弃自动更新以保全信任边界遥测同意以桌面端为唯一事实源。对于想在 Windows 上复刻 macOS 菜单栏体验的开发者它同时是一份 Tauri 2.x React 的完整范本、一套跨平台移植的对照样本macOS Swift ↔ Tauri Rust以及一份可照抄的桌面安全清单。赞分享【免费下载链接】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 vs 原生开发10个关键因素帮你选择Electron系统托盘应用Menubar vs 原生开发10个关键因素帮你选择Electron系统托盘应用 还在为桌面应用开发方案纠结吗Electron Menubar 提供了一个创桌面应用开发工具解决Tauri应用开发中Vite HMR导致系统托盘重复创建的问题解决Tauri应用开发中Vite HMR导致系统托盘重复创建的问题 在Tauri应用开发过程中使用Vite的热模块替换HMR功能时开发者可能会遇到系统托桌面应用跨平台移动开发Claudia网络通信机制前端与Rust后端的IPC通信详解Claudia网络通信机制前端与Rust后端的IPC通信详解 Claudia作为一款强大的GUI应用和Claude Code工具包其核心功能依赖于前端与后端桌面应用AI 应用AI Agent创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表