macOS TCC permissions for unattended AI agents: stop losing nights to hidden prompts
If you run AI agents unattended on a Mac (Claude Code in iTerm, a launchd job driving osascript, Hammerspoon clicking buttons), you've probably woken up to find nothing happened overnight. The cause is usually one dialog
If you run AI agents unattended on a Mac (Claude Code in iTerm, a launchd job driving osascript, Hammerspoon clicking buttons), you've probably woken up to find nothing happened overnight. The cause is usually one dialog sitting on an unwatched screen: "Terminal" would like to control "System Events".
That's macOS TCC (Transparency, Consent and Control). Here's how to set it up once so it stops eating your nights.
The key idea: permissions belong to the host app
TCC grants go to the app that launches the process, not to your script. If claude runs inside iTerm, iTerm needs the grant. If a launchd job runs /bin/bash script.sh, the grant goes to whatever binary macOS names in the prompt.
So the first rule is: pick one terminal app as your agent host and grant everything there. Spreading agents across Terminal, iTerm, Warp and VS Code means four sets of grants that drift out of sync.
What each agent task needs
| Agent task | Privacy & Security pane |
|---|---|
| Click/type into other apps (AX, Hammerspoon) | Accessibility |
osascript controlling another app |
Automation (once per target app) |
| Screenshots / screen reading | Screen & System Audio Recording (relaunch after granting) |
| ~/Documents, Desktop, Downloads | Files and Folders |
| Mail, Messages, Safari data | Full Disk Access (only if really needed) |
| Global hotkeys | Input Monitoring |
Trigger the prompts while you're watching
Automation prompts only appear the first time an app tries to control a target. Run each one deliberately during setup, not at 3am:
osascript -e 'tell application "System Events" to get name of first process'
osascript -e 'tell application "Finder" to get name of startup disk'
Click Allow on each, then you're done for that host/target pair.
A read-only health check before bed
Don't edit the TCC database (and don't disable SIP). Just check that things still work:
osascript -e 'tell application "System Events" to get name of first process' >/dev/null 2>&1 \
&& echo "automation OK" || echo "automation BROKEN"
screencapture -x /tmp/tcc-check.png && echo "screen OK"
If either fails, fix it now instead of finding out in the morning.
After macOS updates
Updates and app re-signing can silently invalidate grants: the toggle still looks on, but it no longer applies. The fix that works most often is to remove the app from the list with the minus button, add it back, and relaunch it.
The free first-time setup checklist is on GitHub: agent-ops-samples.
The full macOS TCC Agent Fleet Runbook ($12) adds the complete permission map, symptom-to-fix recovery steps and a fleet log for tracking grants across machines.
Originally published by Dev.to AI. Aggregated on AIWithGhost for educational purposes β full credit and traffic to the original publisher.