[BUG] Desktop session's host account ignored when ~/.claude.json already has an oauthAccount; userEmail reports the wrong user
Summary
When the Claude desktop app starts a Code session for one account, but ~/.claude.json already holds a different oauthAccount (e.g. from an earlier terminal /login), the session authenticates and bills as the desktop account, while everything that reports identity reports the stale ~/.claude.json account. The model's userEmail context and plugins that read it all name the wrong person, and nothing in the session shows the mismatch.
Version
Claude Code 2.1.286 (CLI bundled with the Claude desktop app, macOS), CLAUDE_CODE_ENTRYPOINT=claude-desktop
Repro
- In a terminal,
claude /loginas account A.~/.claude.json→oauthAccount.emailAddress = A. - Sign the desktop app into account B and start a Code session.
- The session process environment contains the desktop's account:
CLAUDE_CODE_USER_EMAIL=B, CLAUDE_CODE_ACCOUNT_UUID=<B uuid>, CLAUDE_CODE_ORGANIZATION_UUID=<B org>, plus CLAUDE_CODE_OAUTH_TOKEN for B.
- In the session, the system context says "The user's email address is A", and a plugin reading the
userEmailcontext block (or~/.claude.json) also resolves A.
Expected: the session reports B, the account it actually runs and bills as.
Cause (from reading the 2.1.286 bundle)
The host-supplied account is adopted only when no account is already saved:
let r = CLAUDE_CODE_ACCOUNT_UUID, s = CLAUDE_CODE_USER_EMAIL, g = CLAUDE_CODE_ORGANIZATION_UUID,
h = r && s && g ? { accountUuid: r, emailAddress: s, organizationUuid: g } : null;
if (h && !ce().oauthAccount) mUt(h, n); // ignored when ~/.claude.json already has an oauthAccount
and the userEmail context is built from the saved record:
let D = ANTHROPIC_UNIX_SOCKET ? void 0 : Cn()?.emailAddress // Cn() → ce().oauthAccount
So a stale oauthAccount in ~/.claude.json wins over the account the host launched the session with.
Impact
- The model attributes work, authorship, and decisions to the wrong person.
- Plugins that route or authorize by the signed-in user (e.g. RACI/approval routing keyed on
userEmail) grant the wrong person's authority. In our case a session for a senior-engineer account was routed with the CEO account's authority.
Expected fix
When the host supplies CLAUDE_CODE_ACCOUNT_UUID / CLAUDE_CODE_USER_EMAIL / CLAUDE_CODE_ORGANIZATION_UUID, that should be the session's effective account (in memory, without overwriting the terminal CLI's ~/.claude.json), and userEmail should come from it.
Related
- #87447: same symptom family (session reports a different account than it authenticates as), via
CLAUDE_CONFIG_DIRon Windows. - #85294: desktop account switch doesn't reconcile
~/.claude.json.
This report is the specific code path on macOS without CLAUDE_CONFIG_DIR: host env account ignored whenever oauthAccount already exists.