CLI auto-updater doesn't clean up old binaries, triggers repeated macOS TCC permission dialogs

Open 💬 7 comments Opened Apr 15, 2026 by tristandemontebello

Summary

The native CLI installer accumulates old version binaries in ~/.local/share/claude/versions/ without cleanup. Each new binary is a distinct code-signed Mach-O executable, which causes macOS TCC to treat each version as a new app — triggering fresh permission dialogs for Downloads, Photos, Documents, etc.

Environment

  • macOS 15 (Darwin 25.3.0), Apple Silicon
  • Claude Code installed via native installer (not Homebrew)
  • CLI invoked headlessly via LaunchAgents (claude -p)

Reproduction

  1. Install Claude Code CLI natively
  2. Let auto-updater run for a few days
  3. Check ~/.local/share/claude/versions/ — multiple ~200MB binaries accumulate (6 versions = 1.1GB in my case)
  4. The symlink at ~/.local/bin/claude points to the latest, but old versions remain on disk
  5. macOS shows permission dialogs like "2.1.108" would like to access files in your Downloads folder — using the version number as the app name since the binary is named by version, not "claude"

Impact

  • Disk waste: Each binary is ~200MB. No cleanup means unbounded growth.
  • TCC dialog spam: Each new version triggers fresh macOS privacy consent dialogs. For interactive users this is a minor annoyance (click Allow once). For headless/LaunchAgent usage, dialogs pile up while the user is AFK.
  • The version number appears as the app name in the dialog because the binary filename is 2.1.109, not claude. Users won't know what's asking for access.

Suggested fixes

  1. Clean up old binaries after a successful update (keep current + one previous for rollback)
  2. Preserve TCC grants across updates — if the designated code requirement stays the same, macOS should carry forward permissions. The current layout (new standalone binary per version) defeats this.
  3. Name the binary claude (or wrap it in a .app bundle with a stable name) so TCC dialogs show a recognizable app name instead of a version number

Workaround

Manual cleanup: cd ~/.local/share/claude/versions/ && ls | grep -v <current_version> | xargs rm

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

View original on GitHub ↗

This issue has 7 comments on GitHub. Read the full discussion on GitHub ↗