[Bug]: Claude instances authenticated with CLAUDE_CODE_OAUTH_TOKEN (claude setup-token) never appear in Usage → Limits, although their sessions stream usable rate-limit windows#24114

opened20d agobyLLiri-s29

Before submitting

  • I searched existing issues and did not find a duplicate.
  • I included enough detail to reproduce or investigate the problem.

Area

apps/server

Steps to reproduce

  1. Create a token with claude setup-token and a wrapper script that exports CLAUDE_CODE_OAUTH_TOKEN and execs claude. Register the wrapper as a Claude provider instance (binaryPath). Repeat for a second account.
  2. Use both instances normally.
  3. Open Usage → Limits.

Expected behavior

Both accounts show session and weekly bars, or at least a notice saying why they cannot be read.

Actual behavior

Neither account is listed and there is no notice. The boot-time get_usage probe returns rate_limits_available: false for a setup-token session (confirmed by caitlon in #13053), so claudeUsageResponseToLimits marks the instance "unsupported" and collectLimitAccounts and collectLimitNotices both skip it. #18624 fixed the rate_limits_available: true + rate_limits: null shape and explicitly left this case out.

The data is available anyway. A turn on such an instance streams rate_limit_info with unifiedWindows, for example {"five_hour":{"utilization":0.2,"resetsAt":1792759800},"seven_day":{"utilization":0.59,"resetsAt":1792760400}} captured today from claude -p ... --output-format stream-json --verbose under a setup-token wrapper. T3 discards streamed windows for an instance marked unsupported.

Suggested fix: treat rate_limits_available: false as "probe unsupported, streamed windows allowed" when apiKeySource is "none" and the token is an OAuth token: show the instance in Limits as soon as a streamed rate_limit_info arrives, and keep the last streamed reading between turns. Keep "unsupported" only for API-key accounts.

Impact: Anyone running several subscriptions through setup-token wrappers (the documented way to use Claude Code on a headless or multi-account machine) has no limit visibility in T3 and cannot pick the account with headroom.

Impact

Major degradation or frequent failure

Version or commit

T3 Code Nightly 0.1.3-nightly.20261023.3553

Environment

macOS (Darwin 25.6.0, arm64), Claude Code CLI 2.1.309, three Claude subscription accounts each behind a setup-token wrapper script registered as its own provider instance.

Logs or stack traces

shell
1Stream line from a setup-token session (fields other than the rate-limit window omitted):
2"rate_limit_info":{"status":"allowed","rateLimitType":"five_hour","unifiedWindows":{"five_hour":{"utilization":0.2,"resetsAt":1792759800},"seven_day":{"utilization":0.59,"resetsAt":1792760400}}}

Screenshots, recordings, or supporting files

No response

Workaround

No response

Synced from GitHub

Still reproduces on T3 Code Nightly 0.1.9-nightly.20261110.4465 (macOS arm64) with Claude Code 2.1.312, three setup-token accounts behind wrapper scripts.

Why get_usage says rate_limits_available: false. When auth comes from CLAUDE_CODE_OAUTH_TOKEN, Claude Code gives the token the scopes in CLAUDE_CODE_OAUTH_SCOPES, or ["user:inference"] if that is unset. get_usage only reads plan limits when the scopes include user:profile. The default is the same in 2.1.322.

The obvious workaround doesn't help. Setting CLAUDE_CODE_OAUTH_SCOPES="user:inference user:profile" in the wrapper flips get_usage to rate_limits_available: true, but rate_limits stays null. All three tokens get HTTP 429 from /api/oauth/usage with retry-after: 3596 (a bogus token gets 401, so they do authenticate). T3 then marks the probe probeFailed, and the streamed windows are still dropped, because the event only has unifiedWindows and no top-level utilization:

json
1"rate_limit_info":{"status":"allowed","rateLimitType":"seven_day","unifiedWindows":{"seven_day":{"utilization":0.03,"resetsAt":1794574800,"status":"allowed"}}}

So a user can't work around this. It needs both parts of #24128: the setup-token probeFailed path and the unifiedWindows parsing.