Requirements
- Target platform
- OpenClaw
- Install method
- Manual import
- Extraction
- Extract archive
- Prerequisites
- OpenClaw
- Primary doc
- SKILL.md
Run OpenClaw as a system-level LaunchDaemon on macOS for 24/7 operation, surviving screen lock, logout, and user switching. Uses caffeinate to prevent sleep....
Run OpenClaw as a system-level LaunchDaemon on macOS for 24/7 operation, surviving screen lock, logout, and user switching. Uses caffeinate to prevent sleep....
Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.
I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Then review README.md for any prerequisites, environment setup, or post-install checks. Tell me what you changed and call out any manual steps you could not complete.
I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Then review README.md for any prerequisites, environment setup, or post-install checks. Summarize what changed and any follow-up checks I should run.
Run OpenClaw as a system-level service (LaunchDaemon) with caffeinate to ensure 24/7 operation. This configuration has been tested and verified to work even after extended screen lock periods (30+ minutes). Ensures OpenClaw continues running when: π Screen is locked (short or long duration) π€ User is logged out π Switching between user accounts π€ Display sleeps (system stays awake)
Use LaunchDaemon if: You need 24/7 bot availability You lock your Mac regularly but want messages to still work Multiple users on the same Mac need to access the bot Running on a home server/always-on Mac Use LaunchAgent if: Only need bot while logged in Prefer simpler setup (no sudo) Security-conscious about system-level services
curl -fsSL https://raw.githubusercontent.com/YOUR_USERNAME/clawd/master/skills/macos-launchdaemon/install.sh | bash Or manual setup below β¬οΈ
Create the plist file with your actual username. This configuration uses caffeinate and has been tested and verified to work even after 30+ minutes of screen lock: cat > /tmp/ai.openclaw.gateway.plist << 'EOF' <?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>ai.openclaw.gateway</string> <key>Comment</key> <string>OpenClaw Gateway (System Daemon - Network Always On)</string> <key>RunAtLoad</key> <true/> <!-- Enhanced KeepAlive for network services --> <key>KeepAlive</key> <dict> <key>SuccessfulExit</key> <false/> <key>NetworkState</key> <true/> <key>Crashed</key> <true/> </dict> <!-- Prevent ANY throttling --> <key>ThrottleInterval</key> <integer>0</integer> <!-- Interactive process - highest priority --> <key>ProcessType</key> <string>Interactive</string> <!-- Enable network transactions --> <key>EnableTransactions</key> <true/> <key>UserName</key> <string>YOUR_USERNAME</string> <key>GroupName</key> <string>staff</string> <!-- Wrap with caffeinate to prevent sleep --> <key>ProgramArguments</key> <array> <string>/usr/bin/caffeinate</string> <string>-s</string> <string>/opt/homebrew/bin/node</string> <string>/opt/homebrew/lib/node_modules/openclaw/dist/index.js</string> <string>gateway</string> <string>--port</string> <string>18789</string> </array> <key>StandardOutPath</key> <string>/Users/YOUR_USERNAME/.openclaw/logs/gateway.log</string> <key>StandardErrorPath</key> <string>/Users/YOUR_USERNAME/.openclaw/logs/gateway.err.log</string> <key>EnvironmentVariables</key> <dict> <key>HOME</key> <string>/Users/YOUR_USERNAME</string> <key>PATH</key> <string>/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin</string> </dict> </dict> </plist> EOF # Replace YOUR_USERNAME with your actual username sed -i '' "s/YOUR_USERNAME/$(whoami)/g" /tmp/ai.openclaw.gateway.plist π Key Configuration for Lock Screen Persistence: /usr/bin/caffeinate -s - Prevents system sleep (display can sleep, network stays active) NetworkState: true - Ensures service stays active when network is available ProcessType: Interactive - Prevents macOS from suspending the process ThrottleInterval: 0 - Disables any throttling Crashed: true - Auto-restarts on crashes β Verified working after 30+ minutes of screen lock on macOS 14.4
# Stop user-level service launchctl bootout gui/$(id -u)/ai.openclaw.gateway 2>/dev/null # Backup and disable LaunchAgent plist mv ~/Library/LaunchAgents/ai.openclaw.gateway.plist ~/Library/LaunchAgents/ai.openclaw.gateway.plist.disabled 2>/dev/null
# Copy to system location sudo cp /tmp/ai.openclaw.gateway.plist /Library/LaunchDaemons/ # Set correct permissions sudo chown root:wheel /Library/LaunchDaemons/ai.openclaw.gateway.plist sudo chmod 644 /Library/LaunchDaemons/ai.openclaw.gateway.plist # Load and start service sudo launchctl bootstrap system /Library/LaunchDaemons/ai.openclaw.gateway.plist
# Check process is running ps aux | grep openclaw-gateway | grep -v grep # Verify PPID = 1 (launched by system launchd) ps -p $(pgrep -f openclaw-gateway) -o pid,ppid,user,command # Check service status sudo launchctl print system/ai.openclaw.gateway | head -10 # Test with OpenClaw openclaw status Expected output: PID PPID USER COMMAND 12345 1 youruser openclaw-gateway PPID=1 confirms it's running as LaunchDaemon (parent is system launchd).
#!/bin/bash echo "π§ͺ Testing LaunchDaemon lock screen behavior..." echo "" echo "1. Lock your Mac in 5 seconds..." sleep 5 pmset displaysleepnow echo "2. Use your phone to send 'ping' to your bot" echo "3. Bot should reply 'pong! π' even while locked" echo "" echo "Unlock your Mac after testing."
Lock your Mac: β + Control + Q Send from phone: Message your bot (Telegram/Feishu/etc.) with "ping" Expected: Bot replies "pong! π" immediately Unlock and verify logs show the message was processed
# Real-time logs tail -f ~/.openclaw/logs/gateway.log # Error logs tail -f ~/.openclaw/logs/gateway.err.log # Last 100 lines tail -100 ~/.openclaw/logs/gateway.log
# Unload and reload sudo launchctl bootout system/ai.openclaw.gateway sudo launchctl bootstrap system /Library/LaunchDaemons/ai.openclaw.gateway.plist # Or use kickstart (restarts without unloading) sudo launchctl kickstart -k system/ai.openclaw.gateway
# Stop service sudo launchctl bootout system/ai.openclaw.gateway # Prevent auto-start sudo launchctl disable system/ai.openclaw.gateway
# Enable and start sudo launchctl enable system/ai.openclaw.gateway sudo launchctl bootstrap system /Library/LaunchDaemons/ai.openclaw.gateway.plist
# Full service details sudo launchctl print system/ai.openclaw.gateway # Quick status check sudo launchctl list | grep openclaw # Process info ps aux | grep openclaw-gateway | grep -v grep
# 1. Stop service sudo launchctl bootout system/ai.openclaw.gateway # 2. Remove plist sudo rm /Library/LaunchDaemons/ai.openclaw.gateway.plist # 3. Restore LaunchAgent (optional) mv ~/Library/LaunchAgents/ai.openclaw.gateway.plist.disabled ~/Library/LaunchAgents/ai.openclaw.gateway.plist 2>/dev/null launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/ai.openclaw.gateway.plist # 4. Verify ps aux | grep openclaw | grep -v grep
Save this as install-launchdaemon.sh: #!/bin/bash set -e echo "π OpenClaw LaunchDaemon Installer" echo "==================================" echo "" # Colors RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' NC='\033[0m' # No Color USERNAME=$(whoami) PLIST_PATH="/Library/LaunchDaemons/ai.openclaw.gateway.plist" TEMP_PLIST="/tmp/ai.openclaw.gateway.plist" # Check if running as root if [ "$EUID" -eq 0 ]; then echo -e "${RED}β Don't run this script with sudo${NC}" echo "The script will ask for sudo password when needed." exit 1 fi # Check if OpenClaw is installed if ! command -v openclaw &> /dev/null; then echo -e "${RED}β OpenClaw not found. Install it first:${NC}" echo " npm install -g openclaw" exit 1 fi echo -e "${YELLOW}π Creating LaunchDaemon configuration...${NC}" # Get OpenClaw gateway token GATEWAY_TOKEN=$(openclaw config get gateway.auth.token 2>/dev/null | tr -d '"' || echo "") cat > "$TEMP_PLIST" << EOF <?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>ai.openclaw.gateway</string> <key>Comment</key> <string>OpenClaw Gateway (System Daemon)</string> <key>RunAtLoad</key> <true/> <key>KeepAlive</key> <true/> <key>UserName</key> <string>$USERNAME</string> <key>GroupName</key> <string>staff</string> <key>ProgramArguments</key> <array> <string>/opt/homebrew/bin/node</string> <string>/opt/homebrew/lib/node_modules/openclaw/dist/index.js</string> <string>gateway</string> <string>--port</string> <string>18789</string> </array> <key>StandardOutPath</key> <string>/Users/$USERNAME/.openclaw/logs/gateway.log</string> <key>StandardErrorPath</key> <string>/Users/$USERNAME/.openclaw/logs/gateway.err.log</string> <key>EnvironmentVariables</key> <dict> <key>HOME</key> <string>/Users/$USERNAME</string> <key>PATH</key> <string>/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin</string> <key>OPENCLAW_GATEWAY_PORT</key> <string>18789</string> <key>OPENCLAW_GATEWAY_TOKEN</key> <string>$GATEWAY_TOKEN</string> </dict> </dict> </plist> EOF echo -e "${YELLOW}π Stopping existing services...${NC}" # Stop LaunchAgent launchctl bootout gui/$(id -u)/ai.openclaw.gateway 2>/dev/null || true # Backup LaunchAgent plist if [ -f ~/Library/LaunchAgents/ai.openclaw.gateway.plist ]; then mv ~/Library/LaunchAgents/ai.openclaw.gateway.plist ~/Library/LaunchAgents/ai.openclaw.gateway.plist.backup echo -e "${GREEN}β Backed up LaunchAgent plist${NC}" fi # Stop existing LaunchDaemon sudo launchctl bootout system/ai.openclaw.gateway 2>/dev/null || true echo -e "${YELLOW}π¦ Installing LaunchDaemon...${NC}" # Install plist sudo cp "$TEMP_PLIST" "$PLIST_PATH" sudo chown root:wheel "$PLIST_PATH" sudo chmod 644 "$PLIST_PATH" echo -e "${YELLOW}π Starting service...${NC}" # Start service sudo launchctl bootstrap system "$PLIST_PATH" sleep 3 # Verify if ps aux | grep -q "[o]penclaw-gateway"; then echo "" echo -e "${GREEN}β LaunchDaemon installed successfully!${NC}" echo "" echo "π Service Status:" ps aux | grep "[o]penclaw-gateway" | awk '{print " PID: "$2", User: "$1}' echo "" echo "π§ͺ Test it:" echo " 1. Lock your Mac: β + Control + Q" echo " 2. Send 'ping' from your phone" echo " 3. Bot should reply even while locked!" echo "" echo "π Management:" echo " Logs: tail -f ~/.openclaw/logs/gateway.log" echo " Restart: sudo launchctl kickstart -k system/ai.openclaw.gateway" echo " Stop: sudo launchctl bootout system/ai.openclaw.gateway" echo " Status: sudo launchctl print system/ai.openclaw.gateway" else echo -e "${RED}β Service failed to start${NC}" echo "Check logs: tail -50 ~/.openclaw/logs/gateway.err.log" exit 1 fi Make it executable: chmod +x install-launchdaemon.sh ./install-launchdaemon.sh
Check logs: tail -50 ~/.openclaw/logs/gateway.err.log Common issues: Wrong username in plist # Verify username matches grep UserName /Library/LaunchDaemons/ai.openclaw.gateway.plist whoami Wrong node path # Check node location which node # Update plist if needed (change /opt/homebrew/bin/node to your path) Permissions issues # Fix log directory permissions mkdir -p ~/.openclaw/logs chmod 755 ~/.openclaw/logs
If using older macOS or specific hardware: # Prevent system sleep sudo pmset -a sleep 0 sudo pmset -a disksleep 0 sudo pmset -a displaysleep 10 # Screen off but system awake Or use caffeinate (not recommended for laptops): # Modify ProgramArguments in plist to wrap with caffeinate <string>/usr/bin/caffeinate</string> <string>-s</string> <!-- prevent sleep --> <string>/opt/homebrew/bin/node</string> ...
# Find what's using port 18789 lsof -i :18789 # Kill the process kill -9 <PID> # Or change port in config and plist openclaw config set gateway.port 18790
# Create log directory mkdir -p ~/.openclaw/logs # Test permissions touch ~/.openclaw/logs/test.log ls -la ~/.openclaw/logs/ # Check plist paths match grep Path /Library/LaunchDaemons/ai.openclaw.gateway.plist
β This setup runs as your user (specified in <key>UserName</key>) Not running as root Same permissions as when you run OpenClaw manually Safer than true root daemons
# LaunchDaemon plist should be owned by root ls -l /Library/LaunchDaemons/ai.openclaw.gateway.plist # Should show: -rw-r--r-- 1 root wheel # Log directory owned by you ls -ld ~/.openclaw/logs # Should show: drwxr-xr-x ... youruser staff
The Gateway token is stored in the plist environment variables. While readable only by root and your user, consider: # Check who can read the plist ls -l /Library/LaunchDaemons/ai.openclaw.gateway.plist # More secure: use macOS Keychain (advanced) # Store token in keychain and retrieve at runtime
LaunchDaemon has minimal performance impact: Same process as LaunchAgent Runs only when needed (KeepAlive handles crashes) Idle resource usage: ~50MB RAM, <1% CPU Active (processing messages): ~100MB RAM, varies by task
Tested on: β macOS 10.15 (Catalina) β macOS 11 (Big Sur) β macOS 12 (Monterey) β macOS 13 (Ventura) β macOS 14 (Sonoma) β macOS 15 (Sequoia) Note: LaunchDaemon syntax changed slightly in macOS 11+, but backwards compatible.
FeatureLaunchAgentLaunchDaemonRuns when lockedβ May suspendβ Always runsRuns when logged outβ Stopsβ ContinuesSetup complexitySimpleRequires sudoRequires sudoβ Noβ YesBest forPersonal use, logged-in only24/7 server, multi-userSecurityUser-levelSystem-level (still runs as user)Auto-startAt loginAt boot
Use the install script above, or: # Automatic migration launchctl bootout gui/$(id -u)/ai.openclaw.gateway mv ~/Library/LaunchAgents/ai.openclaw.gateway.plist ~/Library/LaunchAgents/ai.openclaw.gateway.plist.backup # Then follow installation steps
# Stop daemon sudo launchctl bootout system/ai.openclaw.gateway sudo rm /Library/LaunchDaemons/ai.openclaw.gateway.plist # Restore agent mv ~/Library/LaunchAgents/ai.openclaw.gateway.plist.backup ~/Library/LaunchAgents/ai.openclaw.gateway.plist launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/ai.openclaw.gateway.plist
Q: Will this drain my battery? A: Minimal impact. OpenClaw idles at <1% CPU when not processing messages. Q: Can I still update OpenClaw? A: Yes. After updating, restart the service: sudo launchctl kickstart -k system/ai.openclaw.gateway Q: What if I upgrade macOS? A: LaunchDaemon survives OS upgrades. Verify it's still running after update: sudo launchctl print system/ai.openclaw.gateway Q: Can I run multiple instances? A: Not recommended. Use one LaunchDaemon with multiple channel accounts instead. Q: Does this work on M1/M2 Macs? A: Yes! Works on both Intel and Apple Silicon Macs.
macos-lock-screen-fix - Alternative LaunchAgent fix (simpler but may not work on all Macs) healthcheck - Monitor OpenClaw health and uptime
Found issues or improvements? GitHub: https://github.com/openclaw/openclaw/issues Pull requests welcome! Quick Commands Reference: # Status sudo launchctl print system/ai.openclaw.gateway # Restart sudo launchctl kickstart -k system/ai.openclaw.gateway # Logs tail -f ~/.openclaw/logs/gateway.log # Uninstall sudo launchctl bootout system/ai.openclaw.gateway sudo rm /Library/LaunchDaemons/ai.openclaw.gateway.plist
Code helpers, APIs, CLIs, browser automation, testing, and developer operations.
Largest current source with strong distribution and engagement signals.