Watchdog
Scheduling gob watchdog on macOS (launchd)
To clean up forgotten VMs automatically, schedule gob watchdog with a
user-level launchd agent. The example below runs it every hour, on the hour.
-
Find the absolute path to your
gobbinary β launchd does not inherit your shellPATH:which gob # e.g. /Users/you/.cargo/bin/gob -
Create
~/Library/LaunchAgents/com.goblinmode.watchdog.plist. Replace the<string>values markedREPLACE_MEwith the path from step 1 and your home directory:<?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.goblinmode.watchdog</string> <key>ProgramArguments</key> <array> <string>REPLACE_ME/.cargo/bin/gob</string> <string>watchdog</string> <string>--max-age</string> <string>8</string> </array> <key>StartCalendarInterval</key> <dict> <key>Minute</key> <integer>0</integer> </dict> <key>StandardOutPath</key> <string>REPLACE_ME/Library/Logs/goblinmode-watchdog.log</string> <key>StandardErrorPath</key> <string>REPLACE_ME/Library/Logs/goblinmode-watchdog.log</string> <key>EnvironmentVariables</key> <dict> <key>PATH</key> <string>/usr/local/bin:/opt/homebrew/bin:/usr/bin:/bin</string> </dict> </dict> </plist> -
Load it (it will also start automatically on each login):
launchctl load ~/Library/LaunchAgents/com.goblinmode.watchdog.plist -
Tail the log to confirm itβs running:
tail -f ~/Library/Logs/goblinmode-watchdog.log
To stop it, run launchctl unload ~/Library/LaunchAgents/com.goblinmode.watchdog.plist.
To run it once on demand without waiting for the next tick, run launchctl start com.goblinmode.watchdog.
A note on secrets
Launchd jobs run with a restricted environment. If your config.toml
uses _cmd fields that depend on tools requiring a terminal or keychain
unlock (e.g. op, security), the watchdog may fail to authenticate.
The most reliable options for an unattended agent are:
- plain-text tokens in
~/.config/goblinmode/config.toml, or EnvironmentVariablesin the plist (e.g.HETZNER__API_TOKEN,TAILSCALE__API_KEY).
Either way, treat the plist file as sensitive and chmod 600 it if you
embed secrets.