[BUG] CLAUDE_CODE_OAUTH_TOKEN silently overrides an active Max subscription → sessions run as "Claude API" (metered) with no warning

Status Open
Maintainer reply None cached
Activity 1 comment · opened Jul 20, 2026

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_TOKEN overrides 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 API label.
  • /status should 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

  1. Log in to a Max subscription via /login (credentials stored in the macOS Keychain).
  2. Export a CLAUDE_CODE_OAUTH_TOKEN in the environment (in my case in ~/.zshenv, so it is injected into every shell).
  3. Start claude. The banner shows · Claude API. The session runs as metered API, not against the Max subscription — with no warning that this happened.
  4. In the same setup, run with the env token removed for that invocation:

``zsh
unset CLAUDE_CODE_OAUTH_TOKEN
claude
`
Now the banner shows **Claude Max**, and
/status` reports the Max plan.

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 and CLAUDE_CODE_OAUTH_TOKEN set in ~/.zshenv

Related (why this isn't a duplicate)

  • #70124 — documents the opposite direction (stored /login creds beating a valid CLAUDE_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 specifically CLAUDE_CODE_OAUTH_TOKEN overriding 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.

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗