[BUG] macOS: a running CLI session loses its TCC Documents grant mid-session — a new session and a new terminal window both stay broken; only quitting the host terminal app recovers it
Preflight
- [x] I have searched existing issues; the same signature is reported in #75374, but for the desktop app on an external volume and attributed to the auto-updater deleting the running version directory — that mechanism is ruled out here, and its stated workaround (start a new session) does not work for this variant. #64685 and #34270 (both closed) are the desktop app's
disclaimershim failing at session start, not a running session losing access. #66553 is the same TCC family but hook-scoped. - [x] This is a single bug report
- [x] I am using the latest version of Claude Code (2.1.219)
Summary
A running claude session on macOS lost its TCC grant for the working directory partway through, with no update, crash, or user action. Every open and readdir under ~/Documents began failing with EPERM, while $HOME, ~/Desktop, ~/Library and /private/tmp continued to work normally and stat kept succeeding everywhere.
The part worth reporting is the recovery behaviour. Starting a new session does not fix it. Opening a new terminal window does not fix it. Only quitting the host terminal application does. A new window is a new shell and a new claude process but the same Terminal.app process, and it stays broken — which locates the lost grant at the host application, not at anything Claude Code owns per session.
This has happened twice on the same machine in one day.
Reproduction
I do not have a deterministic reproduction. It has occurred twice, both times in long-running sessions (~1h40m and several hours) doing heavy filesystem work across many subagents. What follows is the state captured while broken, and the recovery ladder tested in one sitting.
Access matrix while broken:
path readdir stat
/Users/<user> OK OK
/Users/<user>/Desktop OK OK <- read AND write both fine
/Users/<user>/Documents DENIED OK
/Users/<user>/Documents/<workspace> DENIED OK
/Users/<user>/Library/Logs/Claude OK OK
/private/tmp OK OK
/System/Volumes/Data/Users/<user>/Documents/... DENIED OK <- firmlink, same denial
$ stat -f '%z' ~/Documents/<workspace>/spock/AGENTS.md
5428 # metadata fine
$ wc -c < ~/Documents/<workspace>/spock/AGENTS.md
zsh: operation not permitted # open() denied
~/Desktop reading and writing fine while ~/Documents is denied is the key observation: those are separate TCC services, so this is a service-specific grant loss rather than a sandbox or filesystem fault.
Also affected: the native Read tool (EPERM: operation not permitted, open '...'), git (fatal: Unable to read current working directory: Operation not permitted), and every subagent, since they inherit the process tree — which makes it look like independent confirmation of a filesystem problem and actively reinforces a misdiagnosis.
Recovery ladder, tested in order:
| Action | Result |
|---|---|
| Quit claude, relaunch in the same terminal window | Fails — EPERM |
| Open a new terminal window (same Terminal.app pid), launch claude | Fails |
| Quit Terminal.app (⌘Q), reopen, launch claude | Works — access restored immediately |
| Reboot | Also works, but is unnecessary |
Why #75374's mechanism does not apply
#75374 attributes this signature to the auto-updater deleting the running version directory, leaving tccd unable to validate the responsible process's code signature. Checked directly:
- The running binary still exists:
~/.local/share/claude/versions/2.1.219, confirmed present and confirmed as thetxtmapping of the session pid vialsof. - No deleted-but-open files for that pid.
- The only
Removing old versionentries in~/Library/Logs/Claude/main.logare from two days earlier and concern the desktop app's copy of claude-code under~/Library/Application Support/Claude/claude-code/— a different program from the CLI in use. The updater loggedStaged version … is still currentthroughout the session window.
The responsible process for TCC attribution here is Terminal.app, via claude ← zsh ← login ← Terminal.app ← launchd.
Why this matters
The failure presents as filesystem corruption, a stuck lock, or a broken session rather than as a permissions problem: stat works, $HOME works, the network works, and only the project path is dead. Subagents spawned to investigate inherit the same broken process tree and independently "confirm" the wrong diagnosis. Both occurrences cost a substantial diagnostic detour, and the first was resolved by a full reboot that turned out to be unnecessary.
Expected
Any of, in preference order:
- A running session should not lose its TCC grant for its own working directory absent an update, crash, or user action.
- If the grant is lost, detect the
EPERM-on-a-TCC-protected-path condition and tell the user what it is and that quitting the host terminal application restores it — currently nothing distinguishes it from a filesystem fault. - At minimum, document the failure mode and the terminal-restart recovery, since "start a new session" (the workaround given in #75374) is misleading for this variant.
Related issues
- #75374 — same signature, desktop app on an external volume, attributed to the auto-updater; its workaround does not apply here
- #64685, #34270 (closed) — desktop
disclaimershim losing the~/Documentsgrant at session start - #66553 — WorktreeCreate hook
EPERMfor repos under~/Documents
Is this a regression?
I don't know — I haven't tested earlier versions. Both occurrences were on 2.1.219.
Environment
- Claude Code: 2.1.219, native CLI install (
~/.local/share/claude/versions/2.1.219via~/.local/bin/claude), launched from Terminal.app — not the desktop app - macOS Darwin 25.4.0, Apple Silicon
- Project on the internal APFS volume under
~/Documents - Model: claude-opus-5[1m]