Service Management on macOS
On macOS, the standard way to manage background services is through launchd and LaunchAgent. Similar to systemd on Linux, launchd is the macOS system service manager, and LaunchAgent specifically manages user-level background processes. Since OpenClaw, as an AI Agent gateway, needs to run continuously to receive messages from chat platforms like WhatsApp, Telegram, and Discord, configuring it as a LaunchAgent daemon is the best practice on macOS.
Automatic Installation
OpenClaw provides a one-command daemon installation. On macOS, it automatically creates the LaunchAgent configuration:
openclaw onboard --install-daemon
After running this, OpenClaw will automatically create a plist configuration file in the ~/Library/LaunchAgents/ directory. You can verify the installation with:
launchctl list | grep openclaw
If you see an openclaw-related entry in the output, the daemon has been configured successfully. If the automatic installation doesn't work or you want to customize the configuration, continue reading the manual configuration section.
Prerequisites
Before starting the manual configuration, ensure the following conditions are met:
- macOS system (Ventura 13 and later supported)
- Node.js 22+ installed (do not use Bun, as it has known bugs when handling WhatsApp and Telegram connections)
- OpenClaw installed via
npm install -g openclaw@latest - Initial configuration completed by running
openclaw onboard
Confirm that OpenClaw runs properly:
openclaw --version
openclaw doctor
Creating the LaunchAgent Configuration File
The LaunchAgent configuration file is an XML-format plist file stored in ~/Library/LaunchAgents/.
First, confirm the OpenClaw installation path:
which openclaw
Common paths are /usr/local/bin/openclaw or /opt/homebrew/bin/openclaw. Note this path.
Create the plist file:
nano ~/Library/LaunchAgents/com.openclaw.agent.plist
Enter the following content:
<?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.openclaw.agent</string>
<key>ProgramArguments</key>
<array>
<string>/usr/local/bin/openclaw</string>
<string>start</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<dict>
<key>SuccessfulExit</key>
<false/>
<key>NetworkState</key>
<true/>
</dict>
<key>ThrottleInterval</key>
<integer>5</integer>
<key>EnvironmentVariables</key>
<dict>
<key>PATH</key>
<string>/usr/local/bin:/opt/homebrew/bin:/usr/bin:/bin</string>
<key>NODE_ENV</key>
<string>production</string>
</dict>
<key>StandardOutPath</key>
<string>/tmp/openclaw.stdout.log</string>
<key>StandardErrorPath</key>
<string>/tmp/openclaw.stderr.log</string>
<key>ProcessType</key>
<string>Background</string>
</dict>
</plist>
Replace /usr/local/bin/openclaw with your actual OpenClaw path. If you installed Node.js via Homebrew, the path may be /opt/homebrew/bin/openclaw.
Configuration Explained
- Label: Unique identifier for the service, using reverse domain name format
- RunAtLoad: Set to true to auto-start when the user logs in
- KeepAlive: Configures the auto-restart policy.
SuccessfulExitset to false means auto-restart on abnormal exit;NetworkStateset to true means run only when the network is available - ThrottleInterval: Minimum seconds between restarts after a crash, preventing frequent restarts
- EnvironmentVariables: Ensures PATH includes the paths to Node.js and OpenClaw
- ProcessType: Marked as a background process; macOS optimizes resource scheduling accordingly
Loading and Managing the Service
Load the Service
launchctl load ~/Library/LaunchAgents/com.openclaw.agent.plist
Start the Service
launchctl start com.openclaw.agent
Check Service Status
launchctl list | grep openclaw
The first column in the output is the PID (Process ID) — if it's non-zero, the service is running. The second column is the exit status code; 0 indicates normal.
Stop the Service
launchctl stop com.openclaw.agent
Unload the Service
launchctl unload ~/Library/LaunchAgents/com.openclaw.agent.plist
Viewing Logs
OpenClaw's standard output and error logs are saved at the paths we configured:
tail -f /tmp/openclaw.stdout.log
tail -f /tmp/openclaw.stderr.log
If you want to save logs to a more persistent location, modify StandardOutPath and StandardErrorPath in the plist to:
<key>StandardOutPath</key>
<string>/Users/your-username/.openclaw/logs/stdout.log</string>
<key>StandardErrorPath</key>
<string>/Users/your-username/.openclaw/logs/stderr.log</string>
Remember to create the log directory first:
mkdir -p ~/.openclaw/logs
Reloading After Configuration Changes
When you modify the plist file or OpenClaw's configuration file ~/.openclaw/openclaw.json, you need to reload the service:
launchctl unload ~/Library/LaunchAgents/com.openclaw.agent.plist
launchctl load ~/Library/LaunchAgents/com.openclaw.agent.plist
Accessing the Dashboard
Once the service is running, you can access the OpenClaw dashboard through your browser:
openclaw dashboard
Or open http://localhost:3000 directly in your browser.
Troubleshooting
If the service fails to start, follow these steps to diagnose:
- Check plist syntax:
plutil -lint ~/Library/LaunchAgents/com.openclaw.agent.plist - View system logs:
log show --predicate 'senderImagePath CONTAINS "openclaw"' --last 5m - Check error logs:
cat /tmp/openclaw.stderr.log - Test manual run:
openclaw start, and observe for errors - Verify path correctness: Ensure the
ProgramArgumentspath in the plist points to the actual openclaw executable - Run diagnostics:
openclaw doctor
Common issues include the PATH environment variable not containing the Node.js path, incorrect file permissions, or port 3000 being occupied by another application.
Summary
By managing the OpenClaw daemon through LaunchAgent, you can achieve the same service management experience on macOS as Linux systemd: auto-start at login, automatic crash recovery, and centralized log management. This ensures your OpenClaw AI Agent gateway runs stably 24/7, never missing any messages from chat platforms.