majorwiki/05-troubleshooting/claude-code-keychain-prompt-recurring-macos.md
majorlinux 34d9ee42b1 Add wiki: Claude Code keychain prompt keeps reappearing on macOS
New troubleshooting article for the recurring 'security wants to access
Claude Code-credentials' prompt that persists even after Always Allow
(ACL invalidation on binary-signature change / token refresh / post-boot
churn). Covers triage, the reset-and-relogin fix, and the file-based
credentials workaround with its plaintext tradeoff. Registered in
SUMMARY + troubleshooting index; cross-linked with the corrupt-credential
login-failure article (distinct symptom).
2026-06-15 20:12:11 -04:00

73 lines
4.2 KiB
Markdown

---
title: "Claude Code Keychain Prompt Keeps Reappearing on macOS (ACL Invalidation)"
domain: troubleshooting
category: claude-code
tags: [claude-code, authentication, oauth, keychain, macos, acl, security]
status: published
created: 2026-06-15
updated: 2026-06-15
---
# Claude Code Keychain Prompt Keeps Reappearing on macOS (ACL Invalidation)
## Symptom
A macOS dialog repeatedly pops up:
> **security wants to access key "Claude Code-credentials" in your keychain.**
> To allow this, enter the "login" keychain password. — `[Always Allow] [Deny] [Allow]`
The tell-tale sign: it **comes back even after clicking "Always Allow"** — the usual "trust forever" button doesn't make it stop. Login still works; it's the *permission prompt* that won't quiet down. This is **distinct** from [Claude Code won't log in](claude-code-warp-login-corrupt-keychain-credential.md), where the stored credential is corrupt and login itself fails.
## Cause
Claude Code stores its OAuth token in the macOS **login keychain** as `Claude Code-credentials`, read via `/usr/bin/security`. macOS binds an "Always Allow" grant (the keychain item's ACL) to the **code-signing identity** of the requesting binary. That grant is silently invalidated when:
- **Claude Code updates** — the new binary's signature no longer matches the saved ACL. This is the most common trigger (see claude-code issues #48162, #9403).
- **The credential item is recreated on token refresh** — wipes the ACL.
- **Post-reboot keychain churn** — right after boot, the just-unlocked login keychain plus a concurrent token refresh can race ahead of the ACL settling, producing a *burst* of prompts that stops once a clean refresh completes.
It is **not** a lock-timeout issue if `security show-keychain-info` reports `no-timeout` (below).
## Triage (non-destructive — these do not trigger a prompt)
```bash
# Confirm the item exists (metadata only; no secret read)
security find-generic-password -l "Claude Code-credentials" | grep -E "svce|acct"
# Confirm the login keychain isn't auto-locking
security show-keychain-info ~/Library/Keychains/login.keychain-db
# -> "no-timeout" means it won't relock; so recurring prompts = ACL invalidation, not locking
```
## Fixes
### One-off burst (e.g. right after a reboot)
Click **Always Allow** (not Allow) once a clean token refresh has completed. With a `no-timeout` keychain the grant then holds, and the post-boot prompt storm usually self-clears within a minute. *Observed exactly this on MajorAir 2026-06-15 — a reboot triggered a burst that stopped on its own.*
### Keeps returning after updates (durable) — reset the credential
Deleting and re-creating the item rebinds a fresh ACL to the current binary. Costs one re-login.
```bash
security delete-generic-password -s "Claude Code-credentials"
# then re-authenticate inside Claude Code: /login (or relaunch `claude`)
```
### Bypass the keychain entirely (workaround)
Claude Code falls back to `~/.claude/.credentials.json` in non-GUI contexts (SSH, tmux). On a local Mac this can be repurposed to stop keychain prompts for good:
```bash
# pipe straight to the file — never echo the token into a shared terminal
security find-generic-password -s "Claude Code-credentials" -w > ~/.claude/.credentials.json
chmod 600 ~/.claude/.credentials.json
security delete-generic-password -s "Claude Code-credentials"
```
**Caveats:**
- Token is then **plaintext at rest** (mode 600) instead of encrypted in the keychain.
- A future Claude Code update may rewrite the keychain item.
- GUI-session behaviour for the file fallback is **less documented** than the SSH/tmux case — **verify it holds for your setup before relying on it.**
- Do **not** substitute `CLAUDE_CODE_OAUTH_TOKEN` — it is known to delete credentials on exit (issue #37512).
## Notes
- Same keychain item as the corrupt-credential login failure; if login itself breaks, see the related article.
- Always redirect `-w` output straight to a file — never into a terminal whose scrollback feeds shared context.
## Related
- [Claude Code Won't Log In (Warp & iTerm2) — Corrupt Keychain Credential](claude-code-warp-login-corrupt-keychain-credential.md)
- Config: `~/.claude.json`, login keychain item `Claude Code-credentials`
- First observed: MajorAir, 2026-06-15 (post-reboot prompt burst; self-cleared)