Schedule with launchd

Write a minimal LaunchAgent

Create a valid property list with a unique label, explicit program arguments, and one deliberate trigger.

10 minute lesson

~~~

A launchd job is described by a property list: an XML file that says what to run and when. Here is a complete, minimal LaunchAgent:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
  "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>Label</key>
  <string>com.flaviocopes.screenshot-sorter</string>
  <key>ProgramArguments</key>
  <array>
    <string>/Users/flavio/bin/sort-screenshots</string>
  </array>
  <key>StartInterval</key>
  <integer>900</integer>
</dict>
</plist>

Save it as ~/Library/LaunchAgents/com.flaviocopes.screenshot-sorter.plist. Matching the filename to the label is a convention worth keeping: six months from now, the filename is how you will find the job.

Three keys, three decisions.

Label is the job’s identity in your user’s launchd domain. Use a reverse-domain label, unique on the machine. Every launchctl command you run later refers to it.

ProgramArguments lists the executable and its arguments, one <string> per element. Use an absolute executable path, because launchd resolves nothing for you. And do not put shell operators inside ProgramArguments; launchd starts the executable directly, so a > or && in there arrives as a literal argument to your program, not as redirection. If the job needs shell features, put them inside the script.

StartInterval is the trigger: run every 900 seconds. Other triggers exist — StartCalendarInterval for clock times, WatchPaths for reacting to file changes, RunAtLoad for login — but keep the first job small. Add only one trigger, then prove when and why it runs before adding more conditions.

Validate the complete file with plutil -lint:

plutil -lint ~/Library/LaunchAgents/com.flaviocopes.screenshot-sorter.plist
# .../com.flaviocopes.screenshot-sorter.plist: OK

A malformed plist is the most common first failure, and launchd’s own complaint about it is unhelpfully generic. plutil points at the exact line. Nothing runs yet, though: writing the file registers nothing with launchd. Loading it comes in a later lesson, after we pin down the job’s environment.

Lesson completed

Take this course offline

Get every free book and course as PDF and EPUB files.

Get the download library →