macOS: auto-update creates new TCC identity each version, breaking Desktop/FDA grants daily
Summary
On macOS, every Claude Code auto-update installs a brand-new Mach-O binary at a versioned path. macOS TCC (Privacy & Security) keys on the resolved binary identity, so each version is treated as a new app. Users who work inside TCC-protected folders (~/Desktop, ~/Documents, ~/Downloads, iCloud) get a fresh permission prompt every morning, and the previous version's TCC grant becomes useless.
Repro
- Install Claude Code via the standalone installer (default).
- Grant Terminal/iTerm Files & Folders → Desktop access, and grant the
claudebinary Full Disk Access. - Open a new shell tomorrow after the nightly auto-update fires, with
cwdinside~/Desktop/.... - Run
claude. It errors withAn unknown error occurred (unexpected)because Node can'tstatthe cwd. macOS will prompt (or silently deny on first hit) for the new binary's Desktop access.
Why
~/.local/bin/claude → ~/.local/share/claude/versions/2.1.143
(yesterday: 2.1.142, day before: 2.1.141, …)
Each 2.1.x file is a separate 207 MB Mach-O binary at a different path. The symlink swings to the new file on update. macOS TCC resolves the symlink and stores the grant against the real binary's path/identity, so the grant is bound to a file that gets superseded daily.
Evidence
Over ~30 days on one machine, Privacy & Security accumulated separate TCC entries for every version installed: 2.1.114, 2.1.116, 2.1.117, 2.1.118, …, 2.1.143 — both in Files & Folders → Desktop Folder and in Full Disk Access. Each required a click-through the morning it appeared.
Expected behavior
The installer should write to a stable path (e.g. ~/.local/share/claude/current) and atomically replace the file on update (rename(2) of a freshly-written sibling). macOS TCC then sees a single binary identity that persists across version bumps, and the user grants permission once.
The current scheme (versioned filenames + symlink swap) is the worst case for TCC because it changes both the path and the file identity simultaneously.
Workaround
Setting DISABLE_AUTOUPDATER=1 in ~/.claude/settings.json's env block freezes the binary in place so the TCC grant sticks, at the cost of manual claude update runs.
Environment
- macOS 15 (Darwin 25.4.0), Apple Silicon
- Claude Code 2.1.143, standalone installer (
~/.local/bin/claude→~/.local/share/claude/versions/2.1.143) - iTerm2, working dir under
~/Desktop
Suggested fix
In the updater: write the new binary to ~/.local/share/claude/staging-<version>, fsync, then rename() over ~/.local/share/claude/current. Keep ~/.local/bin/claude as a stable symlink to …/current. Optionally keep last N versions in versions/ for rollback but stop pointing the active symlink at them.
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗