CLAUDE LABJP
2.1.278 — The auto mode classifier now runs server-side by default on the Claude API, Enterprise, Bedrock, Vertex and Foundry. You are not billed for the classifier, and /status gained an Auto mode server lineTASKOUT — The TaskOutput tool is gone. taskOutputMaxChars and TASK_MAX_OUTPUT_LENGTH no longer do anything, and background output is read with Read instead10/07 — The old management-configuration key spellings are accepted until noon PT on October 7, seventeen days from now. After that, entries that still use them stop working until you rewrite themBUNPANIC — Reports are coming in of the newest build crashing on launch alone. Earlier builds still run on the same machine, which points at the release rather than the environmentNEW — Deciding what belongs in Cowork and what belongs in Claude Code, using the approval boundary as the lineSONNET4.5 — A date in a deprecation table is a floor, not an end date. Sonnet 4.5 is still active and no deprecation notice has been posted2.1.278 — The auto mode classifier now runs server-side by default on the Claude API, Enterprise, Bedrock, Vertex and Foundry. You are not billed for the classifier, and /status gained an Auto mode server lineTASKOUT — The TaskOutput tool is gone. taskOutputMaxChars and TASK_MAX_OUTPUT_LENGTH no longer do anything, and background output is read with Read instead10/07 — The old management-configuration key spellings are accepted until noon PT on October 7, seventeen days from now. After that, entries that still use them stop working until you rewrite themBUNPANIC — Reports are coming in of the newest build crashing on launch alone. Earlier builds still run on the same machine, which points at the release rather than the environmentNEW — Deciding what belongs in Cowork and what belongs in Claude Code, using the approval boundary as the lineSONNET4.5 — A date in a deprecation table is a floor, not an end date. Sonnet 4.5 is still active and no deprecation notice has been posted
Articles/Claude Code
Claude Code/2026-09-20Intermediate

I Was Paying for Pro and Still Getting Billed by the Console

Your subscription and your API usage are two separate ledgers, and Claude Code will happily run on either one. Which credential wins is decided by a precedence list where your login sits dead last. Here is how to read status, and why unattended runs answer differently.

Claude Code255authentication5cost management8environment variables4indie development25

At the start of the month I opened the Console usage page and found a metered line that had not been there before. The amount was smaller than a cup of coffee. What stayed with me was that I could not account for it at all.

My Pro invoice arrives separately. So who put that line there?

An environment variable I had set once, months earlier, to try something out — and never removed.

Two ledgers, and Claude Code will run on either

Your claude.ai subscription (Pro, Max, Team, Enterprise) and the pay-as-you-go usage on an API key from the Console are separate ledgers by design. Holding one of them does not make the other free.

Claude Code accepts credentials from both. That is the part that slips past people: finishing a browser login does not, by itself, decide that your subscription is what gets used.

The plan you pay for does not decide the bill. The credential currently selected does.

If what you actually need is help choosing a plan, I keep that separate in the Claude plan cheat sheet for indie developers. Here I want to stay on one narrow problem: the plan you hold not being the plan you use.

One line in status tells you which wallet is open

Type /status at the Claude Code prompt and look at the authentication section for the Login method row. When both a login and an API key are present, Claude Code marks the credential that is not in use, so a single glance settles the question.

If a profile is selected instead — the kind written by ant auth login, or by signing in to a Console account without creating a key — the row is replaced by a Profile row. The row changing its own name is the signal that you came in through a different door.

One more detail worth knowing: if the saved login has expired, that row reads as expired and shows the organization and email address stored alongside it. That row needs Claude Code v2.1.210 or later, and from v2.1.203 you also get a startup warning three days before expiry (five days, on releases before v2.1.217).

To check from the terminal alone, close Claude Code and run one of these:

# macOS / Linux
echo $ANTHROPIC_API_KEY
 
# Windows PowerShell
echo $env:ANTHROPIC_API_KEY
 
# Windows Command Prompt
echo %ANTHROPIC_API_KEY%

Empty output means the variable is unset. If a string comes back, that key is holding your bill.

Seven levels of precedence, and your login is the last one

When several credentials exist, Claude Code walks the list from the top and stops at the first one it finds.

RankCredentialTypical use
1Cloud provider (CLAUDE_CODE_USE_BEDROCK / _VERTEX / _FOUNDRY)Bedrock, Vertex, Foundry
2ANTHROPIC_AUTH_TOKENGateways and proxies using bearer auth
3ANTHROPIC_API_KEYDirect API access with a Console key
4apiKeyHelper outputShort-lived or rotating credentials
5CLAUDE_CODE_OAUTH_TOKENCI, or anywhere a browser login is impossible
6Profile and federation credentialsThe ant CLI, Workload Identity Federation
7Subscription OAuth from /loginThe default for Pro, Max, Team, Enterprise

Writing that table out is what finally made it click for me. The subscription is not first — it is last. Leave anything at all above it and your login stays visible on screen while the charges quietly route somewhere else.

In interactive mode you are asked once to approve a key found in your environment, and your answer is remembered. To change it later, use the "Use custom API key" toggle in /config, which only appears while the variable is actually set.

Only the unattended runs were answering differently

This is the part that cost me two days.

As an indie developer I let a cron-invoked shell handle the routine work — updating the Lab sites, sorting source material for my wallpaper apps. That day I opened /status in my own terminal, confirmed it was running on the subscription, and closed it satisfied.

The metered line showed up again the following month.

In non-interactive mode (-p) there is no approval prompt at all. If a key is present, it is used — the "no thanks" I had clicked in an interactive session does not reach there. A shell started by cron has no interactive screen, so the /status I had been reading never once represented what the unattended side was doing.

It took a second invoice before I understood that I had been checking the wrong surface entirely.

Reassurance gathered on an interactive screen does not travel to an unattended run. Let the unattended run identify itself, on its own terms.

A wrapper that records one line before launching gives you the answer by morning:

#!/bin/bash
# Record which credential this run will use, before launching
set -euo pipefail
 
LOG="${HOME}/claude-runs/$(date +%F).tsv"
mkdir -p "$(dirname "$LOG")"
 
if [ -n "${CLAUDE_CODE_USE_BEDROCK:-}${CLAUDE_CODE_USE_VERTEX:-}${CLAUDE_CODE_USE_FOUNDRY:-}" ]; then
  SRC="cloud-provider"
elif [ -n "${ANTHROPIC_AUTH_TOKEN:-}" ]; then
  SRC="auth-token"
elif [ -n "${ANTHROPIC_API_KEY:-}" ]; then
  SRC="api-key(metered)"
elif [ -n "${CLAUDE_CODE_OAUTH_TOKEN:-}" ]; then
  SRC="oauth-token(subscription)"
else
  SRC="login(subscription)"
fi
 
printf '%s\t%s\t%s\n' "$(date -Iseconds)" "$SRC" "$*" >> "$LOG"
claude -p "$*"

Running it here leaves this behind:

2026-09-20T15:02:11+09:00	api-key(metered)	Tighten the headings in this draft

The branches are ordered to match the precedence table exactly. Reorder them and, on a machine that has both a token and a key, the log drifts away from reality — and a log that disagrees with reality is worse than no log at all.

For the separate problem of unattended runs going missing rather than going expensive, I dug into that from another angle in the reconciliation that caught half my scheduled runs vanishing.

Where the key you deleted comes back from

unset ANTHROPIC_API_KEY only affects the terminal you are standing in. If tomorrow morning is metered again, the key is coming back from somewhere else.

Where it livesScopeHow to remove it
~/.zshrc / ~/.bash_profileEvery new shellDelete the line and re-source the file
Windows user environment variablesEvery process for that userRemove it in System Properties, restart the terminal
The env block of a settings fileSessions that settings file coversDelete the key from the settings file
CLAUDE_CODE_OAUTH_TOKENRe-read in every new sessionRemove it from your shell profile
A profile under configs/Every surface that reads profiles/logout or ant auth logout

CLAUDE_CODE_OAUTH_TOKEN deserves a footnote. It authenticates against your subscription, so in billing terms it does not send you to metered usage. But running /login while it sits in your shell profile switches only the current session; every new session reads the variable again. The confusion feels identical even though the bill does not change.

Surfaces differ too, and knowing that saves some guessing. Claude Desktop and cloud sessions read neither these environment variables nor apiKeyHelper. One machine running metered in the terminal and subscription on the desktop is an ordinary state, not a bug.

What to do today

Open Claude Code once and read a single row: Login method, or Profile if that is what you see. Whichever one is not marked is the account currently receiving your charges.

Adding that one glance to my start-of-month routine is what made opening the Console usage page stop feeling like bad news. Thank you for reading.

Share

Thank You for Reading

Claude Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • Copy-paste ready implementation code
  • New advanced guides published daily
  • $5/mo or $15 for lifetime access
View Membership →

If you found this article helpful, a small tip ($1.50) would mean a lot to us. Your support helps keep this site ad-free and covers server and hosting costs.

Related Articles

Claude Code2026-06-20
Keep MCP Connector Authorization in One Place — A Solo Dev Design That Survives Growing Integrations
When Claude chat, Claude Code, and Cowork each configure the same MCP connector separately, their authorization drifts apart and breaks silently. Here is how to borrow the managed-connector idea of 'provision once, reuse everywhere' as an indie developer.
Claude Code2026-06-17
The Day a Billing Change Got Reversed at the Last Minute — Designing a Reversible Pipeline So You Don't Rewrite in a Panic
A billing change due to take effect on June 15 was retracted at the eleventh hour. From the position of someone who had literally logged 'effective today' the night before, here is why I didn't have to scramble to rewrite my headless stages, and how to build a pipeline that survives reversals and delays — with working code.
Claude Code2026-09-12
My overnight crawl never came back, and the reason was that WebFetch had no ceiling on how long it would wait
Claude Code v2.1.268 gives WebFetch a 300-second deadline. Here is how an unattended run stalls on a server that never closes its response, why CLAUDE_CODE_WEBFETCH_DEADLINE_MS=0 does not mean 'do not wait', and how I now place two separate ceilings.
📚RECOMMENDED BOOKS
Build a Large Language Model (From Scratch)
Sebastian Raschka
LLM Dev
Prompt Engineering for LLMs
Berryman & Ziegler
Prompting
AI Engineering
Chip Huyen
AI Eng
* Contains affiliate links