Bundled Claude Code binary at a version-numbered path re-triggers macOS TCC permission prompts on every desktop app update
Summary
The Claude Code binary bundled inside the Claude desktop app lives at a version-numbered path:
~/Library/Application Support/Claude/claude-code/<version>/claude.app/Contents/MacOS/claude
macOS TCC keys privacy grants to the executable path. Because the version is in the path, every desktop app update produces a binary at a path with zero grants, and the user gets a fresh burst of permission dialogs — one per file provider (Dropbox, iCloud, Google Drive, each mounted volume), plus Downloads/Desktop/Documents, Calendar, and each Apple Events target.
Impact
For a user with several cloud providers mounted this is 6-10 modal dialogs after every update. They appear at the first file access, which for anyone running Claude Code on a schedule means a stack of dialogs waiting at the start of the day. Clicking Allow does not help the next update.
It also silently accumulates dead TCC rows — one block per version, permanently. On this machine ~55 rows across four abandoned version paths had built up before being pruned by hand.
Why the obvious workarounds don't work
- Granting Full Disk Access to
/Applications/Claude.appdoes not cover it. The bundled binary is attributed as its own client, not as the parent app. Verified: the app had FDA and the prompts still fired. - Pinning a stable path with a hardlink works for the standalone CLI install (
~/.local/bin/claude), but is not possible here — the desktop app owns that directory and recreates it on update. - Auto-approving via a launchd job cannot work, since writing TCC.db itself requires Full Disk Access, which launchd-spawned shells do not have.
Suggested fix
The binary is already Developer ID signed with a stable identity (com.anthropic.claude-code, Team Q6L2SF6YDW), so grants would carry across updates for free if the executable lived at a version-independent path, e.g.:
~/Library/Application Support/Claude/claude-code/current/claude.app/...
with the version directory referenced internally rather than in the executable path. This is how normal auto-updating apps avoid re-prompting.
Environment
- macOS 26.x (Darwin 25.6.0), Apple Silicon
- Claude desktop app with bundled Claude Code 2.1.247
- Also reproduced on the standalone CLI install before it was pinned to a fixed path
Note
The same class of bug affects the standalone installer: ~/.local/bin/claude symlinks directly into ~/.local/share/claude/versions/<version>, so it re-prompts on every update too. A hardlink to a fixed path fixes that one locally, but only if the versioned name is then removed — while both names exist on the same inode, the kernel can still attribute the process to the versioned path.