fix(server): restore Claude subscription usage through proxies#12069
Claude subscription usage requests forwarded through CLIProxyAPI could receive an upstream 429 and leave Limits without Claude windows. The existing read-only Claude OAuth usage request now includes User-Agent: claude-code/2.1.273 in the header forwarded upstream. Management authentication, Codex requests, quota calculation and credit consumption are unchanged.
Thanks to @Kanaliseren for the original diagnosis, fix and reported 429-to-200 comparison in #12069. Contributor history is preserved, with main integrated by merge. The takeover folds the duplicate header test into the existing Claude window-mapping fixture, reducing the focused file from 19 cases to 18. The fixture rejects requests missing the Claude client header and checks the resulting mapped windows, without pinning its assertion to a version string.
Validation at ca30fa5: all 18 focused tests, server typecheck, changed-file lint and formatting passed. Earlier red/green proof removed the header and produced one failed mapping test with 17 passing; restoring it returned all 18 to green. The affected source/test blobs are unchanged by the merge. Fresh independent full Claude Opus 5.5 and GPT-6.1 Sol reviews found no code blockers.
The fixture validates serialized header delivery and existing response mapping, not a real proxy hub or Anthropic acceptance. The live 429-to-200 result is the contributor's report, not independently repeated account proof. Upstream acceptance of this fixed client identifier can change. This is headless request/response behavior, so screenshots do not apply. Tests and typecheck used this worktree's dependencies; lint may have resolved shared plugin dependencies through an ignored sibling-worktree link. No tracked dependency change is included.
Current-head CI and the existing human usage/metering approval remain landing gates; this publication does not grant either.
Implementation: Claude Fable 5.1; tests and independent full reviews: Claude Opus 5.5 and GPT-6.1 Sol through T3 Code, using Claude Code and Codex.
Checks
Added 1 commit
- fix(server): restore Claude subscription usage through proxiesfddb83c
Approvability
Verdict: Needs Human Approval
Macroscope's review found this PR requires human approval — This focused fix changes the production Claude OAuth usage request so subscription limits are returned through proxies instead of being rejected, with a test covering the required header. Because it affects subscription usage/metering behavior, the change warrants human review despite its small scope.
You can add or adjust custom eligibility rules. Learn more.
No actionable comments were generated in the recent review. 🎉
ℹ️ Recent review info
⚙️ Run configuration
- Configuration used: Path: .coderabbit.config.ts
- Review profile: CHILL
- Plan: Advanced
- Run ID:
746de8b3-c62a-4bf3-87f0-1f44c047d78f
📥 Commits
Reviewing files that changed from the base of the PR and between fddb83c5d0e2441d3acddd11ebc8ee5c86befc29 and eee96ed5c92a5d622b376394822dd2073a8b5819.
📒 Files selected for processing: 2
apps/server/src/usage/cliproxyApi.test.tsapps/server/src/usage/cliproxyApi.ts
Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 5 remain after this review.
📝 Walkthrough
The Claude usage request now includes
User-Agent: claude-code/2.1.273. The test mock returns HTTP 200 only when the request’s User-Agent starts withclaude-code/; otherwise, it returns HTTP 429.Changes: Claude usage request handling
Layer / File(s) Summary Usage request and validation
apps/server/src/usage/cliproxyApi.ts,apps/server/src/usage/cliproxyApi.test.tsThe Claude API call includes the Claude Code User-Agent. The test mock checks its prefix and returns HTTP 200 or 429 based on whether it matches. Priority: ➖ Normal
Estimated code review effort: 2 (Simple) | ~10 minutes
Change: Bug fix
Suggested reviewers:
juliusmarminge
Merge Risk: ⚪ Minimal · up to eee96
The Claude usage request now identifies itself as Claude Code, and its test checks that the header is present. No merge-blocking issue is evident.
Security architecture risk: ⚪ Minimal · up to eee96
The change adds a fixed client identifier to existing Claude usage requests. It does not change account selection, credentials, destinations, or access permissions. No introduced or worsened security concern was identified.
Retained concerns No architecture-level concerns identified.
Security review details
Security Blast Radius
- inferred — The changed behavior is limited to usage reads for enabled Claude accounts returned by an already configured hub. The fixed identifier adds no caller-controlled destination, account selector, or credential.
Trust Boundaries and Controls
- observed — The existing two-hop credential structure remains: the management key authenticates the server-to-hub request, while the upstream request body retains the Bearer $TOKEN$ placeholder and selected auth_index. The added User-Agent does not replace either credential mechanism in this source.
Resilience and Maintainability Implications
- observed — Existing failure containment remains in place: management requests time out after 15 seconds, non-success upstream statuses become errors, and failed account reads produce unavailable usage limits. The new identifier does not add retries or bypass response-status checks.
Pre-merge checks: Passed 4
Check name Status Explanation Linked Issues check Passed Check skipped because no linked issues were found for this pull request. Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request. Title check Passed The title clearly and concisely describes the main change: restoring Claude subscription usage through proxies. Description check Passed The description provides the problem, implementation, scope context, focused verification results, limitations, and agent details. The required template sections are covered in prose, although they ar… Full details: Description check
Explanation
The description provides the problem, implementation, scope context, focused verification results, limitations, and agent details. The required template sections are covered in prose, although they are not explicitly labeled.
✨ Finishing Touches
🧪 Generate unit tests (beta)
- Create a new PR
Comment @coderabbitai help to get the list of available commands.
Taking over this one. I’ll reduce the tests to the useful coverage, update the implementation against current main, and verify it before publishing the changes.
Added 4 commits
I checked the production usage module from base 10f7db7 before the proposed ca30fa5 version against the same local management HTTP fixture. Under the fixture’s modeled rule (429 without a Claude Code User-Agent), base produced probeFailed; the proposed version sent claude-code/2.1.273 and mapped the five-hour and seven-day windows. Codex request headers and an independent account’s error isolation were preserved. The focused suite passed 19/19, including the added runtime fixture.
This verifies local request shape and mapping, not real CLIProxyAPI forwarding or Anthropic acceptance. Dependencies were reused from another checkout whose full lockfile differs; exact source hashes and dependency provenance are included. The reported live 429-to-200 result remains independently unverified, and the existing human usage/metering approval gate remains.
Fixture, serialized before/after requests and outputs, raw test logs, and limitations. No live credentials or external quota were used.