CLI updater's symlink-swap breaks TCC Automation grants on every update (repeated 'would like to access data from other apps' prompts)
Summary
The standalone CLI installer (~/.local/bin/claude → ~/.local/share/claude/versions/<version>) updates itself by writing a new version-numbered binary and repointing the claude symlink to it. Each new version file is a bare Mach-O executable rather than a stable, code-signed .app bundle with a persistent bundle identifier.
Because macOS TCC's Automation (kTCCServiceAppleEvents) grants for an unbundled executable are keyed to the resolved binary path, every CLI self-update produces a brand-new TCC client identity. Any automation the CLI performs (in my case, AppleScript bridges that drive Mail.app and Calendar.app) re-triggers the "<version> would like to access data from other apps" consent dialog after every single update — indefinitely, on every future release.
Evidence
Reading (read-only) ~/Library/Application Support/com.apple.TCC/TCC.db:
/Users/me/.local/share/claude/versions/2.1.186|com.apple.iCal|2
/Users/me/.local/share/claude/versions/2.1.186|com.apple.mail|2
/Users/me/.local/share/claude/versions/2.1.207|com.apple.iCal|2
/Users/me/.local/share/claude/versions/2.1.207|com.apple.mail|2
Each CLI version gets its own separate grant row, keyed on the full versioned path. Compare this with the Desktop app's bundled copy, which registers consistently as com.anthropic.claude-code across versions and does NOT re-prompt on update — because it's a properly code-signed .app bundle with a stable identifier.
$ ls -la ~/.local/bin/claude
lrwxr-xr-x ... claude -> /Users/me/.local/share/claude/versions/2.1.207
$ codesign -dv --verbose=4 "<Desktop app>/claude-code/2.1.205/claude.app"
Identifier=com.anthropic.claude-code
Authority=Developer ID Application: Anthropic PBC (Q6L2SF6YDW)
TeamIdentifier=Q6L2SF6YDW
Notarization Ticket=stapled
Impact
Every CLI auto-update silently generates a fresh "unknown app wants automation access" system dialog, showing a bare version number (not "Claude") as the requesting app name — confusing and easy to mistake for something suspicious, and it recurs forever as long as the updater keeps swapping to a new versioned path.
Suggested fix
Either:
- Keep the installed binary at a stable path across updates (overwrite in place, or symlink through one fixed intermediate path that itself never changes) so TCC's path-based grant survives updates, or
- Properly code-sign the standalone CLI binary with a persistent Developer ID / bundle identifier the same way the Desktop-bundled copy is signed, so TCC can recognize it as the same app regardless of install path.
Either would stop the standalone CLI from re-triggering Automation consent on every release.