/status shows the persisted login identity, not the account of the token in use

Status Open
Reported on v2.1.224
Maintainer reply None cached
Activity 0 comments · opened Aug 7, 2026

Version: 2.1.224 (macOS, darwin)
Auth: claude.ai subscription (OAuth)

Summary

The Email and Organization rows of /status are read from the oauthAccount
block persisted in ~/.claude.json at login time. They are not derived from
the credential the session is actually sending. When those two diverge —
which happens as soon as credential storage is scoped per session with
CLAUDE_SECURESTORAGE_CONFIG_DIR/status reports one account while every
API call, and /usage, uses another.

For a single-account machine the two can never diverge, so this is invisible
in normal use. But per-session credential scoping is presumably what
CLAUDE_SECURESTORAGE_CONFIG_DIR exists for (running two subscriptions side
by side), and in that setup /status — the panel whose job is answering
"who am I" — is the one surface that gets it wrong.

Repro

  1. Log in normally as account A. /status shows A's email. ✔️
  2. Mint a long-lived token for account B: claude setup-token, signing in

as B in the browser.

  1. Put B's token in a scoped credential store:

``sh
mkdir -p ~/pin && chmod 700 ~/pin
cat > ~/pin/.credentials.json <<'EOF'
{"claudeAiOauth":{"accessToken":"sk-ant-oat01-…","refreshToken":null,"expiresAt":null,"scopes":["user:inference"]}}
EOF
chmod 600 ~/pin/.credentials.json
``

  1. CLAUDE_SECURESTORAGE_CONFIG_DIR=$HOME/pin claude
  2. In the session:
  • /statusEmail: A, Organization: A's org.
  • /usageB's rate-limit windows and reset times (fetched with the

session's real bearer, i.e. B's token).

  • Quota consumed by the session lands on B.

The two panels disagree with each other inside the same session.

Expected

/status's identity rows reflect the account the session authenticates as —
or at minimum, flag that the persisted login and the active token disagree.

Root cause

The status panel's account rows read the persisted oauthAccount
(~/.claude.json), not the active credential. In the bundle: the row builder
takes email/organization from the persisted-config accessor
(Bt().oauthAccount), while subscription comes from the credential — so
even within /status, "Login method" is credential-derived and "Email" is
config-derived.

Suggested fix — the codebase already solves this elsewhere

The Chrome-bridge path resolves the in-use access token to its real account
via the OAuth profile endpoint and explicitly handles this divergence,
logging:

"The OAuth token in use resolves to a different claude.ai account than the persisted Claude Code login. Using the token-derived account for the browser bridge."

(telemetry: tengu_chrome_bridge_account_mismatch)

/status could use the same token-derived identity for its Email row, or
keep the persisted values but append the mismatch warning when the resolved
account differs. Either would make /status and /usage agree.

Notes

  • CLAUDE_CODE_OAUTH_TOKEN sessions are unaffected in practice: for those,

/status shows Auth token: CLAUDE_CODE_OAUTH_TOKEN and omits the email
rather than showing a wrong one. The scoped-store case is indistinguishable
from a normal claude.ai login, so it gets the cached identity.

  • Everything above was verified live on 2.1.224: the scoped session's

/usage numbers track account B (and match A's again when the scoped
store holds A's token), while /status shows A throughout.

View original on GitHub ↗