5 min read
Dec 22, 2025

This project started with a noble cause. I wanted to shutdown my remote machine (a DGX Spark) any time I shut down my local machine (my MacBook Pro). Simple enough, right? What followed was a weekend-long deep dive into macOS internals that taught me more about the operating system than I ever expected.
The setup was straightforward: I have a DGX Spark on my local network that I SSH into for ML workloads. When I'm done for the day and shutdown my Mac, I want the Spark to shutdown too. No need to remember to SSH in and run sudo shutdown -h now separately.
My first attempt was a Go application that would listen for the shutdown signal and then SSH to the remote machine to send the shutdown command. I learned about the deprecated LogoutHook mechanism that macOS provides through com.apple.loginwindow.
The LogoutHook is set via:
sudo defaults write com.apple.loginwindow LogoutHook /path/to/script.shBut here's the thing about LogoutHook: it's deprecated. Apple doesn't recommend it for new development. And when I tested it, it simply didn't trigger during shutdown. The hook is supposed to run when the user logs out, but the behavior during system shutdown was unreliable.
This is where I went down the rabbit hole. I learned about launchd, Apple's replacement for the traditional Unix init system. The concept is elegant:
~/Library/LaunchAgents/) - Run in user context when you log in/Library/LaunchDaemons/) - Run at system boot as rootI created a plist file that would start a shell script at boot. The script would run tail -f /dev/nullto stay alive (since macOS's sleep command doesn't support infinity like Linux does), and use trap to catch SIGTERM:
trap shutdown_remote SIGTERM # Keep the script running tail -f /dev/null & wait $!
I discovered a helpful plist key from Apple's own system daemons:
<key>AlwaysSIGTERMOnShutdown</key> <true/>
This guarantees that launchd sends SIGTERM to your daemon during shutdown. Combined withExitTimeOut, you get a window to perform cleanup before SIGKILL.
Here's where everything fell apart. My daemon was receiving SIGTERM correctly, but by the time it tried to SSH to the remote machine, the network was already down. I saw errors like:
ssh: Could not resolve hostname spark-45ca.local: nodename nor servname providedThe mDNS/Bonjour service (which resolves .local hostnames) had already been terminated. Okay, I thought, I'll just use the IP address directly. But then:
ssh: connect to host 192.168.2.17 port 22: No route to hostThe network interface itself was already down. macOS was tearing down services in an order that made my use case impossible. My daemon was getting SIGTERM, but it was too late. The dependencies I needed (networking, DNS) were already gone.
After a weekend of experimentation, I gained a deep appreciation for macOS's shutdown sequence:
bootstrap, bootout, enable, start)If there were a way to prioritize my daemon so that it executes first in the shutdown order, this would probably work. I haven't found a reliable way to ensure that my script runs before the network stack is torn down.
Some ideas I didn't fully explore:
This project is dead at this point. But the time wasn't wasted. I learned more about macOS development in one weekend than I had in years of using the platform. Sometimes the journey is the destination.
The code is still on my GitHub if anyone wants to pick up where I left off. Maybe someone smarter than me will figure out how to win the race against macOS's shutdown sequence.
**This article was principally written by an AI agent, using context from a coding session with small additions, written portions by me (Naeem).