[BUG] /status and the startup banner show the cached oauthAccount identity, not the account the session authenticates and bills (root cause + deterministic repro)

Status Open
Reported on v2.1.215
Maintainer reply None cached
Activity 0 comments · opened Jul 19, 2026

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

What's Wrong?

Claude Code's identity display surfaces — the /status account panel (Email, Organization) and the startup "Welcome back" banner — do not derive their identity from the credential the session actually uses. They read the login-time cache: the oauthAccount blob in .claude.json, written at /login and by a TTL-gated (roughly daily) profile refresh. The credential used for requests is resolved independently from secure storage (macOS: a Keychain entry whose service name derives from CLAUDE_SECURESTORAGE_CONFIG_DIR / CLAUDE_CONFIG_DIR; elsewhere: .credentials.json in the corresponding directory). Whenever cache and credential diverge, the display is wrong — the session authenticates, bills, and rate-limits against one account while /status names another.

In the minified binary (2.1.215) the panel builder reads Wl()?.emailAddress / Wl()?.organizationName, where function Wl(){return MS()?bt().oauthAccount:void 0} — the cached config blob; the startup banner reads the same accessor. The "Login method" line comes from the live credential/profile path, which is why it can be the only truthful field.

Open reports that match this mechanism from different setups, none identifying the cause: #74217 (/status wrong email/org, Enterprise seat billed), #78838 (desktop app injects the stale ~/.claude.json identity into session context; billing correct), #72552 (headless spawn resolves the default Keychain slot while claude auth status reports the cached metadata). Pointer comments left on the first two; filed fresh so the root cause is triageable in one place.

What Should Happen?

/status and the startup banner should display the account the session's active credential belongs to — or, at minimum, compare the cached oauthAccount against the credential store in use and warn on mismatch instead of presenting the cache as authoritative.

Error Messages/Logs

$ CLAUDE_SECURESTORAGE_CONFIG_DIR="$HOME/.claude-b-creds" claude   # credential store = account B
# startup banner: "Welcome back ..." + accountA@example.com's Organization   <-- account A (wrong)
/status
  Version:          2.1.215
  Login method:     Claude Max account
  Organization:     accountA@example.com's Organization   <-- cached account A (wrong)
  Email:            accountA@example.com                  <-- cached account A (wrong; session credential is account B)

Steps to Reproduce

  1. CLAUDE_SECURESTORAGE_CONFIG_DIR="$HOME/.claude-b-creds" claude/login as account B (creates a separate credential store).
  2. Plain claude/login as account A (default store). The shared .claude.json oauthAccount now holds A.
  3. CLAUDE_SECURESTORAGE_CONFIG_DIR="$HOME/.claude-b-creds" claude → the session authenticates and bills B, but the banner and /status show A's email/organization.

Reproduced on 2.1.215 (macOS, 2026-07-19). One timing note: run step 3 within ~24 h of step 2 — a TTL-gated profile refresh (24 h) rewrites the cache from the live session's credential, so a long-stale mismatch can self-correct. The display follows whichever account last wrote oauthAccount into the shared .claude.json; the billing follows the credential store the session resolved.

Claude Model

Other

Is this a regression?

I don't know

Last Working Version

_No response_

Claude Code Version

2.1.215 (Claude Code)

Platform

Other

Operating System

macOS

Terminal/Shell

Other

Additional Information

  • The same last-writer-wins cache also explains why the mismatch direction can flip: /login writes it unconditionally, and the daily profile refresh writes it with the live session's identity.
  • CLAUDE_SECURESTORAGE_CONFIG_DIR is undocumented but widely used by third-party multi-account tooling; a separate documentation request covers it: #79223.
  • On the desktop-app surface, #78838 (comment 2) found the app separately records the true active account (lastKnownAccountUuid in its own config) — a locally available source of truth the display/context paths ignore.

View original on GitHub ↗