Repository navigation
fix(usage): show Claude Agent quota from Claude Code's login - #1214
Conversation
The Usage tab showed "no usage data available" for sessions on OpenCode's
built-in Claude Agent provider, although the same subscription's quota showed
for opencode-claude's `claude-code` provider. The usage registry had no entry
for the Claude Agent's provider ID, so the route treated it as unsupported.
The running OpenCode service lists the provider as `claude-agent` ("Claude
Agent", package `aisdk:@opencode/claude-agent`). Its integration offers a
single external connection method, `claude-login` ("Claude Code login (claude
auth login)"), and it runs Claude Code inside the daemon through the Claude
Agent SDK, so it signs in exactly like `claude-code`: with Claude Code's own
login on the daemon host.
`claude-agent` is therefore an alias of the existing `claude-code` usage
reader instead of a second reader. The route already gives every provider ID
that resolves to that reader the Claude Code login from the daemon host
(session environment, WSL path translation, CLAUDE_CODE_OAUTH_TOKEN, then
Keychain or `.credentials.json`), so no credential logic is duplicated. Both
providers read the same login, so they share one snapshot and one rate-limit
backoff instead of polling Anthropic's usage endpoint twice.
Failures stay safe: without a Claude Code login on the daemon host the
provider reports "not configured"; OpenCode's Anthropic OAuth or a native
`claude-agent` credential entry is never used in its place, and the login is
never returned or logged.
Docs: PROVIDER_ACCOUNTS.md, the server README and the providers help page in
all ten locales name the Claude Agent provider next to `claude-code`.
Tests: service.test.ts resolves `claude-agent` to the Claude Code reader,
checks it ignores Anthropic/native entries and shares the `claude-code`
snapshot. The route test now runs for both `claude-code` and `claude-agent`:
not configured without a host login, the stored login and then the profile
token on the daemon host, with no secret in responses or logs. All three new
assertions fail without the alias.
pascalandr
left a comment
There was a problem hiding this comment.
Verdict: PASS — P0: 0, P1: 0, P2: 0, P3: 0.
Reviewed head 1651562a21dfda56f331872f36d3325171edac8a against origin/dev, including the PR description, complete diff, AGENTS.md, and the binding provider-account, Settings and public-help documentation. No actionable correctness, security or regression findings.
Contract and implementation checks
- Authentication premise: the PR identifies the external
claude-loginmethod and itsclaude auth logininstruction. The official OpenCode V2 provider documentation independently confirms that Claude Agent runs Claude Code on the server machine and uses its login. Reusing the host-login reader is justified for subscription OAuth. - Alias, identity and display:
packages/server/src/usage/providers/extra.ts:380–385registers both IDs on the same reader object.usage/service.ts:56–68shares the cache and pending request by resolved provider and credential identity; the reader's account fingerprint fences its fallback snapshot and cooldown. The response correctly retainsrequestedProviderId: "claude-agent", returns canonicalproviderId: "claude-code", and displaysproviderName: "Claude"; the existing Usage panel consumes that name and the quota windows without requiring the canonical ID to equal the requested ID. - Credential boundary:
server/routes/usage.ts:86–90resolves aliases before injecting the host credential and invokes that reader only for the Claude Code usage provider. It overwrites any projected nativeclaude-codeentry, including with an absent value when the host has no login.usage/claude-credential.ts:100–105and the reader use only that injected entry, never Anthropic or a nativeclaude-agentcredential. The route returns the bounded usage projection and redacts caught failures rather than logging or serializing credentials. - Host handling: the existing host adapter preserves session-environment/profile overrides, WSL path translation, token precedence, and local macOS Keychain/file behavior. Claude Agent takes exactly that same path. Official V2 documentation excludes Claude Agent from remote workspaces; this review does not claim new remote-workspace support.
- Documentation: all ten provider-help translations consistently identify both providers and preserve the same host-login precedence and separation from Anthropic OAuth. The existing limitation for API-key/cloud-backed Claude Code with a stored subscription login is explicitly acknowledged in the PR; it is not a regression introduced by this alias.
Validation performed
All commands ran in the supplied checkout, using Start-Process with redirected stdout/stderr read as UTF-8.
node --import tsx --test --test-force-exit packages/server/src/usage/service.test.ts packages/server/src/server/routes/usage.test.ts packages/server/src/usage/claude-credential.test.ts packages/server/src/usage/providers/extra.test.ts: 29 passed, 0 failed. The route tests exercise the real Fastify route, generated client and resolution chain with synthetic credentials.- Regression sensitivity: a temporary loader removed only the new alias in memory, leaving checkout files intact. The real service/route tests then yielded 20 passed, 3 failed, precisely at the new alias-resolution, Claude Agent service and Claude Agent route assertions.
- Additional synthetic checks against the real service passed: identical reader object; shared cross-alias 429 cooldown beyond the display-cache TTL; absent-login isolation; account-change fencing; and redacted transport-failure responses.
- Root
npm run typecheck: passed. Separate servertsc --noEmit -p packages/server/tsconfig.json: passed. node scripts/test-help.mjs: 31 passed, 0 failed, validating all 27 pages across all ten locales.git diff --check origin/dev...HEAD: passed; checkout remains clean.
No live OpenCode service calls, real credential reads, remote generation, repository edits, commits or pushes were performed. Platform behavior was checked through the existing implementation and isolated tests, not a live macOS/WSL deployment; the full server suite was not rerun in this review.
## Summary - OpenCode **2.2.5** becomes the **recommended** (qualified) runtime. The **2.2.3 minimum** and the 2.1.0 `@opencode/client`/`plugin`/`schema` pins stay: neither 2.2.4 nor 2.2.5 changes a contract CodeNomad consumes. - `RECOMMENDED_OPENCODE_VERSION` is 2.2.5, and the reviewed-publication shortcut in `contractProfile` lists 2.2.3 and 2.2.5; other versions, 2.2.4 included, keep negotiating their authenticated schema. The CI `latest` lane already resolves the latest stable CLI. - Help (all ten locales), READMEs, `CONTRIBUTING.md`, `dev-docs/OPENCODE_COMPATIBILITY.md` and the architecture skill state two separate versions again: minimum 2.2.3 with its reason, recommendation 2.2.5. ## Contract review (v2.2.3 → v2.2.4 → v2.2.5; 31 + 19 commits) Reviewed from the exact tags `v2.2.3` (`082ac6281f`), `v2.2.4` (`45898d0f85`) and `v2.2.5` (`9bbb8ce18c`), the published npm packages, and an authenticated OpenAPI dump from each official CLI running in its own sandbox. The [changelog](https://opencode.ai/changelog) has full notes for 2.2.4 and 2.2.5 (both 30 October); everything below was also checked against the commit log and source. CodeNomad side: `origin/dev` `605820669`. **Headline:** neither release changes a contract CodeNomad consumes. 2.2.4 adds opt-in **artifacts** (seven `/api/experimental/artifacts` operations, four tools, a plugin hook), **renamable persistent terminals**, and moves background-job recovery markers from `kv` into a new **`job` table**. 2.2.5 is a bug-fix release; its one schema change is that `compaction.buffer` accepts a percentage such as `"20%"`. The image tool contract adopted in #1209 (`experimental_image_generate`, on by default) is unchanged through 2.2.5, and still nothing writes `session_part`. - **Authenticated OpenAPI:** 134 → **138** → 138 paths, 162 → **169** → 169 operations, schemas 351 → 362 → 363. - **Added operations (2.2.4):** `GET /api/experimental/artifacts/providers`, `GET|POST /api/experimental/artifacts`, `GET|PATCH|DELETE /api/experimental/artifacts/{artifactID}`, `GET /api/experimental/artifacts/{artifactID}/view/*` ([#60351](anomalyco/opencode#60351)). None removed in either release. - **Changed operations (2.2.4):** `GET /api/event`, where the `types` filter enum gains `persistent-pty.updated` and `artifact.updated` (94 → 96 types, none removed). `PUT /api/experimental/persistent-pty/{ptyID}` can also rename (`title`; `null` clears it), `size` becomes optional, and a 501 `PtyFeatureUnsupportedError` is returned while an older terminal service can't rename ([#60329](anomalyco/opencode#60329)). - **Changed operations (2.2.5):** none. - **Consumed schemas:** same family selector as the 2.2.3 review, 97 schemas at every version. - 2.2.3 → 2.2.4: 95 byte-identical. The two that change, `PersistentPty.Info` (+ `userTitle`, nullable, required) and `PersistentPty.UpdateInput` (`size` optional, + `title`), are both additive. - 2.2.4 → 2.2.5: all 97 byte-identical. - `V2EventEncoded`, `Session.*`, `Form.*`, `Permission.*`, `Prompt*`, `Event.*`, `Location.*`, PTY/Shell are byte-identical from 2.2.3 to 2.2.5. - **`Config.InfoEncoded`:** 2.2.4 adds `experimental.artifacts` (boolean, opt-in). 2.2.5 turns `compaction.buffer` into `Config.Compaction.Percent | integer` ([#60647](anomalyco/opencode#60647)). `experimental.image_generate`, `experimental.media_blob` and `experimental.schedules` are unchanged. - **Admission:** every predicate in `compatibility/negotiate.ts` (unchanged on origin/dev) holds on 2.2.3, 2.2.4 and 2.2.5. `contractProfile` lists only `2.2.3` as reviewed, so 2.2.4/2.2.5 are admitted through authenticated contract recognition. - **Instance proxy:** the allowlist is unchanged on origin/dev. No added or changed route is proxied: artifacts and persistent PTYs are outside it. The proxied `GET /api/config` returns the additive config fields above. - **Published declarations** (2.2.3 → 2.2.5): - **Client:** 185 → **192** → 192 methods. 2.2.4 adds `experimental.artifacts.{providers,list,create,get,update,delete,view}`, the artifact and `PersistentPtyUpdated` types, and `PtyFeatureUnsupportedError`. It removes `createPtyClient`/`PtyConnectInput` from `@opencode/client/solid/pty`, which CodeNomad doesn't import. 2.2.5 adds `ConfigCompactionPercent`. - **Schema:** 2.2.4 adds the `artifact` module and `PersistentPty.Updated`; 2.2.5 adds `config/compaction` `Percent`. - **Plugin:** 2.2.4 adds `effect/artifact` and `promise/artifact` and `ctx.experimental.artifact` (`transform`, `reload`). 2.2.5 has no export changes. - **Typecheck:** the server and UI typecheck with **0 errors** against the 2.2.4 and 2.2.5 client/schema/plugin/effect declarations. The pinned 2.1.0 control is also clean. - **Host modules:** the bundles' host imports are identical to the 2.2.3 review. A probe plugin in an isolated **2.2.4** and **2.2.5** daemon resolves every module and binding. `runtime-modules.ts` is unchanged from v2.2.3 to v2.2.5. - **Host Effect:** stays **4.0.6** (`bun.lock` sha512 identical; published `dependencies.effect` 4.0.6). - **Persistent PTY binary:** the 2.2.4 and 2.2.5 CLIs ship `@opencode/pty` **0.4.0** (string `opencode-pty 0.4.0` in the Windows binary; 2.2.3: `0.3.3`). `process-daemon-v0.4.0` adds only terminal renaming ([#60324](anomalyco/opencode#60324)): an additive `rename` request and `features: ["rename"]` with an unchanged `PROTOCOL_VERSION`. CodeNomad only lists persistent PTYs (worktree deletion guard) and reads `status`/`cwd`. - **Private native services:** the keys (`LocationServiceMap`, `Form`, `Permission`, `Location`, `Job`, `Database`, `Session`, `Bus`, `Shell`) and the members CodeNomad calls are unchanged. The changes are additive: `Job.cancelSession` (2.2.4), `Permission.allows` (2.2.5; never asks, used by `edit` to decide whether to quote file lines), and `Session.remove` now calls `jobs.cancelSession`. The Missions recurrence clock calls `Job.get/start/cancel`. Its Job metadata carries no `sessionID`, so deleting a session doesn't cancel it. - **Storage:** one migration, `20261030054400_job` (2.2.4, [#60491](anomalyco/opencode#60491)). It creates `job`, copies every `kv` row `job.background/%` into it and deletes those `kv` rows. 2.2.5 adds none. - CodeNomad reads only its own `kv` keys (Missions, pruning receipts and claims), never `job.background/*`. - Native migration 2.2.3 → 2.2.4 passes. Every 2.2.4/2.2.5 fixture DB inspected holds the `job` table, **0** `job.background/` rows and no leftover `schedule:leader` lease. - **`session_part`:** still **not written**. `history.ts`/`projector.ts` are unchanged from v2.2.3 to v2.2.5, the projector still only rewrites existing part rows, and every inspected 2.2.4/2.2.5 fixture DB has **0** rows. The forward risk from the 2.2.3 review stands (Recommendations). - **Behavior changes checked** (plain-language list in [What users will notice](#what-users-will-notice)): - **Image tool** (#1209 contract): `image-generate.ts` is unchanged from v2.2.3 to v2.2.5. 2.2.4 refactors restart recovery into one `restartMessage` but keeps `metadata.source: "experimental_image_generate"`, `jobID`, `state`, `path` and the `<image id state>` notice text. Design companion, activation, content and image settings pass natively on 2.2.4. - **Schedules** (2.2.4, [#60478](anomalyco/opencode#60478), then `da87c475a7`): the loop now runs in every server process, including `opencode serve`, and elects a leader through a `kv` lease `schedule:leader` (claimed at boot, released when there are no active schedules). Firing stays opt-in (`experimental.schedules === true`). CodeNomad uses neither OpenCode schedules nor that key; Missions recurrence uses its own storage and the Job service. - **Sessions:** deleting a session now cancels its running background jobs (shell, image, subagent) and drops their markers (2.2.4). That is the intended upstream cleanup; CodeNomad's session deletions (blank-session cleanup, temporary workspaces) get it automatically. - **Events:** `persistent-pty.updated` and `artifact.updated` reach CodeNomad's shared event relay. The relay routes generically (`instance-events.ts`), the 2.1.0 client's SSE reader doesn't validate types, and the UI handles neither type. The native relay suite passes on 2.2.4. - **Tools** (2.2.5): a model call to `bash` runs as `shell` with shell permissions, and the result carries a note ([#60687](anomalyco/opencode#60687)). CodeNomad already groups and renders `bash` and `shell` alike (`message-part-grouping.ts:48`, `tool-call/utils.ts`). `read`/`edit` failure texts are richer ([#60688](anomalyco/opencode#60688), [#60689](anomalyco/opencode#60689)). - **Compaction** (2.2.5): the prompt is capped at the context window when a catalog's input limit is larger ([#60660](anomalyco/opencode#60660)), and `compaction.buffer` may be `"N%"`. CodeNomad never reads or writes `compaction.buffer`. LiteLLM context errors now trigger compaction ([#60692](anomalyco/opencode#60692)). - **Reasoning replay** (2.2.5, [#60498](anomalyco/opencode#60498)): reasoning is no longer re-sent as plain text after a model switch, and interrupted or errored reasoning is dropped from the request. This changes provider requests only; stored transcripts and `Session.Message.*` are byte-identical. - **MCP** (2.2.5): stdio messages over 10 MiB no longer disconnect a server ([#60694](anomalyco/opencode#60694)), and an idle Location no longer restarts its MCP servers right after shutting down ([#60668](anomalyco/opencode#60668)). - **Providers:** a Console-supplied provider can now be overridden by user, project and remote config (2.2.4). The Claude Agent provider only replaces Claude Code's `/login` hint with `claude auth login` in its errors ([#60592](anomalyco/opencode#60592)); the guided setup ([#60603](anomalyco/opencode#60603)) is OpenCode Desktop only. The provider ID (`Provider.ID.claudeAgent`) and its use of Claude Code's own login are unchanged, so CodeNomad's `claude-agent` quota reader (#1214) is unaffected. - **Service lifecycle:** the CLI now adds `127.0.0.1,localhost,::1` to `NO_PROXY`/`no_proxy` for itself and its children ([#60441](anomalyco/opencode#60441)), so loopback traffic from daemon-hosted code, CodeNomad's plugins included, bypasses environment proxies. CodeNomad sets no proxy variables. - **Code Mode, Forms, permission prompts, media blobs:** no source changes from v2.2.3 to v2.2.5 (`packages/codemode` only bumps its version). The Code Mode run-to-completion regression passes on 2.2.4: `{ total: 2000, beforeAwait: 1000, count: 1000 }`. - **`@opencode/ai`:** one `ai` object for Promise and Effect ([#60516](anomalyco/opencode#60516); left out of the changelog by [#60631](anomalyco/opencode#60631)). CodeNomad doesn't import `@opencode/ai`. - Desktop/TUI-only changes (desktop terminals on persistent PTYs, base-branch and worktree shortcuts, quote sending, flat inputs, palette ordering) don't affect CodeNomad. One indirect effect follows. - **Worktree deletion:** OpenCode Desktop terminals now live as persistent PTYs that survive restarts ([#60346](anomalyco/opencode#60346)). CodeNomad's guard (`routes/worktrees.ts`, "Running persistent PTY blocks deletion: <id>") will therefore refuse more often for users who also open terminals in OpenCode Desktop. The behavior is correct, but the message names the PTY ID rather than the terminal's title. **Verdict:** - The **2.1.0 client/plugin pins can stay**. Bumping them would bring only artifacts, PTY renaming and a config type, none of which CodeNomad consumes. - The **2.2.3 minimum has no reason to move**. No consumed HTTP, plugin, private-service or storage contract broke in 2.2.4 or 2.2.5. - **Recommend 2.2.5.** It is admitted today through contract recognition. Recommending it is CodeNomad-side bookkeeping: `RECOMMENDED_OPENCODE_VERSION` (`runtime-support.ts`), the reviewed-version check in `contractProfile` (`compatibility/runtime.ts`), the version texts in docs and help, and CI's qualification target. This is subject to the full native suite on the exact 2.2.5 CLI, run separately. - **No CodeNomad bug found** in 2.2.3 → 2.2.5. Risks: the `session_part` forward risk (unchanged) and the more frequent worktree-deletion refusal (UX). **Not verified here:** - the full native suite on 2.2.5: only a host-module probe ran natively on 2.2.5, and everything else for 2.2.5 is source and OpenAPI review (Appendix I); - the 2.2.4 recurring Missions journey (`test-recurring-simple-native` ABCDGELFWQN), which was interrupted by a server restart; - the `kv` → `job` migration with a real pending background marker: only the empty case ran, and upstream `job.test.ts` covers the copy; - whether a `bash` call is stored as `bash` or `shell` (source suggests the model's name is kept; CodeNomad renders both); - artifacts, Claude Agent and MCP stdio framing at runtime (source only); - macOS/Linux. --- ## What users will notice **OpenCode 2.2.4** - **Persistent desktop terminals:** OpenCode Desktop terminals belong to the session, keep their scrollback across server restarts, stay in sync with the TUI and other windows, and can be renamed. Renamed terminals keep their names. - **Artifacts (opt-in):** with `"experimental": { "artifacts": true }`, agents can publish, update and serve HTML or static artifacts (`artifact_create`, `artifact_read`, `artifact_update`, `artifact_delete`) through a built-in local provider, which stores files under OpenCode's data folder, or a plugin-provided one. - **Schedules:** enabled schedules also fire under `opencode serve`, and only once when several OpenCode processes share a database. They stay off unless `experimental.schedules` is `true`. - **Claude Agent:** OpenCode Desktop guides installation, `claude auth login` and connection checking. Error messages now say `claude auth login` instead of `/login`. - **Config:** user, project and remote configuration can override Console-supplied provider names, limits, variants, settings and headers. - **Networking:** requests to the local OpenCode service no longer go through `HTTP(S)_PROXY`. - **Sessions:** deleting a session also stops its running background work, such as shells, image generations and subagents. - **Desktop/TUI:** base-branch shortcut, simpler location popover, faster Markdown streaming and various fixes. **OpenCode 2.2.5** - **Compaction:** `"compaction": { "buffer": "20%" }` keeps a share of each model's context free; token counts still work. Compaction no longer overfills models whose catalog input limit exceeds their context window, and LiteLLM context errors trigger compaction instead of stopping. - **Tools:** a model calling `bash` gets `shell` (with shell permissions) instead of an error. `read` names the missing folder, and `edit` shows the closest lines when `oldString` isn't found. - **Reasoning:** switching models or resuming an interrupted reply no longer resends reasoning as plain text, which some providers rejected. - **MCP:** large stdio messages (over 10 MiB) no longer disconnect a server, and idle locations don't immediately restart their MCP servers. - **Desktop/TUI:** worktree and base-branch shortcuts, a shell-mode toggle, sending a single quote from its popup, and MCP servers removed from the connect menu. ## Follow-ups (outside this PR) - Hardening for `session_part` (independent of this upgrade; 2.2.5 still writes no rows): make the direct `session_message.data.content` readers and the pruning transaction fail safe when `session_part` has rows for the target messages. - Optional UX: when the worktree deletion guard finds a running persistent PTY, name it by `userTitle ?? title` (2.2.4+) and say it may be an OpenCode Desktop terminal. - Any future reader of `compaction.buffer` must accept `"N%"` as well as a token count. ## Isolated Windows qualification Base: dev `605820669`; Node 25.2.1 (local; CI runs the pinned 24.20.0); exact official CLI **2.2.5**; locked client/plugin **2.1.0**; `CODENOMAD_NATIVE_FIXTURE_PARENT` outside the user profile. - **Native suites on 2.2.5, all passing:** Code Mode jobs, plugin runtime, automation, session pruning (history, navigation, media blobs, proxy, session images), Location/worktrees/event relay, permission receipts, Git init/degraded, Missions (contract, family control, native, trajectory) and all 11 recurring journeys, sessions (environment, fork, aside, interrupt, lifecycle, blank cleanup, compaction isolation, prompt skills), providers (usage, accounts, account selection), service usage, web search settings, plugin packages, output limit, Promise-tool failure, subagent depth, temporary workspaces, Design companion/activation/content, image settings, history migrations from 2.1.2/2.2.3/2.2.4, shared install of the 2.2.3 minimum. - **Installer suites after the bump:** upgrade (installed `opencode v2.2.5`) and legacy replacement (target `2.2.5`) install the new recommendation and pass. - **Builds and checks after the change:** server build, native plugin builds and root typecheck clean; server **2,840 passed, 9 skipped, 1 cancelled** (`index.test.ts` shutdown test timed out under full-suite load; **4/4** alone); runtime-support/transport/update **35/35**; browser `opencode-setup` **34/34**; ten-locale help **31/31**.
Summary
The Usage tab showed no quota for sessions on OpenCode's built-in Claude Agent provider, while the same subscription's quota showed for opencode-claude's
claude-codeprovider. This adds the Claude Agent to the existing Claude Code usage reader.Root cause
The usage registry had no entry for the Claude Agent's provider ID, so
/api/usage/claude-agentresolved to "unsupported".Provider identity, checked read-only against the running OpenCode service (
GET /api/provider) and its bundled@opencode/claude-agentintegration:claude-agent, name "Claude Agent", packageaisdk:@opencode/claude-agent, integrationclaude-agent;claude-login, typeexternal, labelled "Claude Code login (claude auth login)". Its status reports "Claude Code is not logged in. Runclaude auth login" when Claude Code has no login;claude-code.Change
usage/providers/extra.ts:claude-agentis an alias of theclaude-codereader (createClaudeProvider), not a second reader. Both providers read one login, so they share one snapshot and one rate-limit backoff and don't poll Anthropic's usage endpoint twice.server/routes/usage.ts: no logic change. Every provider ID that resolves to that reader already gets the Claude Code login from the daemon host (session environment, WSL path translation,CLAUDE_CODE_OAUTH_TOKEN, then Keychain or.credentials.json). The comments now say so.dev-docs/PROVIDER_ACCOUNTS.md,packages/server/README.mdand the providers help page (Usage section) in all ten locales name the Claude Agent provider next toclaude-code.Failures stay safe. Without a Claude Code login on the daemon host the provider reports "not configured". It never falls back to OpenCode's Anthropic OAuth or to a native
claude-agentcredential entry, and the login is never returned or logged.Tests
usage/service.test.ts:claude-agentresolves to the Claude Code reader. It ignores Anthropic and native entries and shares theclaude-codesnapshot (one upstream request).server/routes/usage.test.ts: the daemon-host test now runs for bothclaude-codeandclaude-agent: not configured without a host login, then the stored login, then the profile token outranking it. No secret appears in responses or logs.Validation
npm run typecheck(root) and the servertsc --noEmit: passnode --import tsx --test "packages/server/src/**/*.test.ts": 2847 tests, 2837 pass, 0 fail, 9 skipped, 1 cancelled. The cancelled one isindex.test.ts's piped-process shutdown, which timed out at 5 s while typecheck and the help build were running; rerun alone it passes 4/4.node scripts/test-help.mjs(all locales): 31/31 passNo UI change: the panel already requests usage for the session's provider ID and shows the returned provider name.
Known limitation, unchanged
Like
claude-code, this reads Claude Code's OAuth subscription login. If Claude Code is set up to use an API key or Bedrock/Vertex instead while a stored subscription login also exists, Usage shows that subscription's windows.