claude-code - 💡(How to fix) Fix [BUG] Headless 'claude -p' fires TCC permission dialogs from startup probes unrelated to operational scope - request --no-startup-probe flag

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…

Headless claude -p invocations from launchd-fired pollers on macOS trigger interactive TCC permission dialogs at the foreground UI for filesystem scopes the operation does not need. Once a previously-granted scope is revoked, the next launchd fire re-prompts. Asking for a startup-probe-disable flag (env var or CLI flag) so headless invocations can skip TCC-protected probes that are unrelated to the requested operation.

Root Cause

Headless claude -p invocations from launchd-fired pollers on macOS trigger interactive TCC permission dialogs at the foreground UI for filesystem scopes the operation does not need. Once a previously-granted scope is revoked, the next launchd fire re-prompts. Asking for a startup-probe-disable flag (env var or CLI flag) so headless invocations can skip TCC-protected probes that are unrelated to the requested operation.

Fix Action

Fix / Workaround

Workaround in place today

RAW_BUFFERClick to expand / collapse

Summary

Headless claude -p invocations from launchd-fired pollers on macOS trigger interactive TCC permission dialogs at the foreground UI for filesystem scopes the operation does not need. Once a previously-granted scope is revoked, the next launchd fire re-prompts. Asking for a startup-probe-disable flag (env var or CLI flag) so headless invocations can skip TCC-protected probes that are unrelated to the requested operation.

Context

Two long-running launchd jobs on a Mac mini invoke Claude Code in headless mode:

  • An "exec poller" that polls Notion every 60 minutes and claims work via claude -p "$(cat exec-poller.txt)" --model claude-sonnet-4-6.
  • A "closeout poller" that polls GitHub every 30 minutes and reconciles merged PRs via claude -p "$(cat closeout-poller.txt)" --model claude-haiku-4-5.

Both are scoped to specific MCP tools (Notion, GitHub), and both operationally need only:

  • ~/.claude/, ~/.claude.json
  • ~/Library/Application Support/Claude/, ~/Library/Caches/Claude/, ~/Library/Logs/
  • ~/.npm/ (for npx-resolved MCP servers)
  • ~/Projects/ (for project repos under poller automation)
  • ~/Obsidian Vault/ (for memory writes)
  • Network (Notion API, GitHub API, Anthropic API)

What we observed

Each claude -p startup probes filesystem locations beyond that operational scope. Captured via sudo fs_usage -w -f filesys against both pollers. Per-fire counts of probes into TCC-protected scopes:

ScopeExec hitsCloseout hits
~/Desktop/6045
~/Documents/13454
~/Downloads/4433
~/Movies/129
~/Music/129
~/Pictures/129
~/Public/4433

None of these are operationally needed by either poller.

What goes wrong in production

When the user has previously revoked one of these scopes from Claude Code's TCC entries (during a security audit, for example), macOS surfaces an interactive permission dialog the next time the poller fires. The dialog appears at the foreground UI even though the poller is running in the background under launchd. The user sees an apparently-spontaneous "Claude would like to access files in your Downloads folder" dialog at random times of day, with no active foreground Claude Code session.

Three Claude identities probe independently in this environment:

  • The path-based binary at /opt/homebrew/Caskroom/claude-code/<version>/claude.
  • The CLI bundle ID com.anthropic.claude-code.
  • The desktop app bundle ID com.anthropic.claudefordesktop.

Granting the scope to one identity does not stop the others from re-prompting.

What we'd like

A way to tell claude -p to skip startup probes that aren't required by the requested operation. Two shapes that would work:

  1. A CLI flag, e.g. --no-startup-probe or --minimal-fs-scope, that opts out of the speculative probes.
  2. An environment variable, e.g. CLAUDE_SKIP_STARTUP_PROBE=1, with the same effect. This would be the easier integration point for a launchd run-poller.sh wrapper.

Either form would let pollers run with a deterministic, narrow filesystem footprint, removing the random-dialog UX problem and tightening the security posture.

Workaround in place today

Documented the minimal grant set the pollers actually need. Deny all dialogs that fall outside it. Works but reproduces every time TCC state changes. The product-side fix would be more robust.

Reproduction steps

  1. Configure a launchd plist that fires claude -p "<some prompt>" --model claude-sonnet-4-6 on a schedule (e.g. hourly).
  2. From System Settings -> Privacy & Security -> Files and Folders, revoke a scope from Claude Code that the prompt does not need (e.g. Downloads).
  3. Wait for the next launchd fire.
  4. Observe the permission dialog appear at the foreground UI despite no interactive Claude Code session being active.

Minimal repro: claude -p "echo hello" against a launchd-fired plist with one scope revoked is sufficient.

Versions

  • macOS: 26.4
  • Claude Code: 2.1.118 (also reproduces in 2.1.119)
  • Hardware: Apple Silicon Mac mini

Additional info

Happy to provide the full fs_usage traces if useful (around 130k lines per fire, captured at filesys depth, around 30 MB raw).

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…

Still need to ship something?

×6

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

Back to top recommendations

TRENDING