Conversation
Preserve matching Codex and Swap logins on each account card, keep workspace identities distinguishable, and test credential fallback, account switching, and spending isolation.
Connect a CLIProxyAPI hub in Settings and every Claude and Codex account it pools becomes its own card, refreshed through the hub's management API with that account's token. Mirrors the usage-limit source T3 Code supports for the same hubs. - Settings ▸ Usage Hubs: add a hub (URL, management key, optional label) after a live account listing, or remove it behind a confirmation. Hubs persist in ~/.config/openusage/usage-hubs.json. - UsageHubClient lists the hub's enabled Claude/Codex credentials and tunnels any provider request through `api-call`, so the existing Codex and Claude usage clients, mappers, and the reset-credit claim run unchanged against a hub account. A claim also clears the hub's routing cooldown (`reset-quota`). - Hub-only accounts reconcile into the account registry with a `usageHub` source and a minted `family@hash` id; an account signed in locally keeps its local card, and hub accounts never count as local logins for the unattributed-history rules. - Hub cards show the family's live-limit rows (split out of the Codex and Claude descriptor lists) and skip the log-backed trend and spend tiles, which need the session logs that stay on the hub.
Bil0000
requested review from
davidarny,
robinebers and
validatedev
as code owners
September 15, 2026 22:24
|
Thanks for your interest in contributing to OpenUsage! External pull requests must reference an open issue that:
Please discuss the change on an issue first, wait for a maintainer to approve and assign it to you, then reopen this pull request with |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
TL;DR
Connect a CLIProxyAPI hub in Settings → Usage Hubs and every Claude and Codex account it pools shows up as its own card, with the same live limits, plan badge, and reset-credit action a local login gets. Mirrors the usage-limit hub support in T3 Code (
apps/server/src/usage/cliproxyApi.ts), on top of the account-first model from #1264.Stacked on #1264. This branch is
maddada:feat/codex-swap-accountsplus one commit; GitHub can't target a fork branch as the base, so the diff here includes #1264's commits until it merges. The hub change itself isc9c8b8b(21 files, +1256/-68).What was happening
auth-files+api-callwith$TOKEN$substitution), so the request contract is known and stable.What this changes
~/.config/openusage/usage-hubs.jsonthrough the existing owner-only atomic writer; the key never touches UserDefaults.UsageHubClient. Lists the hub's enabledclaude/codexcredentials (Codex identity from the listing'sid_tokenclaims, Claude identity from the account's/api/oauth/profileread once and cached), and exposes aTunnelthat conforms toHTTPClientand forwards any request throughPOST /v0/management/api-callfor one credential. The existingCodexUsageClient,ClaudeUsageClient, both mappers, andCodexResetClaimServicerun unchanged against a hub account — no second parsing path.UsageHubProvider. OneProviderRuntimeper hub-held account. Each refresh relists the hub's accounts (so an account added to the hub later reaches the store and gets a card on the next launch, and a removed/disabled credential fails loudly with a typed error instead of fetching with a dead index), then reads usage through the tunnel. Errors map toErrorCategorylike every other provider.usageHubsource kind. Hub-only accounts reconcile intoProviderAccountsStoreand always mint afamily@hashid — the bareclaude/codexid stays reserved for a local login. An account that is also signed in on this Mac keeps its local card (the hub adds nothing a local login lacks). Hub accounts don't count as local logins for the "one local account owns unattributed history" rules from fix: discover Claude Swap accounts and isolate their usage #1226/Add Codex Swap account support #1264, so connecting a hub never flips a single local login into multi-account mode.CodexProvider/ClaudeProviderintolimitDescriptors(provider:); local cards keep the same list plus trend and spend tiles, hub cards show only the limits. Hub cards inherit their family'sDefaultLayoutdefaults through the existingexpandingAccountsfan-out and slot right after the family's local cards in the provider order.CodexResetClaimServiceover the tunnel; after a successful claim the hub's routing cooldown for that account is cleared viareset-quota(best-effort, like T3 Code) before the post-claim refresh.docs/settings.md(new Usage Hubs section),docs/providers/claude.md,docs/providers/codex.md, README.Heads-up
http://works for localhost, IPs, and.localnames; other hosts needhttps://(ATS). Documented.ClaudeProviderapplies per token).Tests
UsageHubTests(11 tests): listing filters (disabled, non-Claude/Codex, nameless credentials), known-identity reuse without profile calls, typed management errors (401 → key rejected, transport, bad URL), Codex card usage + credits + plan through the tunnel with the$TOKEN$header andChatGPT-Account-Id, Claude card usage + one-shot plan lookup, dropped-account and expired-login error categories (and that upstream error bodies never reach the badge), reset claim through the tunnel with cooldown clear, hub-only cards minting ids while a local login wins and never enters multi-account mode, card order + default fan-out, store round-trip, id/label derivation.Full suite on
macos-26CI (fork run): 1385 tests, 3 skipped, 0 failures. Theapi-callenvelope shape (Codex usage, Claude usage, Claude profile) was also checked live against a local CLIProxyAPI hub with the same request headers the code sends.Screenshots
To follow.