[BUG] macOS native install: `claude` reads its own credentials via `/usr/bin/security`, but the keychain item's partition list lacks `apple-tool:` — endless XARA keychain prompts, "Always Allow" never persists
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code
What's Wrong?
What's Wrong?
On macOS, Claude Code (native install) repeatedly triggers the system keychain dialog:
security wants to access key "Claude Code-credentials" in your keychain.
Clicking Always Allow (and entering the login keychain password) silences it only temporarily. The prompt returns after a while — apparently after each OAuth token refresh — making it effectively endless. No third-party tools, statusline scripts, or hooks are involved: the process requesting access is claude itself.
Root Cause Analysis
The Claude Code-credentials keychain item appears to be written via Security.framework (partition list contains only the teamid: partition), while Claude Code reads it by spawning /usr/bin/security (CLI), which requires the apple-tool: partition. Since the item's partition list does not include apple-tool:, every CLI read triggers a XARA partition check and a user-facing prompt.
When the user clicks "Always Allow", macOS adds apple-tool: to the partition list and the prompts stop. But on the next OAuth token refresh, Claude Code rewrites the keychain item, resetting the partition list — and the cycle restarts:
- Token refresh → item rewritten → partition list resets (no
apple-tool:) claudespawns/usr/bin/securityto read credentials → XARA mismatch → prompt- User clicks "Always Allow" →
apple-tool:added → quiet for a few hours - GOTO 1
This is the inverse of the failure mode described in steipete/CodexBar#458 (where the item is created with apple-tool: only and teamid:-partitioned third-party apps get rejected). Here, Claude Code's own read path is the one being rejected — the write path and read path of the same application use mismatched keychain partitions.
Evidence
1. The requesting process is claude itself
Polling loop run while the dialog was on screen (while :; do for p in $(pgrep -x security); do ...):
11:53:38 security(<pid1>) ← parent(<ppid>): claude
11:53:38 security(<pid2>) ← parent(<ppid>): claude
11:53:39 security(<pid1>) ← parent(<ppid>): claude
...
Two concurrent security child processes, both parented by the single claude process. No other tool on the system accesses this keychain item.
2. securityd logs showing the partition mismatch
securityd: [com.apple.securityd:integrity] ACL partition mismatch: client apple-tool: ACL (
securityd: [com.apple.securityd:integrity] asking user about XARA partition for 'apple-tool:'
securityd: [com.apple.securityd:kcacl] displaying keychain prompt for /usr/bin/security(<pid>); ACL: <AclValidationContext(action:65538)SUBJECT[not-init]OBJECT[not-init]>
securityd: [com.apple.securityd:integrity] user approved XARA access for 'apple-tool:'
securityd: [com.apple.securityd:integrity] adding XARA partition 'apple-tool:' to list
Note: the client is apple-tool: (i.e. /usr/bin/security) and it is not in the item's ACL partition list — confirming the item was created under a different partition (presumably teamid: via Security.framework).
3. Clean single-install environment
$ which -a claude
/Users/<user>/.local/bin/claude
$ ls -la ~/.local/bin/claude
lrwxr-xr-x ... /Users/<user>/.local/bin/claude -> /Users/<user>/.local/share/claude/versions/2.1.170
$ npm ls -g | grep -i claude
(nothing — no npm install)
$ claude --version
2.1.170 (Claude Code)
~/.claude/settings.json contains no statusLine and no hooks — only permissions, model, alwaysThinkingEnabled, effortLevel, autoUpdatesChannel, verbose.
What Should Happen?
Expected Behavior
- Clicking "Always Allow" should permanently suppress the prompt, OR
- Claude Code should read/write the keychain item through a single consistent mechanism so its own reads never trigger a XARA partition check, OR
- Token refresh should update the item in place (
SecItemUpdate/ preserving ACL & partition list) instead of delete-and-recreate
Error Messages/Logs
Steps to Reproduce
- Install Claude Code via the native installer on macOS (single install, no npm/Homebrew copy)
- Log in with OAuth (
/login) — credentials stored in keychain itemClaude Code-credentials - Use Claude Code normally across token-refresh cycles
- Observe the keychain dialog "security wants to access key 'Claude Code-credentials'"
- Click "Always Allow" and enter the keychain password
- Continue using Claude Code → the dialog reappears after the next token refresh
Claude Model
Opus
Is this a regression?
Not sure
Last Working Version
_No response_
Claude Code Version
2.1.170
Platform
Claude.ai (subscription)
Operating System
macOS
Terminal/Shell
VS Code integrated terminal
Additional Information
_No response_
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗