Problem
hermes gateway restart hangs indefinitely on macOS when the gateway is managed by launchd with KeepAlive/SuccessfulExit = false.
Root cause
launchd_restart() in hermes_cli/gateway.py does:
launchctl stop <label> — sends SIGTERM
_wait_for_gateway_exit() — polls until the PID disappears
launchctl start <label>
But with KeepAlive/SuccessfulExit = false, launchd immediately respawns the process after stop, so step 2 never completes — the old PID dies but a new one appears instantly.
Fix
Use launchctl kickstart -kp gui/<uid>/<label> which atomically kills and restarts the service in one operation, avoiding the race. Falls back to the old stop/wait/start sequence if kickstart fails (e.g., on older macOS).
Environment
- macOS (tested on M4 Max, Sequoia)
- launchd plist with KeepAlive/SuccessfulExit = false