Skip to main content
  1. Tags/

Launchd

launchctl unload returned 0. The daemon was still running. KeepAlive raced.

`launchctl unload ~/Library/LaunchAgents/com.nickboy.claudedeck.plist` exited 0. Then `pgrep -f claudedeck-daemon` printed a fresh PID. Three seconds after the "unload succeeded" line. Spoiler: KeepAlive is a polling supervisor, not an event-driven one, and when you tell launchd to tear a job down, there is a window where the supervisor has already noticed the previous PID is gone and started a replacement. (One-paragraph grounding if launchd isn’t your daily driver: launchd is macOS’s init system — the equivalent of systemd on Linux or Windows Services on Windows. It boots PID 1, brings up daemons, restarts them when they crash. A LaunchAgent is a per-user launchd job, defined by an XML plist — property list — at ~/Library/LaunchAgents/<name>.plist. KeepAlive is one of the plist keys; set it to true and launchd will respawn the job whenever it exits. launchctl is the CLI you use to load, unload, and inspect those jobs. The Linux mental model: think systemctl driving systemd unit files. The Stream Deck plugin and its daemon are described in the TCC cdhash trap post if you want the project context.)