Schedule with launchd
Load, test, and remove the job
Validate a LaunchAgent, start it in the user domain, inspect state and logs, then remove it cleanly.
10 minute lesson
The plist exists and the environment is pinned down. Now hand the job to launchd, watch it run, and — just as deliberately — take it back out.
Validate the property list before loading it:
plutil -lint ~/Library/LaunchAgents/com.flaviocopes.screenshot-sorter.plist
# OK
Load it into your user’s GUI domain with bootstrap, force an immediate run with kickstart, and inspect it with print. Use the current user domain and label when inspecting the job:
launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.flaviocopes.screenshot-sorter.plist
launchctl kickstart -k gui/$(id -u)/com.flaviocopes.screenshot-sorter
launchctl print gui/$(id -u)/com.flaviocopes.screenshot-sorter
kickstart -k runs the job now instead of waiting up to fifteen minutes for StartInterval, which makes testing bearable. The print output is dense, but three parts matter: the state, the last exit code, and the program it resolved. For a quicker glance, launchctl list | grep screenshot shows the PID (or - when idle) and the last exit status. Then confirm the job did its actual work: check the log files and the destination folder.
If bootstrap answers Bootstrap failed: 5: Input/output error, the job is usually already loaded — boot it out first — or the plist has a problem plutil cannot see, like a program path that is not executable.
These are the launchctl subcommands documented by the installed macOS release. Older tutorials use load and unload; they still work but are the legacy interface. When in doubt, trust man launchctl on your machine over a blog post.
Removal is bootout:
launchctl bootout gui/$(id -u)/com.flaviocopes.screenshot-sorter
Record the exact removal step in the runbook while it is fresh. After removal, confirm the label no longer appears in launchctl list and the process has stopped. Keep the property list until the uninstall check passes, so you can reload and retest if removal reveals a problem.
Lesson completed