claude-code - 💡(How to fix) Fix Auto-updater leaves orphan TCC entries for every previous CLI version on macOS

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…

The Claude Code CLI bundled with the Claude Desktop app (macOS) installs each new version into a versioned subdirectory:

~/Library/Application Support/Claude/claude-code/<VERSION>/claude.app

When a new version is staged, the user is re-prompted for the privacy permissions that the prior version had already been granted (Accessibility, AppleEvents/Automation, Files & Folders, Removable Volumes, etc.). Each grant becomes a new path-based row in macOS's TCC database. The updater never tells macOS to revoke the prior version's rows, so they accumulate as orphans whose binary no longer exists on disk.

After ~13 CLI version updates on my system, ~70 orphan rows had piled up across multiple Privacy & Security panels, plus one in the system-level TCC.db. The Privacy & Security panels (Files & Folders, Automation, Local Network, etc.) showed dozens of blank-icon "claude" / "claude.app" entries.

The homebrew install path (/opt/homebrew/lib/node_modules/@anthropic-ai/claude-code/bin/claude.exe) does not exhibit this — its path is stable across updates and TCC reuses the row.

Root Cause

Cosmetic / quality of life, not a security issue per se — the orphan rows are inert because their code-signing anchors are broken. But the Privacy & Security panels become very hard to audit when filled with phantom rows, and most users have no straightforward way to clean them (the macOS UI offers no per-row delete on Automation/Files & Folders/Local Network).

Fix Action

Fix / Workaround

Workaround (mitigation, not a fix)

Code Example

~/Library/Application Support/Claude/claude-code/<VERSION>/claude.app

---

sqlite3 -header -column ~/Library/Application\ Support/com.apple.TCC/TCC.db "
  SELECT service, client, client_type
  FROM access
  WHERE client LIKE '/Users/%/Library/Application Support/Claude/claude-code/%/claude'
    AND client_type = 1;
"

---

tccutil reset SystemPolicyDocumentsFolder /Users/.../claude-code/<OLDVER>/claude
tccutil reset SystemPolicyDesktopFolder   /Users/.../claude-code/<OLDVER>/claude

---

~/Library/Application Support/Claude/claude-code/current/claude.app   ← symlink to versioned dir
RAW_BUFFERClick to expand / collapse

Bug report — paste into https://github.com/anthropics/claude-code/issues

Title: Auto-updater leaves orphan TCC entries for every previous CLI version on macOS


Summary

The Claude Code CLI bundled with the Claude Desktop app (macOS) installs each new version into a versioned subdirectory:

~/Library/Application Support/Claude/claude-code/<VERSION>/claude.app

When a new version is staged, the user is re-prompted for the privacy permissions that the prior version had already been granted (Accessibility, AppleEvents/Automation, Files & Folders, Removable Volumes, etc.). Each grant becomes a new path-based row in macOS's TCC database. The updater never tells macOS to revoke the prior version's rows, so they accumulate as orphans whose binary no longer exists on disk.

After ~13 CLI version updates on my system, ~70 orphan rows had piled up across multiple Privacy & Security panels, plus one in the system-level TCC.db. The Privacy & Security panels (Files & Folders, Automation, Local Network, etc.) showed dozens of blank-icon "claude" / "claude.app" entries.

The homebrew install path (/opt/homebrew/lib/node_modules/@anthropic-ai/claude-code/bin/claude.exe) does not exhibit this — its path is stable across updates and TCC reuses the row.

Reproduction

  1. Use Claude Desktop and let the embedded CLI auto-update through ~5+ versions.
  2. Open System Settings → Privacy & Security → Files & Folders (or Automation, Local Network, Full Disk Access).
  3. Observe multiple blank-icon "claude" / "claude.app" entries, each corresponding to an old version's install path.

Verify in the TCC database:

sqlite3 -header -column ~/Library/Application\ Support/com.apple.TCC/TCC.db "
  SELECT service, client, client_type
  FROM access
  WHERE client LIKE '/Users/%/Library/Application Support/Claude/claude-code/%/claude'
    AND client_type = 1;
"

(Requires Full Disk Access on the running shell.)

Expected behavior

When the auto-updater stages a new version and removes the previous one, it should:

Option A — Call tccutil for each TCC service the old version had records in:

tccutil reset SystemPolicyDocumentsFolder /Users/.../claude-code/<OLDVER>/claude
tccutil reset SystemPolicyDesktopFolder   /Users/.../claude-code/<OLDVER>/claude

(Though note: tccutil reset resets by bundle ID, not arbitrary path, so this may require direct DB manipulation by an entitled helper.)

Option B — Install at a stable, versioned-via-symlink path:

~/Library/Application Support/Claude/claude-code/current/claude.app   ← symlink to versioned dir

…and request TCC permissions only via the current path. New versions update the symlink target; TCC keys reuse.

Workaround (mitigation, not a fix)

I've automated cleanup on my machine via a launchd agent that runs monthly. It:

  • Enumerates path-based TCC rows under ~/Library/Application Support/Claude/claude-code/*/claude
  • Tests whether each path still exists on disk
  • DELETEs rows for missing paths

This requires the running script to have Full Disk Access. It does not clean the system-level TCC.db (would need root).

The script and launchd plist are local — happy to share if useful.

Environment

  • macOS: <fill in: sw_vers -productVersion and build>
  • Claude Desktop version: <Settings → About>
  • Embedded CLI version: <~/Library/Application Support/Claude/claude-code/<current>/claude --version>
  • Homebrew npm-installed CLI version (if applicable): <claude --version>

Severity

Cosmetic / quality of life, not a security issue per se — the orphan rows are inert because their code-signing anchors are broken. But the Privacy & Security panels become very hard to audit when filled with phantom rows, and most users have no straightforward way to clean them (the macOS UI offers no per-row delete on Automation/Files & Folders/Local Network).

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

FAQ

Expected behavior

When the auto-updater stages a new version and removes the previous one, it should:

Option A — Call tccutil for each TCC service the old version had records in:

tccutil reset SystemPolicyDocumentsFolder /Users/.../claude-code/<OLDVER>/claude
tccutil reset SystemPolicyDesktopFolder   /Users/.../claude-code/<OLDVER>/claude

(Though note: tccutil reset resets by bundle ID, not arbitrary path, so this may require direct DB manipulation by an entitled helper.)

Option B — Install at a stable, versioned-via-symlink path:

~/Library/Application Support/Claude/claude-code/current/claude.app   ← symlink to versioned dir

…and request TCC permissions only via the current path. New versions update the symlink target; TCC keys reuse.

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING