Recently, I read how to "prevent link riot in my obsidian vault" and I wanted to do something similar. The author wrote a small CLI utility, called wayback-archiver and a script that greps links from markdown files in a directory which then executes the archiver utility to archive the collected links. But how should this be automated in macOS? Crontab comes to mind immediately, but opening the man page shows that it has been deprecated.

DESCRIPTION
     [...]

     (Darwin note: Although cron(8) and crontab(5) are officially supported
     under Darwin, their functionality has been absorbed into launchd(8), which
     provides a more flexible way of automatically executing commands.  See
     launchctl(1) for more information.)

The man page for launchd shows that we should use launchctl.

The primary and preferred interface to launchd is via the launchctl(1) tool
     which (among other options) allows the user or administrator to load and
     unload jobs. Where possible, it is preferable for jobs to launch on demand
     based on criteria specified in their respective configuration files.

Creating a launch daemon

To configure a job, we need to create a launchd Property List File in ~/Library/LaunchAgents. For example, ~/Library/LaunchAgents/com.example.archive-links.plist. In my case, I want to run a script weekly to make sure all links I have in my notes are archived.

<?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>fish.flo.archive-links</string>
    <key>ProgramArguments</key>
    <array>
        <string>archive-links.sh</string>
        <string>~/source/obsidian</string>
    </array>
    <key>StartCalendarInterval</key>
    <dict>
        <key>Minute</key>
        <integer>45</integer>
        <key>Hour</key>
        <integer>13</integer>
        <key>Weekday</key>
        <integer>0</integer>
    </dict>
</dict>
</plist>

Queuing the job

Now we need to load the script.

  • launchctl list shows the currently running agents/daemons
  • launchctl load ~/Library/LaunchAgents/fish.flo.archive-links.plist loads the script → now it is queued to run at the specified time

Links

  • https://www.launchd.info/
  • https://developer.apple.com/library/archive/documentation/MacOSX/Conceptual/BPSystemStartup/Chapters/CreatingLaunchdJobs.html#/apple_ref/doc/uid/10000172i-SW7-BCIEDDBJ
  • https://benjamincongdon.me/blog/2021/09/19/Preventing-Link-Rot-in-my-Obsidian-Vault/