Skill flagged — suspicious patterns detected

ClawHub Security flagged this skill as suspicious. Review the scan results before using.

OpenClaw macOS Always-On

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....

MIT-0 · Free to use, modify, and redistribute. No attribution required.
0 · 379 · 0 current installs · 0 all-time installs
byhappy dog@happydog-intj
MIT-0
Security Scan
VirusTotalVirusTotal
Suspicious
View report →
OpenClawOpenClaw
Suspicious
medium confidence
Purpose & Capability
The declared purpose (run OpenClaw as a system LaunchDaemon that survives lock/logout) matches the instructions and the included install.sh: it creates a /Library/LaunchDaemons plist, wraps the node process with caffeinate, and bootstraps the service. Requiring sudo for installation and locating node/OpenClaw binaries is coherent with the stated goal.
Instruction Scope
Runtime instructions focus on creating and installing a LaunchDaemon, stopping user LaunchAgents, and verifying lock-screen behavior. The installer reads local OpenClaw configuration (openclaw config get gateway.auth.token) and writes system-level files; it does not appear to collect unrelated system data. However the instructions do recommend piping a remote install.sh via curl|bash (from a personal GitHub repo) which broadens the scope of trust.
Install Mechanism
The skill is instruction-only but includes an install.sh. The README/SKILL.md suggest a one-line curl|bash from raw.githubusercontent.com (a common host). That pattern is common but inherently risky: running remote scripts without review can execute arbitrary code. The included install.sh itself performs privileged operations but is contained in the package for inspection.
!
Credentials
The installer retrieves the OpenClaw gateway token and writes it into the plist's EnvironmentVariables (OPENCLAW_GATEWAY_TOKEN). The plist is installed at /Library/LaunchDaemons with permissions set to 644 (root:wheel), making the token readable by all local users — disproportionate exposure of a secret. Persisting sensitive tokens in a world-readable system file is a clear security risk. (No unrelated credentials are requested otherwise.)
!
Persistence & Privilege
The skill asks to create a system LaunchDaemon (requires sudo) and sets aggressive keepalive/throttle settings and caffeinate to prevent sleep — appropriate for 24/7 operation but impactful for battery and system policies. The combination of system-level persistence plus storing a gateway token in a world-readable system file increases the blast radius if other local users or processes can read that file.
What to consider before installing
This package will run OpenClaw as a system LaunchDaemon (requires sudo) which is consistent with its goal, but take these precautions before installing: 1) Inspect the install.sh and the plist yourself instead of piping curl | bash from an unfamiliar GitHub account. 2) Do NOT allow the gateway token to be written into a world-readable plist. If you must set a token, store it in a file with restrictive permissions (600 owned by you) or use launchctl to set environment variables at runtime, or better, use the macOS Keychain and have the service retrieve it securely. 3) If you don't need system-wide uptime (survive logout), prefer a LaunchAgent (no sudo) to reduce privilege and exposure. 4) Be aware caffeinate prevents system sleep and may harm laptop battery life. 5) If you proceed, change /Library/LaunchDaemons/ai.openclaw.gateway.plist permissions to restrict access or remove the OPENCLAW_GATEWAY_TOKEN from the plist and inject it at service start with a safer mechanism. If you want, I can suggest a safer plist pattern or a modified install script that avoids storing secrets in a world-readable file.

Like a lobster shell, security has layers — review code before you run it.

Current versionv1.0.1
Download zip
latestvk972dfcdxy0f0btmpzcs784qrx81kh0b

License

MIT-0
Free to use, modify, and redistribute. No attribution required.

SKILL.md

macOS LaunchDaemon Setup for OpenClaw

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)

When to Use This

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

Quick Setup

One-Command Installation

curl -fsSL https://raw.githubusercontent.com/YOUR_USERNAME/clawd/master/skills/macos-launchdaemon/install.sh | bash

Or manual setup below ⬇️

Manual Setup

Step 1: Create LaunchDaemon Configuration

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

Step 2: Stop Existing LaunchAgent

# 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

Step 3: Install LaunchDaemon (requires sudo)

# 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

Step 4: Verify Installation

# 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).

Testing Lock Screen Behavior

Test Script

#!/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."

Manual Test Steps

  1. Lock your Mac: ⌘ + Control + Q
  2. Send from phone: Message your bot (Telegram/Feishu/etc.) with "ping"
  3. Expected: Bot replies "pong! 🎉" immediately
  4. Unlock and verify logs show the message was processed

Management Commands

View Logs

# 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

Restart Service

# 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

# Stop service
sudo launchctl bootout system/ai.openclaw.gateway

# Prevent auto-start
sudo launchctl disable system/ai.openclaw.gateway

Start Service

# Enable and start
sudo launchctl enable system/ai.openclaw.gateway
sudo launchctl bootstrap system /Library/LaunchDaemons/ai.openclaw.gateway.plist

Check Status

# 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

Uninstallation

Complete Removal

# 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

Automated Install Script

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

Troubleshooting

Service Won't Start

Check logs:

tail -50 ~/.openclaw/logs/gateway.err.log

Common issues:

  1. Wrong username in plist

    # Verify username matches
    grep UserName /Library/LaunchDaemons/ai.openclaw.gateway.plist
    whoami
    
  2. Wrong node path

    # Check node location
    which node
    
    # Update plist if needed (change /opt/homebrew/bin/node to your path)
    
  3. Permissions issues

    # Fix log directory permissions
    mkdir -p ~/.openclaw/logs
    chmod 755 ~/.openclaw/logs
    

Still Suspends After Lock

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>
...

Port Already in Use

# 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

Logs Not Writing

# 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

Security Considerations

Running as User vs Root

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

File Permissions

# 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

Token Security

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

Performance Impact

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

macOS Version Compatibility

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.

Comparison: LaunchAgent vs LaunchDaemon

FeatureLaunchAgentLaunchDaemon
Runs when locked❌ May suspend✅ Always runs
Runs when logged out❌ Stops✅ Continues
Setup complexitySimpleRequires sudo
Requires sudo❌ No✅ Yes
Best forPersonal use, logged-in only24/7 server, multi-user
SecurityUser-levelSystem-level (still runs as user)
Auto-startAt loginAt boot

Migration

From LaunchAgent to LaunchDaemon

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

From LaunchDaemon back to LaunchAgent

# 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

FAQ

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.

Related Skills

Contributing

Found issues or improvements?


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

Files

4 total
Select a file
Select a file to preview.

Comments

Loading comments…