[BUG] macOS App Management accumulates one permission row per release; stable signing identity defeated by version-named binary paths (follow-up to #38722)
Impact (why this deserves priority)
This is not cosmetic and not limited to one Settings pane. On one machine, TCC database inspection shows version-named Claude Code clients registered across SEVEN permission services: App Management, Files & Folders (Desktop, Documents, Downloads), File Provider, Media Library, Microphone, and App Data. 23 of 23 user-database rows pointed at binaries that no longer exist, meaning users carry stale permission grants (including Microphone) attributed to deleted executables. Every macOS native-installer user accumulates this on every release, at a near-daily release cadence, with an opaque version-number prompt each time; users who hit Don't Allow silently break auto-update. There is no supported user-side cleanup for the system-database rows short of resetting the entire service for all apps.
Description
The native installer ships every release as a bare executable whose filename is the version string, e.g. ~/.local/share/claude/versions/2.1.207. macOS TCC keys App Management (kTCCServiceSystemPolicyAppBundles) clients by binary path, so each release registers a brand-new client. Result: one new row in System Settings > Privacy & Security > App Management per release, named only 2.1.x, plus one opaque permission prompt per update ("\"2.1.207\" would like to update other applications"). With near-daily releases the pane accumulates dozens of rows (screenshot available: 2.1.191 through 2.1.207 on one machine).
New evidence beyond the prior reports
- The grant SHOULD already carry across updates.
codesign -dvvon multiple installed versions shows the identical stable identity:Identifier=com.anthropic.claude-code, Developer ID Application: Anthropic PBC (Q6L2SF6YDW), and byte-identical designated requirements. The macOS machinery for carrying a TCC grant across updates exists and is correctly configured at the signing layer; the per-release binary path is what defeats it.
- Users cannot clean this up themselves.
tccutil reset SystemPolicyAppBundles com.anthropic.claude-codefails with OSStatus -10814 because a bare (non-bundle) binary has no LaunchServices registration; tccutil has no per-path targeting; and the system TCC.db is SIP-protected against direct edits. The only cleanup that works is a fullsudo tccutil reset SystemPolicyAppBundles, which also revokes App Management for every other app on the machine (Cursor, Google Drive, etc. all re-prompt).
Steps to reproduce
- Install Claude Code via the native installer on macOS 13+.
- Grant the App Management prompt.
- Let several auto-updates occur.
- Open System Settings > Privacy & Security > App Management: one
2.1.xrow per release.
Expected
A single persistent "Claude Code" entry that survives updates, as with Chrome or VS Code. Any layout where the TCC client path is stable would fix it, for example a stable launcher binary that execs the versioned binary, or shipping an .app bundle.
Environment
- Claude Code 2.1.207, native installer (
~/.local/share/claude/versions/) - macOS 26.3 (25D125)
Prior reports
#38722 (this exact accumulation; closed NOT_PLANNED by the inactivity bot, which invited a fresh issue). Same root cause family: #59608, #54016, #58713, #43562 (prompt shows the version string as the app name and re-prompts every update).
Showing cached comments. Read the full discussion on GitHub ↗
3 Comments
Same accumulation in the Files & Folders pane, not just App Management: one row per release, each displayed as the bare version string (#76080's naming bug), each a path-keyed TCC row for a binary at
~/.local/share/claude/versions/<ver>— the executable is literally named2.1.x(Mach-O thin, signedIdentifier=com.anthropic.claude-code). Observed range on this machine: 2.1.179 → 2.1.210, all dead paths (the updater already deleted those binaries), plus the live 2.1.211.What makes this worse than cosmetic clutter is that the stale rows are effectively impossible for users to remove individually:
tccutil resetaddresses bundle IDs only; these rows are path-keyed, andtccutil reset All com.anthropic.claude-codedoesn't match them.TCC.dbis sealed on recent macOS, so no direct cleanup either.tccutil reset SystemPolicyDocumentsFolder(etc.) per service class — which wipes every third-party app's grant in the pane as collateral.So each release permanently appends an unremovable dead row to the user's privacy settings. Running the CLI from a stable path (or a stable-path shim that owns the TCC identity, since the signing identifier is already stable) would stop the accrual.
Adding independent confirmation with measured data from another machine (macOS 26 / Darwin 25.5, native installer).
Accumulation rate, measured: Between 2.1.204 and 2.1.215 (Jul 8–19: 11 releases in ~12 days), this machine accumulated duplicate TCC grants for four different version-named binaries (2.1.204, 2.1.207, 2.1.212, 2.1.215) across Files & Folders (Desktop/Documents/Downloads), File Provider, Media Library and App Data. A manual cleanup pass removed 25 stale TCC rows pointing at binaries that no longer exist — consistent with the 23/23 stale-row observation in the original report. Re-prompts appear the first time a new version's session touches a protected folder, which at the current release cadence means every few days.
Why the stable bundle doesn't fix it (as of 2.1.215):
~/.local/share/claude/ClaudeCode.appnow exists and some helper processes (e.g. pty-host) launch through it, so the signing identity (com.anthropic.claude-code, Q6L2SF6YDW) is stable. But session workers still re-exec the version-named binary at~/.local/share/claude/versions/<version>, and TCC attributes the permission request to that path. The result is the infamous bare-number dialog (“2.1.215” would like to access…) and grants that die on every update. Granting Full Disk Access to the terminal or to ClaudeCode.app does not suppress the prompts (same behavior reported in #66216 and #77734).Suggested direction: route every worker re-exec through the stable
ClaudeCode.appbundle (or any version-independent path/hard link), so the TCC attribution — and therefore the grant — survives updates. The signing identity is already stable; only the on-disk path churns.Workaround until then:
DISABLE_AUTOUPDATER=1insettings.jsonenv plus a scheduled weeklyclaude updateconfines the re-prompt to one predictable session per week.Related: #79053 (same root cause, network-volume variant).
On the suggested direction of routing workers through the stable bundle or a version-independent hardlink: worth checking the hardlink stays current. On 2.1.221 here (macOS 26.6, native installer), the bundle's executable is still hardlinked to 2.1.220:
So the bundle is a release behind what
~/.local/bin/clauderesolves to. If TCC attribution moves to the bundle path without the bundle also being refreshed on every release, the identity problem gets fixed by introducing a staleness one.Separately, on the manual cleanup pass that removed 25 stale rows: what did that use?
tccutil reset All "<absolute path>"refuses here with-10814without reaching either database, and the Files & Folders pane has no remove control. If there's a per-row method that works, it'd be worth having in this thread.