codeburn/mac
ozymandiashh 53cd44daf2 fix(menubar): give the pasted Copilot token a GitHub host of its own
The last rung of the chain is a token the user pastes into Settings, and an
enterprise personal access token pasted there was still sent to
api.github.com. Settings now takes the host beside the token, defaulting to
github.com, and saves both in the same provider Keychain record so the host a
request is addressed to always comes from the entry that carried the token.

A host no endpoint can be derived from is refused at the field instead of
being stored and reported later as a terminal fetch failure, and the crafted
values #1286 guarded against are refused there too. Clearing the token clears
the host with it, so a stale tenant can never be paired with the next token.

The record's decoding moves into an extension and reads every key with
decodeIfPresent: Swift's synthesized init(from:) ignores a property's default
and throws on a missing key, so adding a field would otherwise make every
credential saved before it unreadable — for every provider, not just Copilot.

The dormant connection row no longer promises api.github.com before anything
has been fetched; it names a host only once one has answered.

Tests cover the three new host sources with a hostile value each, the rung
wiring for all five rungs, the gh hosts.yml key scan, and that a record
written before the host field still decodes.
2026-09-12 12:02:13 -07:00
..
Scripts feat(menubar): add native Capacity Dock (#1167) 2026-08-29 00:37:30 -07:00
Sources/CodeBurnMenubar fix(menubar): give the pasted Copilot token a GitHub host of its own 2026-09-12 12:02:13 -07:00
Tests/CodeBurnMenubarTests fix(menubar): give the pasted Copilot token a GitHub host of its own 2026-09-12 12:02:13 -07:00
.gitignore feat(mac): native Swift menubar app + one-command install 2026-04-17 16:55:56 -07:00
Package.swift feat: add native Cursor quota connection 2026-08-29 23:48:42 +05:30
README.md fix(macos): launch mise-installed CLI from Spotlight (#1138) 2026-08-25 04:20:00 -07:00

CodeBurn Menubar (macOS)

Native Swift + SwiftUI menubar app. The codeburn menubar surface.

Requirements

  • macOS 14+ (Sonoma)
  • Swift 6.0+ toolchain (bundled with Xcode 16 or standalone)
  • codeburn CLI installed globally (npm install -g codeburn)

Install (end users)

One command:

codeburn menubar

That's it. The command records the persistent codeburn CLI path, downloads the latest .app from the newest mac-v* GitHub Release with a matching checksum, verifies it, drops it into ~/Applications, clears Gatekeeper quarantine, and launches it. Re-running it upgrades in place with --force, or just launches the existing copy otherwise.

Build from source

For contributors running a local build instead of the packaged release:

npm install -g codeburn                       # CLI the app shells out to for data
git clone https://github.com/getagentseal/codeburn.git
cd codeburn/mac
swift build -c release
.build/release/CodeBurnMenubar                # launch

On macOS 14 (Sonoma) without Xcode 16

swift build above assumes the macOS 15 SDK, whose SwiftUI marks the View protocol @MainActor. The Sonoma SDK (shipped with Command Line Tools) lacks that annotation, so a plain build fails with ~80 main actor-isolated ... from a nonisolated context errors.

(The -10825 launch failure itself is fixed by Package.swift's .macOS(.v14) deployment target: ld64 drops the macOS-15-only libswift_errno.dylib dependency for any build with that target, regardless of which SDK built it, including the CI-distributed release. This local-build path exists only for the narrower case of building on a Sonoma machine with nothing but the Command Line Tools, where the SDK's un-annotated View protocol needs the @MainActor patch below.)

Use the helper, which builds against the local macOS 14 SDK with a standalone swift.org Swift 6.x toolchain and adds explicit @MainActor to the views in a scratch copy (repo sources stay clean), producing a minos = 14.0 bundle installed to ~/Applications:

mac/Scripts/build-local.sh         # then: codeburn menubar

Build & run (dev against a local CLI checkout)

cd mac
swift build
# Point the app at your dev CLI build instead of the globally installed `codeburn`:
npm --prefix .. run build
CODEBURN_ALLOW_DEV_BIN=1 CODEBURN_BIN="node $(pwd)/../dist/cli.js" swift run

The app registers itself as a menubar accessory (LSUIElement = true at runtime). No Dock icon.

Data source

On launch and every 60 seconds thereafter, the app spawns codeburn status --format menubar-json --no-optimize directly (argv, no shell) via CodeburnCLI.makeProcess and decodes the JSON into MenubarPayload. The manual refresh button in the footer invokes the same command without --no-optimize, which includes optimize findings but takes longer.

Release installs record a persistent absolute CLI path in ~/Library/Application Support/CodeBurn/codeburn-cli-path.v1, then fall back to common Homebrew and Node-manager locations. GUI launches augment the minimal macOS PATH with Volta, npm-global, asdf, mise, and nvm runtime locations so a persisted JavaScript launcher also works when the app is opened from Spotlight. For development only, set CODEBURN_ALLOW_DEV_BIN=1 with CODEBURN_BIN; the value is validated against a strict allowlist before use, so a malicious env var can't inject shell commands.

Project layout

mac/
├── Package.swift                     SwiftPM manifest (deployment target: macOS 14)
├── Scripts/
│   ├── package-app.sh                CI: universal signed .app + zip + checksum
│   └── build-local.sh                Local macOS 14 build (Sonoma SDK + @MainActor patch)
├── Sources/CodeBurnMenubar/
│   ├── CodeBurnApp.swift             @main + MenuBarExtra scene
│   ├── AppStore.swift                @Observable store + enums
│   ├── Data/MenubarPayload.swift     Codable payload types + placeholder
│   ├── Theme/Theme.swift             Design tokens (warm terracotta palette)
│   └── Views/MenuBarContent.swift    Popover layout + footer action bar
└── README.md                         This file

Status

Live data wired. Next iterations:

  1. FSEvents watch for ~/.claude/projects/ changes (debounced refresh on real edits)
  2. Persistent disk cache for optimize findings so the default refresh can include them without the 30-second penalty
  3. Currency metadata in the JSON payload + Swift-side formatting
  4. Sparkle auto-update
  5. DMG packaging + Homebrew Cask tap

Design tokens

Sourced from ~/codeburn-menubar-mac-swiftui.html. Warm terracotta-ember palette:

  • Accent (light): #C9521D
  • Accent (dark): #E8774A
  • Ember deep: #8B3E13
  • Ember glow: #F0A070
  • Surface (light): #FAF7F3
  • Surface (dark): #1C1816

SF Mono for currency values; SF Pro Rounded for hero.