127.0.0.1 with a rotated token, adds launchd, and pairs scheduled pull with preflight. See the blog list, home, or purchase for a dedicated Mac.
Why skill chains break on remote Mac runners
Three failure modes recur on shared or rented Macs:
- Node mismatch. SSH, GUI, and CI jobs pick different majors. Target Node 22+ for the OpenClaw CLI from npm; align MCP servers to the same runtime when they share a process.
- MCP path fragility. Relative commands break after reboot when
PATHomits the global npm bin or nvm shim, so stdio servers exit immediately. - Unsafe gateway defaults.
0.0.0.0advertises tool RPC on the LAN. Without a token or mTLS, neighbors can invoke shell and filesystem tools.
Install path decision matrix (pick one entry point)
We standardize on npm global so Ansible, user-data, or golden images can pin semver. Use curl or pkg only when npm is blocked.
| Path | When to choose | Trade-off | Reproducibility tip |
|---|---|---|---|
npm global openclaw@latest |
You already manage Node with nvm, fnm, or asdf on the Mac | Global upgrades affect every user on that prefix | Pin npm install -g [email protected] and checksum the tarball in logs |
| Official install script (curl or pkg) | Registry mirrors block npm but allow vendor CDN | Harder to diff across hosts without a declarative file | Vendor the script hash and run from a read-only staging dir |
| Docker sidecar | Multi-tenant Mac or strict cgroup policy | Extra RAM, socket bind rules, volume mounts for MCP | Mount the workspace read-write and publish only 127.0.0.1 ports |
After Node is pinned, install the CLI:
node -v # expect v22.x or newer for OpenClaw mainline npm install -g openclaw@latest which openclaw
Reproducible setup checklist on the Mac
Run in order on the CI image; fold into your config management as needed.
NODE_VERSION; verify with node -p process.version in the CI wrapper.
npm install -g openclaw@latest or pin a tag. Add the global bin to LaunchAgent PATH; agents ignore shell rc files.
openclaw.json with absolute MCP commands. Fix working dirs under /Users/ci/openclaw-workspace. Store secrets in a chmod 600 env file or keychain, never in git.
127.0.0.1, not 0.0.0.0. Put a random token only in the plist; rotate quarterly. For remote admins use SSH port-forward or mTLS, not a public bind.
LaunchAgent with WorkingDirectory, StandardOutPath and StandardErrorPath under logs/, and RunAtLoad; set KeepAlive false if CI should supervise restarts.
Plist skeleton (trim keys to your vendor docs):
<?xml version="1.0" encoding="UTF-8"?>
<plist version="1.0"><dict>
<key>Label</key><string>com.example.openclaw.mcp</string>
<key>ProgramArguments</key><array>
<string>/usr/local/bin/openclaw</string><string>gateway</string>
</array>
<key>WorkingDirectory</key><string>/Users/ci/openclaw-workspace</string>
<key>EnvironmentVariables</key><dict>
<key>OPENCLAW_TOKEN</key><string>replace-me</string>
</dict>
<key>RunAtLoad</key><true/>
</dict></plist>
Common errors reference table
Tail logs/openclaw.err.log while matching rows here.
| Symptom | Likely cause | Fix |
|---|---|---|
ERR_REQUIRE_ESM or engine warnings |
Node older than 22 on the active shell | Align nvm default, plist PATH, CI env |
| MCP server exits code 127 | Relative command or missing global bin in non-login shell | Absolute paths; plist EnvironmentVariables |
| Connection reset from gateway | Token mismatch or missing Authorization header |
Rotate token; restart agent; sync CI secret |
| Port already in use | Previous agent not cleaned up or another tool grabbed the port | launchctl bootout; clear stale socket; change port |
Minimal reproducible workspace layout
Stable paths survive reboots and user switches.
openclaw-workspace/ ├── openclaw.json # skills + MCP server entries ├── skills/ # ClawHub or custom skill bundles ├── scripts/ │ ├── preflight.sh # health checks before CI jobs │ └── scheduled-pull.sh # git fetch + cache warm (optional) ├── logs/ # stdout/stderr from launchd └── .env.local # chmod 600, never commit
Scheduled pull plus preflight example
Add cron or StartCalendarInterval to run a wrapper: git pull --ff-only, optional npm cache warm, then scripts/preflight.sh curling 127.0.0.1 with the token.
#!/bin/bash set -euo pipefail cd /Users/ci/openclaw-workspace git pull --ff-only ./scripts/preflight.sh # checks openclaw doctor, MCP ports, token
Run nightly jobs as the same user as LaunchAgents.
Quick reference you can cite
- Node baseline: Node 22+ for npm-installed OpenClaw CLI in 2026; match MCP majors when sharing a process.
- Security: bind
127.0.0.1, rotate tokens, never expose0.0.0.0without firewall review. - Automation: pair
launchctl bootstrapwith pinnednpm install -g [email protected]for reproducible images.
Summary
Pin Node, npm-install OpenClaw, absolute MCP paths, localhost gateway with a token, launchd, and a pull-plus-preflight wrapper before heavy CI. Need Apple Silicon dedicated to this stack? Open pricing, purchase, or help on MacPull.
Rent a Mac Mini for long-lived gateways and MCP tools off shared runners—finish checkout when your 2026 CI image is ready.
Remote Mac for OpenClaw & MCP CI in 2026
Dedicated Mac Mini nodes for OpenClaw, MCP, and SSH. Browse pricing, purchase without login, help for access, or the blog for more guides.