feat(desktop): add API-billed usage profiles
Merged
KI
2mo ago+1292+1292+0123456789012345678901234567890123456789-406-406-012345678901234567890123456789
What & why
Supersedes #6967 (thanks @iamgadmarconi) — that branch was 141 commits behind main and on the retired explicit-ID i18n scheme, so this re-applies it on main and reworks the UI. Fixes #6966.
The Usage page can already discover several Claude Code and Codex subscription profiles and switch the default with one click. API-billed profiles (Anthropic Console, codex login --with-api-key) could not take part. Now:
- Add account gets a Billing row: Subscription or API key. The generated command runs the provider's own API login and then writes a marker file into the profile dir; the key never passes through Superset.
- API-billed profiles get an API badge and, instead of quota bars, a "Billed per token" line with a View usage link to the provider's usage page.
- Switch sign-in on an API profile stays on API billing (re-runs the API login, rewrites the marker); Remove works as for any profile.
- Sections render before the first quota read lands, so Add account is reachable immediately.
Changes vs #6967
- Marker is agent-tagged. The marker now holds
claudeorcodex. A presence-only marker made every marked~/.codex-*home also show up as a Claude API profile, because Claude discovery scans all~dot-dirs (reproduced in the running app). - Codex command is one line with
read -rsinstead of thestty/trapsubshell, and the marker step precedesunsetso it follows the login's exit status. A multi-line paste would feed the next line toreadas the key, so it stays single-line on purpose. - Login poll survives an unfocused window.
useHostUsageLoginssetsrefetchIntervalInBackground: true. The app ties react-query's focusManager to window focus, so the poll paused exactly while the user was off in a terminal signing in, and the dialog never noticed the new profile. - Inline
RadioGroupinstead ofTabs; dialog copy trimmed; catalogs for all 17 locales.
How I tested it
bun testonpackages/host-service/src/trpc/router/usage(97 pass) and the desktop usage folder (39 pass): agent-tagged marker classification, fingerprint changes on re-login, other agent's marker ignored, unmarked APIauth.jsonignored, generated commands for both agents and both billing kinds.typecheckfor desktop and host-service, biome clean,bun run check:i18nclean.- Real dev app over CDP, window unfocused:
- Ran the generated Codex command verbatim with a throwaway key:
codex login --with-api-keyaccepted it from stdin and the marker was written; the profile appeared under Codex only. - Claude add flow with API billing: simulated the Console login finishing by writing the marker; the dialog detected it in ~1.5s.
- Switch sign-in on an API profile shows the API login command; Remove deleted both test dirs.
- Ran the generated Codex command verbatim with a throwaway key:
- Not exercised: a real Anthropic Console OAuth login.
Screenshots
Cards under Claude Code and Codex, the dialog in API mode for both providers, the detected state, and Switch sign-in are in the session link below.
https://claude.ai/code/session_01Qy1bWiGW9qq8V3zZ64v2r3
Summary by CodeRabbit
-
New Features
- Added support for API-key billing profiles for Claude and Codex.
- API-billed accounts now show billing status and a link to provider usage pages instead of quota windows.
- Added terminal-based sign-in guidance, including secure API-key entry for Codex.
- Account switching preserves billing type.
-
Improvements
- Usage sections now appear immediately with per-agent “Reading usage…” states.
- Login discovery continues while the app is unfocused.
- Updated translations across supported languages for billing, sign-in, usage, and zoom controls.