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
- Ngôn ngữ chính
- Python
- Star
- 145k
- Fork
- 23.1k
- Chỉ số merge pull request
- Chỉ số pull request đang chờ
Mô tả
### 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.
Hướng dẫn đóng góp
Chưa lập chỉ mục được hướng dẫn đóng góp cho kho mã nguồn này
Hướng nghiên cứu
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.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Đánh giá
- Công nghệ
- macos, python, shell
- Lĩnh vực
- authentication, cli, security
- Loại issue
- Lỗi
- Độ khó
- 4/5
- Thời gian dự kiến
- 3-5 ngày
- Mức độ hoạt động
- Sôi nổi
- Độ rõ ràng
- Khá rõ ràng
- Mức phù hợp với người mới
- 45/100