anthropics / anthropics/claude-code

CLAUDE_CONFIG_DIR set to the default path ($HOME/.claude) selects a different Keychain credential entry than leaving it unset, with no diagnosis

Aperta
#92,252 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub
area:auth bug has repro platform:macos
Lingua principale
Python
Stelle
145k
Fork
23.1k
Metriche di merge delle PR
Metriche PR in attesa

Descrizione

### What's Wrong?

Per the docs (Authentication → Credential management), setting `CLAUDE_CONFIG_DIR` keys the macOS Keychain entry to that directory, "so a session with a different `CLAUDE_CONFIG_DIR` reads a different entry." That's expected when the directory actually differs. But here the directory is byte-identical to the default — only whether the variable is textually present differs — and the result is a full loss of login, with nothing in `auth status` or the "Not logged in · Please run /login" message saying which credential store was consulted.

Any script or automation that forwards `CLAUDE_CONFIG_DIR` unconditionally (e.g. to pin a relocated install's root, or because it defensively re-sets `process.env` values) silently breaks auth for that child process the moment the parent never had the variable set in the first place.

### Steps to Reproduce

```bash
claude auth status
# → {"loggedIn": true, "authMethod": "claude.ai", ...}

CLAUDE_CONFIG_DIR="$HOME/.claude" claude auth status
# → {"loggedIn": false, "authMethod": "none"}
```

Variants that isolate it to the variable's literal presence/value, not path resolution:

```bash
CLAUDE_CONFIG_DIR="$HOME/.claude/" claude auth status # trailing slash → still false
CLAUDE_SECURESTORAGE_CONFIG_DIR="$HOME/.claude" claude auth status # → still false
```

(An unexpanded `CLAUDE_CONFIG_DIR='~/.claude'` also fails, but that's a genuinely different directory — `auth status` reports `projectsDirectory: "~/.claude/projects"`, literal tilde, unresolved — so it isn't a same-directory data point and is omitted here.)

Workaround, pinning the default credential store explicitly — restores login but not identity reporting:

```bash
CLAUDE_CONFIG_DIR="$HOME/.claude" CLAUDE_SECURESTORAGE_CONFIG_DIR="" claude auth status
# → {"loggedIn": true, "authMethod": "claude.ai", "email": null, "orgId": null, "orgName": null, "subscriptionType": "max"}
```

### Environment

- `claude --version`: 2.1.261 (npm install under Homebrew's node prefix)
- macOS 26.6.2 (arm64)
- OAuth subscription login (Claude.ai, Max plan); `~/.claude/.credentials.json` does not exist — Keychain-only credential store
- Regression status: unknown, not tested on earlier versions (per #79223, the CLI has recognized `CLAUDE_SECURESTORAGE_CONFIG_DIR` since roughly 2.1.144, which is the related-but-separate mechanism this report's `CLAUDE_CONFIG_DIR` keying appears to route through — not a claim about when `CLAUDE_CONFIG_DIR`'s own keying began)

### What Should Happen?

Primarily: make this diagnosable. `claude auth status` and the `--print` "Not logged in" path should report which credential store/Keychain entry was consulted (and that an explicit `CLAUDE_CONFIG_DIR` selects a different one than unset), instead of an undifferentiated "Not logged in · Please run /login". This should also be documented alongside the existing `CLAUDE_CONFIG_DIR` docs, not only inferable from `CLAUDE_SECURESTORAGE_CONFIG_DIR` behavior.

Alternative (one clause): resolve an explicit `CLAUDE_CONFIG_DIR` that is byte-identical to the default to the same credential entry as leaving it unset. (This has a migration wrinkle — anyone who already logged in under the explicit path has a credential in the other slot — so the diagnosability fix above is the safer primary ask.)

### Related

- #87447 — "Repro C" in that issue is this same unset-vs-explicit-default discrepancy (seen there as `loggedIn:true` with null identity on Windows' plaintext credential file; here as a clean `loggedIn:false` on macOS Keychain). Buried as the third of three repros in a broader issue about a different primary complaint.
- #79223 — documents `CLAUDE_SECURESTORAGE_CONFIG_DIR` behavior in detail, including "setting the variable to your default config directory's absolute path selects a different, empty credential store, which presents as a lost login" and "an empty value pins the default credential store." This issue's repro matches that description exactly; #79223 is a docs request for the sibling variable, not a report against `CLAUDE_CONFIG_DIR`'s own behavior or the error message.
- #88601 — describes per-config-dir credential isolation as current behavior (different directories get different Keychain items, `Claude Code-credentials-`); closed by its own author, not a maintainer statement of intent. Not in conflict with this report, which is about explicit-vs-unset for the *same* directory.
- #84275 / #90527 — a different, adjacent defect (hash-suffixed Keychain items accumulating daily, never cleaned up), not this one.

### Additional context

Found this while debugging a background automation that unconditionally forwarded `CLAUDE_CONFIG_DIR` to a spawned child process — even when the parent never had the variable set, the forwarding code still injected the resolved-to-default path, reproducing this exactly. Only forwarding the variable when the parent actually had it set resolved it.

Guida per i contributori

Nessuna guida per i contributori indicizzata per questo repository

Direzione di ricerca

Start by reproducing the unset and explicit-default CLAUDE_CONFIG_DIR commands through the auth status and --print entry points. Read the Authentication → Credential management documentation and related issue #79223, then trace how the credential store is selected. Done means auth status and --print identify the consulted store, with documentation updated, or equivalent paths consistently select one credential entry.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Valutazione

Stack tecnologico
macos, python, shell
Ambito
authentication, cli, security
Tipo di issue
Bug
Difficoltà
4/5
Tempo stimato
3-5 giorni
Stato di attività
Attiva
Chiarezza
Abbastanza chiara
Idoneità per principianti
45/100

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.