[BUG] Claude Desktop's bundled Claude Code overwrites the CLI's 'Claude Code-credentials' keychain item → CLI 'Not logged in' daily (macOS)
Summary
On macOS, the Claude Code that ships inside Claude Desktop (the Code tab, bundled binary 2.1.295) writes to the same keychain item, Claude Code-credentials, as the standalone CLI. When Desktop auto-creates a "scratch" Code session on launch or wake, that process overwrites the CLI's stored OAuth credentials. The next CLI start shows Not logged in · Please run /login.
For me this meant a /login almost every day for two weeks. I never used the Code tab on purpose: Desktop starts at login, opened on the Code tab, and created a scratch session by itself.
Environment
- macOS 15, Apple silicon
- Claude Code CLI 2.1.296 (native install), used in the VS Code integrated terminal
- Claude Desktop 2.31226.1; bundled Claude Code 2.1.295 at
~/Library/Application Support/Claude/claude-code/2.1.295/.../claude.app - The CLI and Desktop are signed in to the same personal Pro account
Reproduction (deterministic)
- With Claude Desktop running, run
/logoutin the CLI. TheClaude Code-credentialskeychain item is deleted. - In Claude Desktop, open the Code tab or start a Code session. A scratch session started on launch has the same effect.
- The
Claude Code-credentialsitem is recreated within 1 s of Desktop spawning its bundled CLI ([CCD] learned CLI process group …in~/Library/Logs/Claude/main.log). The recreated JSON has noclaudeAiOauth, only other state.
Observed timestamps, from a watcher polling the item's mdat every 20 s:
10:02:29 CLI /logout → item gone
10:03:02 Desktop: [CCD] learned CLI process group 36575
10:03:02 keychain item recreated (mdat 07:03:02Z), JSON has no claudeAiOauth
10:04:02 CLI /login → full credentials again
How it breaks the CLI in normal use
On a normal day, after the CLI's 8 h access token has expired overnight:
- 09:26:15: Desktop wakes and obtains its own token.
- 09:27:41: Desktop auto-creates a scratch Code session (
LocalSessions.createScratchWorkspace,Using Claude Code binary at …/2.1.295/…). - 09:27:43: the
Claude Code-credentialsitem is rewritten, 2 s after the spawn. - 09:41:
claude --debugin Terminal starts unauthenticated. The debug log shows[Claude in Chrome] Disabled: OAuth token has no scope accepted by /api/oauth/validate (needs user:profile …)and[claudeai-mcp] Disabled: API-key auth precedence active. The session reportsNot logged in.
The token the CLI finds is not the one it stored, and it lacks the scopes the CLI requires. Server-side refresh itself works: the same night the CLI's token refreshed fine.
Correlation
In the user's Desktop data, Code sessions per month were Jul 2, Aug 1, Sep 1 and Oct 25. The first auto-created scratch-* workspace is dated Sep 29, the same day the daily re-logins began. Almost every re-login in that period followed a Desktop launch that auto-created a scratch Code session.
Workaround
Switch Claude Desktop to the Chat tab and relaunch it. Desktop then starts without spawning a Code session, and the CLI login persists.
Expected
Claude Desktop's bundled Claude Code should not read, write or recreate the standalone CLI's Claude Code-credentials item. It should use its own credential store, or its own CLAUDE_CONFIG_DIR-style suffix, especially since Desktop passes its own token to the session anyway. A scratch session that the user never opened should also not touch CLI credentials.