Skip to content

claude login: read the shared Keychain credential when the CLI doesn't namespace by config dir - #20

Open
rbutera wants to merge 1 commit into
RubricLab:mainfrom
rbutera:fix/claude-login-shared-keychain
Open

claude login: read the shared Keychain credential when the CLI doesn't namespace by config dir#20
rbutera wants to merge 1 commit into
RubricLab:mainfrom
rbutera:fix/claude-login-shared-keychain

Conversation

@rbutera

@rbutera rbutera commented Aug 6, 2026

Copy link
Copy Markdown

Problem

tokenmaxx login claude reports success but never stores an account, so the proxy later answers every request with 503 no active anthropic account.

registerClaudeAccount runs an isolated claude auth login --claudeai under a temporary CLAUDE_CONFIG_DIR, then importCliCredential reads the credential back from the macOS Keychain under a service name namespaced by a hash of that config dir (Claude Code-credentials-<hash8>). Current Claude Code (checked on v2.1.220 and v2.1.223) stores its OAuth credential under the plain service Claude Code-credentials regardless of CLAUDE_CONFIG_DIR, and writes no .credentials.json on macOS. Both read branches miss, importCliCredential throws CREDENTIAL_MISSING, and no account row is written. The inner login has already printed "Login successful", so from the outside it looks like it worked and the account simply never appears in the list.

Fix

Read whichever store the CLI actually wrote. Try the namespaced service first, so any build that does namespace keeps working, then fall back to the shared Claude Code-credentials service (keeping the same -a <user> filter), then the on-disk file.

removeClaudeProfile still deletes only the namespaced service, so cleanup never touches the user's own shared Claude Code login.

Evidence

On v2.1.223, security dump-keychain shows only the plain Claude Code-credentials service with no namespaced variant, and that entry carries the claudeAiOauth object the schema expects. The -a <user> filter matters: without it the same service name resolves to a different mcpOAuth-only entry, so the read keeps the user filter.

Tests

Added a regression test: the namespaced lookup misses, the shared service returns the credential, and registerClaudeAccount persists it. The existing namespaced-path test still passes. bun test, typecheck, and biome are all clean.

The version bump and changelog line came from the repo's own prepare commit hook; drop or reformat them if you'd rather handle that at release.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant