Commit Graph
4365 Commits
Author SHA1 Message Date
Tam Nhu Tran cf3bd8a5ef fix(bar): stage downloads and swap so reinstall never strands the user
The reinstall guard deleted the existing bundle before download, so a
transient download or extraction failure left no app on disk. The
archive now extracts into a hidden staging directory inside the
Applications folder; the old bundle is removed only after the new one
is verified in staging, then renamed into place. Every failure before
the swap leaves the previous install untouched, and staging is cleaned
up on all paths.
2026-06-10 14:09:28 -04:00
Tam Nhu Tran f68c08ede3 fix(bar): verify server compat before Gatekeeper steps and harden reinstall
Three review/CI corrections to the install flow:

The compat handshake now runs before the quarantine-clear and launch
block. It is a server-side check unrelated to Gatekeeper, and the
previous ordering let a failed quarantine clear (always the case where
xattr is absent, e.g. Linux CI) skip the handshake entirely.

Reinstalls remove the existing bundle before extraction so the
post-extraction existence check actually proves the fresh bundle
landed; an unremovable bundle aborts install instead of extracting
over it.

Declining the launch prompt now prints the same run-ccs-bar hint as
the non-TTY path instead of ending silently. Install tests inject the
newer deps (clearQuarantine, isBarRunning, promptLaunch) everywhere
the defaults could touch host binaries, keeping results identical on
macOS and Linux runners.
2026-06-10 13:59:08 -04:00
Tam Nhu Tran 015cc4dd32 fix(bar): stop install at the manual step when quarantine clearing fails
A failed quarantine clear previously fell through to the launch
handoff, so a default-yes prompt (or --launch) opened the still
quarantined app straight into the Gatekeeper block. Install now ends
after printing the manual xattr guidance, with a hint to run 'ccs bar'
once quarantine is cleared; --launch does not override a failed clear.
2026-06-10 13:42:52 -04:00
Tam Nhu Tran dfc8b7d1dc fix(bar): harden install handoff per review
Pin xattr and pgrep to absolute /usr/bin paths so quarantine clearing
and process detection cannot be hijacked through a caller-controlled
PATH. Gate the launch prompt on stdin being a TTY instead of stdout, so
piping install output through tee no longer silently skips the
handoff. Detect an already-running CCS Bar via pgrep before prompting:
a running instance gets a quit-and-reopen hint instead of a redundant
launch prompt, while --launch still proceeds explicitly.
2026-06-10 13:36:35 -04:00
Tam Nhu Tran 4eef3f77a4 feat(bar): one-flow install with quarantine automation and launch handoff
'ccs bar install' previously ended with two manual steps: clearing the
Gatekeeper quarantine by hand and running 'ccs bar' separately.

Install now detects an existing installation and says so before
reinstalling, clears the quarantine attribute itself via execFile with
a graceful fallback to the printed hint when xattr fails, and ends with
a TTY-aware 'Launch CCS Bar now?' prompt (default yes) that hands off
to the existing launch flow. --launch forces the handoff and
--no-launch suppresses it for scripted installs; non-TTY runs skip the
prompt and print the manual command instead.

Closes #1504
2026-06-10 13:25:07 -04:00
Kai (Tam Nhu) TranandGitHub f743677d5d Merge pull request #1501 from kaitranntt/kai/fix/1500-bar-launch-reuse
fix(bar): reuse a running CCS web-server instead of failing to bind
2026-06-10 13:17:18 -04:00
github-actions[bot] 16e8531568 chore(release): 8.2.0-dev.4 2026-06-10 17:07:50 +00:00
SergeyandGitHub 298c89f2c3 feat(catalog): add Claude Fable 5 to Anthropic model registry 2026-06-10 13:03:38 -04:00
walker1211andGitHub cf90f48240 fix(mcp): retry Claude user config locks 2026-06-10 13:03:25 -04:00
kastrupproandGitHub f59536a81f fix(cliproxy): guard upstream response timeout cleanup against detached socket 2026-06-10 13:03:17 -04:00
Tam Nhu Tran 2fd90fff9b perf(bar): probe reuse candidates concurrently to avoid launch stalls
Sequential probing of up to 10 loopback targets at 1.5s timeout each
could stall 'ccs bar' for ~15s when a non-CCS service occupied a
candidate port without answering. All probes now run concurrently and
the first success in priority order (bar.json port first, IPv4 before
IPv6 per port) is selected, bounding detection at roughly one probe
timeout.
2026-06-10 12:57:39 -04:00
Tam Nhu Tran 3569297b6d fix(bar): probe IPv6 loopback when detecting a running CCS server
'ccs config' starts the web-server on host 'localhost', which macOS
resolves to ::1, so a reuse probe limited to 127.0.0.1 missed the most
common already-running server and launch started a redundant second
instance. Each candidate port is now probed on 127.0.0.1 first and then
[::1]; an IPv6 hit writes the bracketed-literal baseUrl into bar.json,
which URLSession in the Swift app resolves correctly.
2026-06-10 12:04:10 -04:00
Tam Nhu Tran db1d125f83 docs(bar): troubleshooting reflects reuse-first launch behavior 2026-06-10 11:09:51 -04:00
Tam Nhu Tran af1a2a0f5d fix(bar): reuse a running CCS web-server and probe ports on the bind host
'ccs bar' always tried to start its own web-server. With a CCS server
already listening on 127.0.0.1:3000, get-port (probing the unspecified
address, which macOS allows to bind alongside a specific loopback
listener) reported 3000 as free, and the subsequent 127.0.0.1 bind
failed with EADDRINUSE, aborting launch.

Launch now probes candidate ports (bar.json port first, then the
default list) with a short-timeout GET /api/bar/summary and reuses the
first live CCS server it finds; only when none responds does it start a
new server. The get-port probe also passes host 127.0.0.1 so the
availability check matches the actual bind target. Probe failures are
treated as no-server-found and never break launch.

Closes #1500
2026-06-10 11:09:41 -04:00
github-actions[bot] 67d93e6722 chore(release): 8.2.0-dev.3 2026-06-10 04:22:48 +00:00
Kai (Tam Nhu) TranandGitHub 9a3cee3653 Merge pull request #1498 from kaitranntt/kai/fix/1497-bar-install-version
fix(bar): install version from app bundle and bar-API capability handshake
2026-06-10 00:19:04 -04:00
Tam Nhu Tran e7f3ec0da1 docs(bar): align install docs with Info.plist version pinning and bar-API check 2026-06-10 00:11:38 -04:00
Tam Nhu Tran c572d9f860 fix(bar): read app version from Info.plist and verify bar API instead of version majors
The floating ccs-bar-latest release tag carries no version, so deriving the
app version from tag_name printed 'vccs-bar-latest' and pinned that literal
string. The version now comes from CFBundleShortVersionString in the
extracted bundle's Info.plist; an unreadable plist skips pinning and clears
any stale pin.

The post-install check compared app semver major against the CCS server
major, but the app is versioned independently of the CLI, so the mismatch
warning fired on every install. It is now a capability handshake against
GET /api/bar/summary: 200 confirms the server serves the bar API, 404 warns
the server predates CCS Bar, and anything else keeps the soft warning.
Install never hard-fails on the handshake.

Closes #1497
2026-06-10 00:11:29 -04:00
Tam Nhu Tran 9ae6f85fa7 feat(bar): add ccs bar --help with docker-style help screen
--help and -h are honored anywhere in the args so 'ccs bar install --help'
shows help instead of running the installer. Also wires the 'ccs help bar'
topic, shell-completion flag suggestions, and a more-help table entry.
2026-06-10 00:11:19 -04:00
github-actions[bot] b24c943afc chore(release): 8.2.0-dev.2 2026-06-10 03:15:32 +00:00
Kai (Tam Nhu) TranandGitHub b966ba369a Merge pull request #1495 from kaitranntt/kai/fix/bar-launch-ipv4-bind
fix(bar): real-deployment fixes from normal-user install + CI test isolation
2026-06-09 23:11:48 -04:00
Tam Nhu Tran ad9bdd5794 fix(test): restore real account modules in tier-lock to fully stop mock leak
The prior fix only corrected PROVIDERS_WITHOUT_EMAIL, but the mock still stubbed
validateNickname -> null, hasAccountNameConflict -> false, and registry paths -> '',
which leak to cliproxy-auth-routes (same bun worker) and broke nickname validation
+ registry ops (9 CI failures). Now every mock factory spreads the REAL
account-manager and overrides only the account-DATA reads + IO; afterAll restores
the real account-manager/account-safety modules. tier-lock 8/0, combined ordering
39/0, tsc clean.
2026-06-09 21:25:21 -04:00
Tam Nhu Tran 0770b89037 fix(test): stop tier-lock mock.module leaking an empty PROVIDERS_WITHOUT_EMAIL
bun's mock.module is global and sticky; this test mocked account-manager with
PROVIDERS_WITHOUT_EMAIL: [] at top level and in beforeEach, poisoning the module
registry for later files in the same bun worker. cliproxy-auth-routes imports
PROVIDERS_WITHOUT_EMAIL at load time, got [], and getStartAuthNicknameError's
guard returned null for all providers -> 9 flaky CI failures (ordering-dependent).
Use the real ['kiro','ghcp'] in every mock factory and re-register safe defaults
in afterAll. Verified: worst-case ordering 39/39, full fast bucket 2500/0.
2026-06-09 21:11:10 -04:00
Tam Nhu Tran 2e99b58d09 fix(bar): read codex rollout tail via fs so quota surfaces under node
defaultTailLines used Bun.spawn(['tail',...]), but the ccs server (and
'ccs bar launch') runs under node where Bun is undefined — it threw, the
per-path catch swallowed it, and Codex quota silently never appeared in real
deployments (it only worked under the bun-run dev harness). Replace with a
pure fs read: runtime- and OS-agnostic, no subprocess. Verified under node:
surfaces a live rollout's rate_limits (primary/secondary).
2026-06-09 21:11:01 -04:00
Tam Nhu Tran 2f8745bc1f fix(bar): bind 'ccs bar launch' server to IPv4 loopback
startServer was called without a host, defaulting to 'localhost' which
resolves to ::1 (IPv6) on macOS, while bar.json's baseUrl and the menu-bar
app use 127.0.0.1 — so the app could not reach its own server (connection
refused) and showed offline. Pass host 127.0.0.1 explicitly to match.
2026-06-09 20:08:07 -04:00
github-actions[bot] 7537fd79b3 chore(release): 8.2.0-dev.1 2026-06-09 22:53:22 +00:00
Kai (Tam Nhu) TranandGitHub 2dbfa6a845 Merge pull request #1493 from kaitranntt/kai/feat/ccs-bar
feat(bar): CCS Bar — native macOS menu-bar app for live quota & usage
2026-06-09 18:49:29 -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
Kai (Tam Nhu) TranandGitHub 7d7f033134 Merge pull request #1491 from kaitranntt/kai/feat/ccs-bar-harden-discover
fix+feat(bar): pre-dev hardening + dashboard banner & docs
2026-06-09 18:05:57 -04:00
Tam Nhu Tran 1e7ad7e75e feat(bar): add Get CCS Bar dashboard banner and ccs bar docs page
Add a 'Get CCS Bar' promo banner + card to the dashboard (mirroring the
OpenRouter promo pattern + design system) so users discover the macOS menu-bar
app, with a macOS-aware install CTA. Add a user-facing docs/ccs-bar.md covering
what it is, install via 'ccs bar install', launch, what it shows, uninstall,
and the loopback requirement -- closing the docs-sync gap for the new ccs bar
command.
2026-06-09 18:04:53 -04:00
Tam Nhu Tran 7d3a11a452 fix(bar): resolve pre-dev review findings (security gate, honesty, correctness)
Gate /api/bar/* behind the localhost-when-auth-disabled guard (single DRY
choke point) so native quota/tier/cost can't leak on a non-loopback bind with
auth disabled; add a guard test. Delete the dishonest maxRedirections test that
asserted the opposite of the production redirect hardening. Key per-account
today-cost on the local day (matching analytics) instead of UTC. Stop the
inner 429 retry in the Claude usage fetch so the outer cache + circuit breaker
honor Retry-After. Narrow the usage-transformer map type and fix stale
doc-comments; clarify the one-alert-per-reset-window quota rule; gitignore the
local demo scaffolding.
2026-06-09 18:04:31 -04:00
Kai (Tam Nhu) TranandGitHub ce98a69830 Merge pull request #1490 from kaitranntt/kai/feat/ccs-bar-inline-chart-toggle
feat(bar): inline spend chart bars/line toggle
2026-06-09 17:34:00 -04:00
Tam Nhu Tran a700a92171 feat(bar-app): inline spend chart bars/line toggle in the Spend header
Move the bars/line choice out of Settings and into the Spend section header's
blank space as a small inline toggle, so the user flips the chart style right
where the chart is. Persistence unchanged.
2026-06-09 17:33:40 -04:00
Kai (Tam Nhu) TranandGitHub 0787c445ca Merge pull request #1489 from kaitranntt/kai/feat/ccs-bar-density-spend-chart
feat(bar): density tuning + spend chart Bars/Line toggle
2026-06-09 17:06:53 -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
Kai (Tam Nhu) TranandGitHub b9a4a4a3a4 Merge pull request #1488 from kaitranntt/kai/feat/ccs-bar-settings-window
fix(bar): standalone Settings window, real theme forcing, roomier layout
2026-06-09 16:44:31 -04:00
Tam Nhu Tran b950b41503 fix(bar-app): settings as standalone window, real theme forcing, roomier layout
Move Settings out of the menu-bar popover into a standalone resizable AppKit
window so clicking it no longer steals focus and dismisses the bar (the .sheet
inside MenuBarExtra(.window) was the root cause). Force the actual NSWindow
appearance (aqua/darkAqua/system) on both the popover and the settings window
so Light/Dark visibly flips materials and semantic colors, not just custom
tokens. Replace the fragile popover quit dialog with an inline two-step
arm/confirm. Widen the dropdown and increase spacing/type for readability. Fill
the settings window responsively and make Done close it via the window
controller (dismiss() is a no-op in a hosted NSWindow).
2026-06-09 16:44:10 -04:00
Kai (Tam Nhu) TranandGitHub 97ce63ff75 Merge pull request #1487 from kaitranntt/kai/feat/ccs-bar-settings-discoverability
feat(bar): discoverable Settings + quit confirmation
2026-06-09 16:18:47 -04:00
Tam Nhu Tran 26323c13df feat(bar-app): label settings clearly and confirm before quit
Rename the footer 'Alerts' button to 'Settings' (gear icon) since it opens all
preferences including the appearance/theme picker, which was undiscoverable
behind an alerts label. Add a confirmation to the Quit button so a stray click
no longer closes the whole menu-bar app with no easy way back.
2026-06-09 16:18:28 -04:00
Kai (Tam Nhu) TranandGitHub 107b01903b Merge pull request #1486 from kaitranntt/kai/feat/ccs-bar-theming
feat(bar): selectable System/Light/Dark theming
2026-06-09 16:12:06 -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
Kai (Tam Nhu) TranandGitHub eb384bb999 Merge pull request #1485 from kaitranntt/kai/feat/ccs-bar-footer-and-chips
feat(bar): legible tier chips, Icon label, dashboard auto-start
2026-06-09 15:40:09 -04:00
Tam Nhu Tran 11b3cd5a5c feat(bar-app): legible tier chips, honest Icon label, dashboard auto-start
Lift chip text toward white so small tier badges (max/pro) read clearly on the
dark surface. Rename the icon toggle from Color/Mono to 'Icon' (it only swaps
the menu-bar icon, not the bar theme) to remove the misunderstanding. Make the
Dashboard button actually work when the server is down: probe reachability and,
if not up, launch 'ccs config' (detached) which boots the web-server and opens
the dashboard itself; degrade gracefully when the ccs binary isn't found.
2026-06-09 15:39:50 -04:00
Kai (Tam Nhu) TranandGitHub 20854a94b4 Merge pull request #1484 from kaitranntt/kai/feat/ccs-bar-subscription-palette
feat(bar): retune subscription card palette
2026-06-09 15:14:27 -04:00
Tam Nhu Tran 5aa94b5019 feat(bar-app): retune subscription card palette for the dark theme
Replace the raw system green/yellow/orange/red headroom colors (garish on the
dark surface and colliding with the brand orange) with a muted, intuitive
green-amber-coral-red palette that leans coral for 'low' so a near-empty
window never reads as the accent. Drop the cool indigo card wash for a neutral
elevated surface so the warm bars no longer clash; subscription identity stays
on the section header and badge.
2026-06-09 15:13:56 -04:00
Kai (Tam Nhu) TranandGitHub f22a8a0aee Merge pull request #1483 from kaitranntt/kai/feat/ccs-bar-quota-card-visual
feat(bar): bar-first quota card + sane time formatting
2026-06-09 15:07:42 -04:00
Tam Nhu Tran df967792b9 feat(bar-app): bar-first quota card with sane time formatting
Replace the prose window lines with an aligned per-window bar list (5h /
weekly / Opus / Sonnet), colored by headroom, with the binding window
highlighted and a compact reset chip. Humanize durations beyond a day
(Nd Nh instead of raw hours) and only show the burn-rate pace clause when a
window is projected to exhaust before it resets, so a meaningless 'resets in
44h' / '~110h left' projection no longer appears.
2026-06-09 15:07:08 -04:00
Kai (Tam Nhu) TranandGitHub a5579f84fe Merge pull request #1482 from kaitranntt/kai/feat/ccs-bar-subscription-cockpit
feat(bar): subscription-first cockpit — detailed quota card, Codex fix, scrollbar fix
2026-06-09 14:40:39 -04:00
Tam Nhu Tran 0e0b912187 feat(bar-app): subscription-first cockpit with detailed quota card
Lead the dropdown with subscriptions: a dedicated card shows the binding
window as the hero (gauge, remaining %, reset countdown, and a burn-rate
'left at this pace' line), a secondary window, and the Opus/Sonnet split for
Max, with a stale marker for older Codex data. Demote spend/usage to a compact
strip and surface cross-tool headroom. Add pure burn-rate / time-to-exhaustion
and binding-window math in Core. Kill the menu scroll indicator for real
(NSScrollView hider) so content stays aligned. Spend-cap alerts default off
(pay-per-use, opt-in).
2026-06-09 14:40:03 -04:00
Tam Nhu Tran e96967c224 feat(bar): per-window subscription quota detail + codex multi-session scan
Expose per-window detail (5h / weekly / Opus / Sonnet) on native subscription
rows instead of collapsing to a single percentage, so the bar can show the
binding window, resets, and a burn-rate pace line. Fix the Codex collector to
scan recent session rollouts newest-first for the latest non-null rate_limits
(today's exec-mode session is null) and mark the result stale with its source
time, so Codex quota appears instead of silently vanishing.
2026-06-09 14:39:41 -04:00