macOS TCC Automation grants not preserved across CC versions — Settings panel accumulates one row per release

Status Closed — not planned
Reported on v2.1.90
Maintainer reply None cached
Activity 6 comments · opened Apr 29, 2026 · closed Jun 3, 2026

Summary

On macOS, every new release of Claude Code registers as a separate app
in System Settings → Privacy & Security → Automation. Old entries
from binaries that no longer exist persist indefinitely. The list
grows by roughly one row per CC release where the Bash tool invokes
osascript.

Reproduction

  1. Run CC version A (e.g. 2.1.90) and execute a Bash call that uses

osascript to control an app (Reminders, Photos, Calendar, etc.).
macOS prompts for Automation permission; user clicks Allow.

  1. CC auto-updates to version B (2.1.91).
  2. Run the same osascript action. macOS prompts again — TCC treats it

as a new app.

  1. Repeat for every subsequent release.

After ~30 releases, the Automation panel shows one row per version
(2.1.90, 2.1.91, … 2.1.121), each expandable to a list of
controlled apps. None can be deleted via the GUI in current macOS.

Expected

CC releases should share a stable code-signing identity / designated
requirement so TCC matches them as the same app. A user who grants
Automation to one CC version should not be re-prompted on every
update, and the panel should show a single Claude Code row.

Actual

Each version registers separately. Stale entries persist after the
binary is gone. Users see repeat prompts and accumulating clutter.

Environment

  • macOS 26.4.1 (build 25E253)
  • Claude Code 2.1.121, with stale Automation entries back to 2.1.90
  • Bash tool calling /usr/bin/osascript

Impact

  • Repeat consent prompts erode the trust signal — users start

clicking Allow reflexively, defeating TCC's purpose.

  • The Automation panel becomes unusable for auditing what CC can

actually control today versus historically.

  • Cleanup paths are unattractive: tccutil reset Automation nukes

all Automation grants for every app on the system; direct edits
to TCC.db require Full Disk Access and are unsupported.

Likely cause

CC's signature designated requirement appears to be version-pinned
rather than identifier-based. TCC uses the designated requirement to
decide whether two binaries are the same app. If the requirement
references the exact code signature or version, every release looks
new.

Suggested fix

Audit the CC code-signing setup. The designated requirement in the
signature should match by Team ID + bundle identifier (e.g.
identifier "com.anthropic.claude-code" and anchor apple generic and
certificate leaf[subject.OU] = "<TEAM_ID>"
), not by exact binary
hash, so TCC sees 2.1.90 and 2.1.121 as the same app.

View original on GitHub ↗

6 Comments

github-actions[bot] · 5 months ago

Found 3 possible duplicate issues:

  1. https://github.com/anthropics/claude-code/issues/49282
  2. https://github.com/anthropics/claude-code/issues/53703
  3. https://github.com/anthropics/claude-code/issues/48311

This issue will be automatically closed as a duplicate in 3 days.

  • If your issue is a duplicate, please close it and 👍 the existing issue instead
  • To prevent auto-closure, add a comment or 👎 this comment

🤖 Generated with Claude Code

eins78 · 5 months ago

+1 — seeing the exact same pattern on macOS, with one important nuance: I think the suggested fix above is mis-aimed.

Empirical evidence (one machine, ~17 days)

Direct query of ~/Library/Application Support/com.apple.TCC/TCC.db:

service                              | client (path)                                      | granted
kTCCServiceSystemPolicyDownloadsFolder | ~/.local/share/claude/versions/2.1.104              | Apr 12
kTCCServiceSystemPolicyNetworkVolumes  | ~/.local/share/claude/versions/2.1.104              | Apr 12
…
kTCCServiceSystemPolicyDesktopFolder   | ~/.local/share/claude/versions/2.1.116              | Apr 21
kTCCServiceSystemPolicyNetworkVolumes  | ~/.local/share/claude/versions/2.1.117              | Apr 22
kTCCServiceSystemPolicyDownloadsFolder | ~/.local/share/claude/versions/2.1.118              | Apr 23
kTCCServiceSystemPolicyDesktopFolder   | ~/.local/share/claude/versions/2.1.119              | Apr 26
kTCCServiceSystemPolicyDownloadsFolder | ~/.local/share/claude/versions/2.1.120              | Apr 25
kTCCServiceSystemPolicyDesktopFolder   | ~/.local/share/claude/versions/2.1.121              | Apr 28
kTCCServiceSystemPolicyDownloadsFolder | ~/.local/share/claude/versions/2.1.122              | Apr 28 (yesterday)
…not yet granted: 2.1.123 (today's symlink target)

14+ rows total over 17 days, one per release, each storing the literal versioned path as client. That's the same pattern your Automation grants are showing — TCC stores client_path literally and treats versions/2.1.122 and versions/2.1.123 as different clients.

The DR is already Team-ID-anchored — code signing isn't the problem

codesign -d -r- on the current claude (2.1.123) returns:

designated => identifier "com.anthropic.claude-code"
              and anchor apple generic
              and certificate 1[field.1.2.840.113635.100.6.2.6] /* exists */
              and certificate leaf[field.1.2.840.113635.100.6.1.13] /* exists */
              and certificate leaf[subject.OU] = Q6L2SF6YDW

That already matches by Team ID + bundle identifier (not by cdhash) — which is what your "suggested fix" recommends. So the DR isn't the obstruction; this DR is correct and would let TCC see two CC versions as the same app for app-bundle-keyed services.

The reason it doesn't help for command-line claude is that TCC keys grants on client_path for non-bundled binaries, and the install layout produces a new path on every release (~/.local/share/claude/versions/<v>/). The DR isn't being consulted to merge old/new paths because nothing is asking it to — TCC just sees an unfamiliar client path and prompts.

Real fix is the install layout, not the signature

The path needs to be stable across releases. Options:

  1. Install at a non-versioned path (e.g. ~/.local/share/claude/current/claude), keep version directories around for rollback but expose only the stable name to TCC.
  2. Bundle as a proper .app so TCC keys on bundle ID + DR rather than path.
  3. Per-user TCC migration on update (write a tiny helper that copies grants from the previous versions/<old> row to the new versions/<new> row in TCC.db). Requires FDA, ugly, but unblocks today's installs without changing the layout.

Cross-references that all describe the same path-keying problem with different symptoms:

  • #49282 (canonical) — re-registers as new app on every version update
  • #48311 — auto-updater doesn't clean up old binaries
  • #53703 — Network volume permission prompt on every update
  • #42546 (closed without fix) — binary named by version number
  • #41297 — recurring TCC dialogs

Workaround for users hitting this today

Set DISABLE_AUTOUPDATER=1 (or DISABLE_UPDATES=1 for stricter), pin to a version, re-grant once. Stops the daily-grant churn until the install layout is fixed upstream. Trade-off is manual claude update cadence.

basjes1977 · 5 months ago

Same root cause here — macOS Sequoia (Darwin 25.4), Claude Code via npm.

Beyond Automation, this also affects Files and Folders. Each release registers a separate entry under Privacy & Security > Files and Folders with its own toggles for Desktop, Documents, and Downloads. Versions 2.1.117 through 2.1.129 each appear as distinct rows; granting folder access to one version does not carry over to the next.

Affected TCC scopes observed so far:

  • kTCCServiceAppleEvents (Automation — as described in this issue)
  • kTCCServiceSystemPolicyDesktopFolder
  • kTCCServiceSystemPolicyDocumentsFolder
  • kTCCServiceSystemPolicyDownloadsFolder

The suggested fix (DR anchored on Team ID + bundle identifier) should cover all of these since TCC uses the same designated-requirement matching across scopes. Worth confirming the scope of any signing change covers Files and Folders in addition to Automation.

github-actions[bot] · 4 months ago

Closing for now — inactive for too long. Please open a new issue if this is still relevant.

digitalby · 3 months ago

Bumping this

github-actions[bot] · 1 month ago

This issue has been automatically locked since it was closed and has not had any activity for 7 days. If you're experiencing a similar issue, please file a new issue and reference this one if it's relevant.