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).
73 lines
4.2 KiB
Markdown
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)
|