11 Commits
Author SHA1 Message Date
Tam Nhu Tran 0a2c549268 feat(bar): one-click in-app updater with update-available notification
Adds a lightweight self-update path to the CCS Bar menu-bar app so users are
told when a newer build is available and can update with one click.

- App: BarUpdateChecker fetches the published version.txt and compares it to
  the running bundle version (numeric semver). A throttled background check
  (post-launch, then every 6h) surfaces an "Update available" row in the menu;
  "Update Now" spawns `ccs bar install --launch --await-quit` then quits so the
  installer can swap the locked bundle and relaunch. A Settings toggle gates
  the auto-check (default on). Offline checks degrade silently.
- CLI: `ccs bar install --await-quit` waits for a running CCS Bar to quit
  (300ms poll, 15s cap) before swapping, enabling the one-click relaunch.
- Release: bar-release publishes a machine-readable version.txt asset beside
  the app zip so the check is cheap (no full download just to compare).
- Shares the ccs-binary resolver between DashboardLauncher and the updater.
- Bumps bar VERSION to 1.8.0; adds isNewer assertions to ccs-bar-check.

Closes #1588
2026-06-22 21:00:02 -04:00
Tam Nhu Tran 6ed5b2d62b feat(bar): live Codex usage sync with force refresh and spend-chart periods
Codex quota in the menu bar came only from frozen local session logs, so it
showed stale data ("older session") that no refresh could update. Fetch it live
from the same source the dashboard uses, under the existing Claude-style safety
controls (10-min TTL, in-flight coalescing, 429 backoff, circuit breaker,
serve-stale), falling back to local logs when offline or rate-limited. A success
with no usable 5h/weekly window keeps the local reading rather than caching a
contentless row. The footer refresh and a new inline button on the Codex card
force a live pull past the open debounce, and a forced /summary re-pulls native
rows while serving the last-known cached rows if the live pull overruns its
budget, so the Claude/Codex cards never blank mid-refresh.

The spend strip gains a Today / 7d / 30d selector (default 7d), a taller chart,
and bottom time-axis labels (local hours for today, weekday for 7d, dates for
30d). The analytics endpoint now exposes a 24-bucket hourly series for today,
converted from the pipeline's UTC hour keys to the user's local clock so the
intra-day chart matches the dashboard.
2026-06-20 18:37:18 -04:00
Tam Nhu Tran 64fbf2e062 feat(bar): self-start the server from the app and stop dropdown clipping
The app now port-probes for a live CCS server and, if none is found,
starts the recorded detached server itself (launch.json, with a login-shell
fallback) before connecting, so double-clicking the app works without the
CLI. The offline panel gains a Start CCS action and a starting state. The
dropdown is sized to its measured content up to a screen-aware cap instead
of a fixed maxHeight, so it no longer collapses and clips rows.

Refs #1526, #1527
2026-06-15 17:13:58 -04:00
Tam Nhu Tran 28fef67a45 fix(bar-app): periodic background refresh so the glance self-heals
The menu only re-polled on open or after a mutation, so if the server briefly
dropped rows (e.g. a backend restart mid-session) the dropdown could stay stuck
showing stale/missing rows until reopened. Add a 60s background poll that
reconnects if the client was lost and reloads non-force (respecting server-side
caches, so it never hammers providers). As a bonus, alerts now evaluate every
interval instead of only on menu-open, making them genuinely proactive.
2026-06-09 18:32:26 -04:00
Tam Nhu Tran 0b1c4e4908 feat(bar-app): tune density and add spend chart style toggle
Narrow the dropdown (380 to 360) and give it more vertical room (620 to 700).
Tighten the subscription cards (less spacing/padding) since they carry only a
few window rows. Make the spend chart taller (18 to 30) and let the user pick
its style in Settings: chunk bars (default) or a line graph with a subtle area
fill. Persist the choice in UserDefaults.
2026-06-09 17:06:33 -04:00
Tam Nhu Tran e33da989eb feat(bar-app): selectable System/Light/Dark theming
Add a theme token system (CCSBarCore/BarTheme.swift): a BarAppearance enum
(system/light/dark, default dark to preserve the current look), light+dark
token palettes, a colorScheme-driven resolver, and a SwiftUI EnvironmentKey.
The root forces .preferredColorScheme so Light renders light even under a dark
macOS, and paints an explicit light window surface. Thread the tokens (accent,
headroom bands, subscription, card surface, track) through every view so the
whole dropdown themes consistently, with chip text blending toward black on
light. Add an appearance picker in Preferences, persisted in UserDefaults.
Dark accent/subscription values are locked byte-identical and harness-guarded;
pool-account rows now share the muted band palette for cross-section
consistency.
2026-06-09 16:11:36 -04:00
Tam Nhu Tran 559d4340e7 feat(bar-app): quota gauges, threshold alerts, configurable glance
Add real quota gauges with threshold bands and a reset countdown for
quota-capable accounts. Introduce a pure, deterministic alert rule engine
(CCSBarCore) covering quota-remaining, daily/monthly spend caps, reauth, and
cooldown, with per-rule dedupe keys that re-arm on period rollover or
clears-then-recurs so it never spams. Deliver via UNUserNotificationCenter
with an in-dropdown Alerts fallback when notifications are denied. Add a
preferences surface (per-rule toggles, caps, quota levels, glance mode)
persisted in UserDefaults, and a configurable menu-bar glance
(auto/today/month/lowest-quota/account-count) that still never shows a
lifetime dollar. Default spend caps raised to $500/day and $10000/month.
2026-06-09 13:03:44 -04:00
Tam Nhu Tran 4a633eac65 feat(bar-app): per-surface usage UI, unambiguous title, hidden scrollbar
Mirror the richer analytics payload (quotaStatus, per-account last-active,
bySurface) in the Codable models. Add a per-surface usage section (Claude
Code, Codex, Droid, CLIProxy) with proportional bars beside the existing
spend grid, sparkline, and top models. Rebuild the menu-bar title chain so a
lifetime dollar can never sit in the always-on title (it read as live spend):
quota% then today spend then account count. Rebuild the accounts rows
(default badge, tri-state quota, honest no-data cost, health), pivot to an
honest idle hero when no recent data, hide the scroll indicator, and tighten
spacing.
2026-06-09 11:49:55 -04:00
Tam Nhu Tran 9b64514a57 feat(bar-app): add CCS icon variants and usage analytics UI
- Menu-bar icon from the CCS logo: color mark + monochrome template that
  macOS auto-tints; footer toggle, persisted in UserDefaults
- Dropdown analytics section: today/7d/30d/all-time spend, 7-day sparkline,
  top-model bars (BarAnalytics model + client + view)
- Polished rows: branded header, colored health dots, provider/tier chips
- package_app.sh bundles the icon assets into the .app
- assert harness covers analytics decode + compact money/count formatting
2026-06-08 09:31:43 -04:00
Tam Nhu Tran 8350c24733 fix(macos-bar): correct set-default key, lead account, asset name
Send the composite provider:accountId (row.id) for Set as default so the server
can resolve the CLIProxy account; feature the account closest to exhaustion
(lowest remaining quota) in the title instead of the healthiest; rename the
packaged asset to CCS-Bar.app.zip to match what 'ccs bar install' downloads.
2026-06-07 16:38:38 -04:00
Tam Nhu Tran e7001fc252 feat(macos-bar): add SwiftUI MenuBarExtra app + view-model
Menu-bar app that paints cached rows instantly and fires a debounced
force-refresh on open. Dropdown shows per-account health, quota, tier, cost and
paused state with pause/resume, set default, solo and tier-lock actions, plus an
offline state when CCS is not running.
2026-06-07 15:52:03 -04:00