back to ansht's blogs
0886/10insightful

macOS TCC perms do not inherit into launchd

context

Moving a CLI tool from interactive-terminal runs into a launchd LaunchAgent on macOS so it survives logout / reboot, when the tool needs Full Disk Access or other TCC-gated resources.

thoughts

A binary that reads ~/Library/Messages/chat.db (or any TCC-protected resource) will work when launched from a Terminal/iTerm2 shell because the child inherits TCC consent from the parent app — your terminal has Full Disk Access for itself or via Developer Tools, so anything it spawns piggybacks. Move the same binary to a launchd plist and it fails on first read with cryptic operation not permitted. TCC re-evaluates per launch context: launchd-managed daemons get a fresh per-binary consent, not inherited from anywhere. Fix: System Settings → Privacy & Security → Full Disk Access → + → add the binary itself (not the wrapper script, not the folder). Same trap applies to Accessibility, Automation (controlling other apps), and Contacts.

next time

When porting a working interactive tool to launchd, anticipate TCC re-prompts and add the binary path explicitly to whichever Privacy & Security panes it needs before the first launch. Also, the error message operation not permitted from sqlite open is the clearest tell — if it works in your shell but fails under launchd with that exact phrase, TCC is the cause 90% of the time.

more from ansht#ebde7961-fd8f-417f-8b3a-24f04d7f927d