[BUG] CLAUDE_CODE_OAUTH_TOKEN silently overrides an active Max subscription → sessions run as "Claude API" (metered) with no warning
Preflight Checklist
- [x] I have searched existing issues and believe this is a distinct, cleanly reproducible case (closest related: #70124, #77376, #62338, #45390 — see "Related" below for why this is not a duplicate)
- [x] This is a single bug report
- [x] I am using the latest version of Claude Code
What's Wrong?
If a CLAUDE_CODE_OAUTH_TOKEN is present in the environment, Claude Code silently ignores an active, logged-in Max subscription and runs the session in "Claude API" (metered) mode — with no warning, no confirmation, and nothing in the normal flow that tells you your billing source just changed.
The account was logged in to a Max subscription via /login (credentials in the macOS Keychain). But because a CLAUDE_CODE_OAUTH_TOKEN was exported in a shell startup file (~/.zshenv), every session picked up that token and ran as Claude API instead of Max. The only visible symptom is the small · Claude API label in the startup banner — which is easy to read as a product name, not as "you are now on pay-as-you-go metered billing instead of your subscription."
This is a billing-safety problem: the switch from subscription to metered API billing happens silently and globally, and it persisted across many sessions before it was noticed. Changing the model, toggling /extra-usage, /logout + re-login, and removing [1m] from the model flag all had no effect — because none of them touch the real cause (the env token). The behavior is 100% determined by whether that one environment variable is set.
What Should Happen?
- When a
CLAUDE_CODE_OAUTH_TOKENoverrides an available subscription login and causes the session to bill as API/metered instead of the subscription, Claude Code should show an explicit, unmissable warning at startup (and ideally in/status), not a two-word· Claude APIlabel. /statusshould clearly state the billing source (subscription vs. metered API) and which credential (env token vs. Keychain login) is in effect, so a user can tell at a glance why they're not on their subscription.- More generally: any transition from subscription billing to metered API billing should require a visible acknowledgement, consistent with the concerns already raised in #77376 and #62338.
Steps to Reproduce
- Log in to a Max subscription via
/login(credentials stored in the macOS Keychain). - Export a
CLAUDE_CODE_OAUTH_TOKENin the environment (in my case in~/.zshenv, so it is injected into every shell). - Start
claude. The banner shows· Claude API. The session runs as metered API, not against the Max subscription — with no warning that this happened. - In the same setup, run with the env token removed for that invocation:
``zsh`
unset CLAUDE_CODE_OAUTH_TOKEN
claude
/status` reports the Max plan.
Now the banner shows **Claude Max**, and
Result: token present → Claude API (metered). Token absent → Claude Max (subscription). Nothing in the interactive experience flags that the presence of the token silently moved billing off the subscription.
Note: I have not yet reconciled the exact metered charges in the Console — I'm reporting the observed billing-mode switch (banner + /status) and the total absence of any warning. If Anthropic can confirm from telemetry whether these sessions were charged as metered API vs. subscription, that would help.
Environment
- Platform: macOS (Darwin 25.5.0)
- Claude Code: v2.1.216
- Plan: Claude Max
- Auth:
/login(Keychain) present andCLAUDE_CODE_OAUTH_TOKENset in~/.zshenv
Related (why this isn't a duplicate)
- #70124 — documents the opposite direction (stored
/logincreds beating a validCLAUDE_CODE_OAUTH_TOKEN) and cites the documented precedence where the env token ranks above subscription/login. This report is the same precedence machinery but with the billing-safety consequence: the env token wins and the subscription is silently bypassed into metered billing. - #77376 / #62338 — silent crossover into API billing with no visible warning; those are triggered by
[1m]/ general API-key detection. Here the trigger is specificallyCLAUDE_CODE_OAUTH_TOKENoverriding an active subscription, and it reproduces on a non-[1m]standard model. - #45390 — 1M/extra-usage gating on Max; not the cause here (reproduced on standard context).
The common thread across all of these: billing mode can change from subscription to metered without any clear, visible warning. Please make that transition impossible to miss.
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗