Scheduling Tasks With launchd

macOS a robust tool for scheduling automated tasks: launchd. While quite different for those used to cron, it’s a pretty great tool for scheduling jobs.

The backstory is that I use the command-line task manager TaskWarrior for managing my todo items and I recently setup a sync server to share data between my personal and work computers. However, TaskWarrior requires manually syncing data by running task sync. This is annoying, so I thought, why not run this automatically?

That’s where launchd comes in! I created a simple config that will run at 8:30 and 5:30 each day, in addition to running on a 10 minute interval throughout the day.

dev.mskelton.task-sync.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
  <dict>
    <key>Label</key>
    <string>dev.mskelton.task-sync</string>
    <key>ProgramArguments</key>
    <array>
      <string>/opt/homebrew/bin/task</string>
      <string>sync</string>
    </array>
    <key>StartInterval</key>
    <integer>600</integer>
    <key>StartCalendarInterval</key>
    <array>
      <dict>
        <key>Hour</key>
        <integer>8</integer>
        <key>Minute</key>
        <integer>30</integer>
      </dict>
      <dict>
        <key>Hour</key>
        <integer>17</integer>
        <key>Minute</key>
        <integer>30</integer>
      </dict>
    </array>
  </dict>
</plist>

Drop this file in ~/Library/LaunchAgents/ and running the following command to start the schedule.

launchctl bootstrap "gui/$(id -u)" ~/Library/LaunchAgents/dev.mskelton.task-sync.plist

If you make edits to the config, run the following to reload the config.

path=~/Library/LaunchAgents/dev.mskelton.task-sync.plist
launchctl bootout "gui/$(id -u)" $path
launchctl bootstrap "gui/$(id -u)" $path

Now sit back and enjoy the beauty of macOS doing work for you! I was very pleasantly surprised with how well this worked, haven’t had to manually sync my tasks at all since adding this.