Cross-reference the two helpers that solve the persisted-settings-env
override (overlay in launch-settings.ts, strip in
openai-compat-launch-settings.ts) and mark shell-executor's
ANTHROPIC_MODEL_ENV_KEYS as the intentional superset distinct from the
4-key list in extended-context-utils. See issue #1609.
Add a test for the env-only overlay fallback when the persisted settings
file is corrupt (the existing 'missing file' test skips JSON.parse), and
a POSIX-gated assertion that the overlay is written 0600 inside a 0700
dir, since it carries an auth token.
The runtime settings overlay cleanup was registered only on the child
'exit'/'error' events, which run after spawn() returns. A synchronous
spawn() throw (e.g. invalid arg/env) propagated out of launchClaude
before those handlers were wired, orphaning the secret-bearing 0600
overlay file in os.tmpdir(). Wrap the spawn in try/catch and run the
idempotent cleanup before rethrowing.
Addresses two review focus areas:
- Stale Parked Rows: profiles with no on-disk credentials cached their parked
row for the full quota TTL, so a fresh login stayed dimmed for up to 10 min.
Parked rows (quotaStatus 'unsupported') now use a 30s TTL so a new login is
picked up within seconds.
- Codex Fallback: a named codex profile whose token authenticated but whose
response lacked core windows was downgraded to a parked/needsAuth row, hiding
a real subscription. It now emits an active (quota-less) row; only the bare
default still falls back to global local session data.
Also fixes a latent coalescing bug the short TTL exposed: a synchronous return
inside the pending IIFE cleared state.pending during its own assignment, leaving
a stale resolved promise that the next call reused. The IIFE now yields once so
the assignment lands before the finally clears it.
The Codex CLI provider config uses wire_api = "responses", so the Codex CLI
appends "/responses" to its base_url. buildCodexCliproxyProviderBaseUrl derived
the base URL from the backend-aware route helper, which returns the bare root for
the original backend. Codex then called http://127.0.0.1:<port>/responses, which
the original CLIProxy binary does not serve, producing a 404 on every request.
The original backend serves the Codex Responses API only at /v1/responses and the
chatgpt_base_url-compatible alias /backend-api/codex/responses. Use that alias for
the original backend; keep the provider-scoped alias for the Plus backend.
Closes#1597
The collector cached each row before the default profile was resolved, so the
cache-fallback path (getCachedNativeAccountRows) served the default account with
is_default:false -- the UI then lost default ordering/tagging when /summary
served from cache. Write the resolved default flag back onto the cached copy so
the fallback stays consistent with a fresh collection.
The horizontal paging carousel only responded to trackpad swipe; a mouse could
not move it. Add clickable prev/next arrows and make the page dots tappable --
each sets the scrollPosition binding (animated), so mouse users can page through
a provider's profiles. Trackpad swipe is unchanged.
Addresses two review focus areas:
- Reauth polling: a 401/expired profile now caches its dimmed reauth row and
opens a cooldown, so it is shown parked and re-checked at most every 10 min
instead of being re-polled (and re-401'd) on every /summary refresh.
- Wrong fallback: the global ~/.codex session-log fallback now applies ONLY to
the bare default account. A named codex profile with no on-disk auth parks
instead of borrowing the default's local usage (no misattribution).
The per-provider carousel reserved more height than a card needs, leaving blank
space between each card and its page dots. Size the paged frame to the tallest
card (title + one bar per window + optional stale footnote) instead of a generous
estimate, and trim the subscriptions section spacing from 8 to 6.
The multi-profile path enumerated only named ccs auth profiles, dropping the
bare ~/.claude default login that the shipped Bar showed. Re-add it as the
DEFAULT_PROFILE account read through the standard global credential lookup
(file, falling back to the single global 'Claude Code-credentials' Keychain
item Claude Code itself maintains) -- the one pre-existing global read, not a
per-profile Keychain scan. It leads the Claude carousel as 'ccs' + 'default'.
Address UX review: the bare login (e.g. ~/.codex) is the default way of running a
surface, not a profile. Rename it from 'personal' to 'default' and present it as
the base command ('ccsx') with a 'default' badge, while named profiles show their
name ('ck') plus the owning surface tag ('ccsx'). Order each provider carousel so
the default account leads, then by tightest quota window.
Group native subscription rows by provider and render each provider as its own
horizontally paged carousel of profile cards (one profile per page, swipe
between a provider's profiles, page dots indicate count). Add a surface tag
chip (ccs/ccsx) and dim parked profiles. Switch the native-vs-pool split to the
is_subscription flag so pool codex accounts are not misclassified. Raise the
deployment target to macOS 14 for the native scroll paging APIs and bump the
Bar version to 1.9.0.
Replace single-account native quota collection with per-profile enumeration:
read ccs auth (Claude) and ccsx auth (Codex) profile registries plus the bare
~/.codex login, fetch each profile's quota under the existing TTL cache,
per-profile circuit breaker and 2.5s summary deadline. Emit surface, profile
and is_subscription wire fields; account_id becomes "<surface>:<profile>".
Active profiles (valid token) are live-polled and shown undimmed regardless of
default status; profiles without resolvable on-disk credentials are parked
(cache-only, dimmed). Claude per-profile credentials are read from disk only --
no macOS Keychain access -- so a profile without a credentials file renders as
needs-reauth instead of triggering a keychain prompt.