claude-code - 💡(How to fix) Fix [BUG] Claude.app deletes & recreates keychain item on workspace open, dropping apple-tool: from partition list and causing recurring macOS prompts

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…

When Claude.app opens a workspace, it triggers a write to the Claude Code-credentials keychain item via a SecItemDelete + SecItemAdd sequence rather than SecItemUpdate. The freshly added item ships with a minimal partition list that no longer contains apple-tool:, so any subsequent /usr/bin/security call against the item — by system services, the desktop app's own components, or third‑party tools — triggers a macOS "security wants to access" dialog.

Clicking "Always Allow" only adds the calling binary to the application list, not apple-tool: to the partition list, so the prompt returns the next time a different binary makes a /usr/bin/security call. The only permanent recovery is the user manually re‑running security set-generic-password-partition-list -S apple-tool:,apple:,… — which itself gets undone the next time Claude.app opens a workspace.

Same root cause as #22144 (closed as not planned). Filing again as a bug report because I now have a deterministic reproducer with raw log timestamps showing the partition‑list mutation in real time.

Root Cause

I'm shipping a Stream Deck plugin ("Usage Monitor for Claude Code", currently in Elgato marketplace review) that reads the rate‑limit headers from /v1/messages to surface session and weekly usage on a physical button. Real end users will hit this every time they open a workspace in Claude.app:

  • They click Always Allow + type their login password
  • A few hours later, on next wake or next workspace switch, the same prompt returns
  • They reasonably blame the third‑party plugin

I've already mitigated my read path: my plugin uses a bundled, ad‑hoc‑signed Swift helper that talks to Security.framework directly, so the helper's CDHash survives in the partition list and its own polling is silent. But anything else on the user's system that uses /usr/bin/security against this item (system services on wake, the Claude.app's own components on some code paths, other third‑party tools they install) still prompts — because the partition list has been left in a broken state.

Fix Action

Fix / Workaround

  1. Use SecItemUpdate instead of SecItemDelete + SecItemAdd for the keychain write path. This is the proper API for rotating the stored data while preserving the existing ACL and partition list. Existing third‑party trust and apple-tool: survive across token rotations and workspace opens. Smallest possible patch, fixes the issue completely.

  2. If a fresh add is unavoidable, include apple-tool: (and ideally merge in the previous partition list values, if any can be read before the delete) when constructing the new item with kSecAttrAccessControl. This silences /usr/bin/security for every existing third‑party integration with zero API additions.

Happy to provide more diagnostics, the raw watcher script, or test patches against the macOS keychain layer.

Code Example

11:56:25  PARTITION LIST CHANGED
          was: cdhash:44a5a8…, apple-tool:
          now: cdhash:44a5a8…
          !! apple-tool: was REMOVED/usr/bin/security calls will prompt now
11:56:35  keychain item rewritten (mdat changed)
          was: 20260525015645Z
          now: 20260525095609Z

---

12:08:57  PARTITION LIST CHANGED   was: cdhash:44a5a8…   now: <missing>
12:09:45  PARTITION LIST CHANGED   was: <missing>        now: cdhash:44a5a8…
RAW_BUFFERClick to expand / collapse

Summary

When Claude.app opens a workspace, it triggers a write to the Claude Code-credentials keychain item via a SecItemDelete + SecItemAdd sequence rather than SecItemUpdate. The freshly added item ships with a minimal partition list that no longer contains apple-tool:, so any subsequent /usr/bin/security call against the item — by system services, the desktop app's own components, or third‑party tools — triggers a macOS "security wants to access" dialog.

Clicking "Always Allow" only adds the calling binary to the application list, not apple-tool: to the partition list, so the prompt returns the next time a different binary makes a /usr/bin/security call. The only permanent recovery is the user manually re‑running security set-generic-password-partition-list -S apple-tool:,apple:,… — which itself gets undone the next time Claude.app opens a workspace.

Same root cause as #22144 (closed as not planned). Filing again as a bug report because I now have a deterministic reproducer with raw log timestamps showing the partition‑list mutation in real time.

Reproducer (verified twice in 13 min on my machine)

I wrote a passive watcher that polls the keychain item's partition_id description and mdat every 30 s via security dump-keychain — metadata only, no ACL decrypt, so the watcher itself never triggers a prompt. I then opened a new workspace in Claude.app while watching.

Event 1 (11:56 CEST, ~10 s after opening a workspace):

11:56:25  PARTITION LIST CHANGED
          was: cdhash:44a5a8…, apple-tool:
          now: cdhash:44a5a8…
          !! apple-tool: was REMOVED — /usr/bin/security calls will prompt now
11:56:35  keychain item rewritten (mdat changed)
          was: 20260525015645Z
          now: 20260525095609Z

Event 2 (12:08 CEST, ~5 s after opening another workspace) — shows the underlying delete+add pattern across two consecutive polls:

12:08:57  PARTITION LIST CHANGED   was: cdhash:44a5a8…   now: <missing>
12:09:45  PARTITION LIST CHANGED   was: <missing>        now: cdhash:44a5a8…

The item was completely absent from the keychain for ~48 s between those two polls, confirming the rewrite goes through SecItemDelete then SecItemAdd rather than SecItemUpdate. Each event correlated with active processes:

  • /Applications/Claude.app/Contents/MacOS/Claude (the desktop app)
  • …/claude-code/2.1.149/claude.app/Contents/MacOS/claude (the bundled CLI that Claude.app shells out to for code workspaces)

Downstream symptom: wake‑from‑sleep prompts

The partition list reset persists across sleep/wake cycles. My watcher captured 3 sleep/wake cycles (gaps of +152 s, +230 s, +514 s) over 2 h following a single workspace‑open rewrite. Partition list stayed cdhash:… (no apple-tool:) the entire time — no further keychain mutations. On the last wake, the user got a "security wants to access" prompt despite not having touched Claude.app since the morning. The wake itself doesn't mutate the keychain; some background service simply made a /usr/bin/security call against the already‑broken partition list.

This is why end users perceive the issue as "random prompts after opening the Mac" rather than "after I opened a workspace": the cause is many hours before the symptom. They never make the connection — they blame the third‑party tool that happened to call security at wake time.

Why this matters

I'm shipping a Stream Deck plugin ("Usage Monitor for Claude Code", currently in Elgato marketplace review) that reads the rate‑limit headers from /v1/messages to surface session and weekly usage on a physical button. Real end users will hit this every time they open a workspace in Claude.app:

  • They click Always Allow + type their login password
  • A few hours later, on next wake or next workspace switch, the same prompt returns
  • They reasonably blame the third‑party plugin

I've already mitigated my read path: my plugin uses a bundled, ad‑hoc‑signed Swift helper that talks to Security.framework directly, so the helper's CDHash survives in the partition list and its own polling is silent. But anything else on the user's system that uses /usr/bin/security against this item (system services on wake, the Claude.app's own components on some code paths, other third‑party tools they install) still prompts — because the partition list has been left in a broken state.

Asked‑for fix, in decreasing order of "would unblock us"

  1. Use SecItemUpdate instead of SecItemDelete + SecItemAdd for the keychain write path. This is the proper API for rotating the stored data while preserving the existing ACL and partition list. Existing third‑party trust and apple-tool: survive across token rotations and workspace opens. Smallest possible patch, fixes the issue completely.

  2. If a fresh add is unavoidable, include apple-tool: (and ideally merge in the previous partition list values, if any can be read before the delete) when constructing the new item with kSecAttrAccessControl. This silences /usr/bin/security for every existing third‑party integration with zero API additions.

  3. Either of the options from #22144 (cache file at ~/.claude/usage-cache.json, or a claude auth token export command) as a long‑term cleaner API surface — but (1) is so much smaller that it should land first regardless.

Happy to provide more diagnostics, the raw watcher script, or test patches against the macOS keychain layer.

Environment

  • macOS Tahoe (Darwin 26.5.0)
  • Claude Code CLI 2.1.149
  • Claude.app 1.8555.2
  • Watcher script + complete raw log available on request.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING