macOS: Keychain item written without trusted-application list -> auth prompt on every credential read
Version: 2.1.207 (also on 2.1.206)
Platform: macOS (Apple Silicon), login.keychain-db
Install: single, no tmux, no SSH, single terminal session
Summary
Claude Code stores OAuth credentials in a keychain item Claude Code-credentials, and reads it back by shelling out to /usr/bin/security.
The item is created without any trusted-application entry (no -T equivalent). macOS therefore prompts for the keychain password on every read -- in practice every LLM call, i.e. every 3-4 minutes of active use.
"Always Allow" does not help: Claude Code rewrites/recreates the item, and the new item again has an empty trusted-application list, discarding the granted ACL.
This is NOT the multi-session refresh race (#24317, #48786), which surfaces as an unexpected /login. And it is not limited to third-party tools (#22144): here the CLI prompts on its own reads.
Evidence
1. claude spawns security, and is not authorized against the item it wrote.
Process ancestry captured while the dialog was on screen:
PID PPID COMMAND
68091 56374 security
56374 793 claude
793 757 -zsh
757 656 login
2. The keychain ACL machinery is healthy on this machine.
A control item created with an explicit trusted app reads back silently, twice, no prompt:
security add-generic-password -s "acl-test" -a "$USER" -w "x" -T /usr/bin/security
security find-generic-password -s "acl-test" -w # -> x, no dialog
security find-generic-password -s "acl-test" -w # -> x, no dialog
This rules out a corrupted keychain or a broken SecurityAgent.
3. Rewriting the item WITH -T /usr/bin/security suppresses the per-read prompts.
TOKEN=$(security find-generic-password -s "Claude Code-credentials" -w)
security delete-generic-password -s "Claude Code-credentials"
security add-generic-password -s "Claude Code-credentials" -a "$USER" -w "$TOKEN" -T /usr/bin/security
Prompt frequency drops from ~1 every 3-4 min to ~1 every 1h45. The residual prompts correlate exactly with Claude Code rewriting the item (ACL lost on rewrite):
| Event | cdat | mdat | Prompt |
|---|---|---|---|
| Item rewritten manually with -T | 14:10 CEST | 14:10 | none for 1h45 |
| Claude Code rewrote the item | 14:10 | 15:55 | dialog at 15:55 |
4. ~/.claude/.credentials.json is not an effective fallback on macOS.
With a valid credentials file in place, the keychain item was deleted. Claude Code recreated it on its own (fresh cdat), again with no trusted-application list, and prompting resumed. The file is not consulted in preference to the keychain, contrary to what several community workarounds assume.
Impact
Any macOS user on the keychain path gets an OS password dialog every few minutes of active use. Not dismissible, not remembered, not fixable from the user side. Only mitigation is to periodically rewrite the item by hand with -T, which reduces but does not eliminate the prompts.
Suggested fixes (in order of preference)
- Attach a trusted-application list on write (equivalent to
security add-generic-password -T <path>), so the ACL is valid from creation and no user interaction is ever needed. - Update the item in place instead of delete-and-recreate, so a user-granted ACL survives a token refresh.
- Honour
~/.claude/.credentials.jsonon macOS as on Linux, and do not silently recreate the keychain item.