Setting Up the OpenClaw Gateway Runtime on macOS

This page explains how the macOS app uses an external openclaw CLI and a per-user launchd service to run the Gateway. It covers automatic setup during onboarding and manual recovery steps for advanced users.

Read this when

  • Packaging OpenClaw.app
  • Debugging the macOS gateway launchd service
  • Installing the gateway CLI for macOS

OpenClaw.app does not include Node or the Gateway runtime. The macOS app expects an external openclaw CLI installation, does not launch the Gateway as a child process, and manages a per-user launchd service to keep the Gateway running (or connects to an already-running local Gateway).

Automatic setup

On a fresh Mac, select This Mac during onboarding. The app runs its signed, bundled installer script before the Gateway wizard: it installs a user-space Node runtime and the matching openclaw CLI under ~/.openclaw, then installs and starts the per-user launchd service. This approach requires no Terminal, Homebrew, or administrator privileges.

The app bundles only the installer script, not the Node or Gateway payload. Setup requires an internet connection to download the runtime and the matching OpenClaw package.

Manual recovery

Node 24.15+ is recommended for a manual installation; Node 22.22.3+ also works. Install openclaw globally:

npm install -g openclaw@<version>

Use Retry setup after an automatic setup fails. If that still fails, install the CLI manually with the command above, then select Check again in onboarding.

Launchd (Gateway as LaunchAgent)

Label: ai.openclaw.gateway (default profile), or ai.openclaw.<profile> for a named profile.

Plist location (per-user): ~/Library/LaunchAgents/ai.openclaw.gateway.plist (or ai.openclaw.<profile>.plist).

The macOS app owns LaunchAgent install/update for the default profile in Local mode. The CLI can also install it directly: openclaw gateway install (named profiles are selected via the OPENCLAW_PROFILE env var).

Behavior:

  • "OpenClaw Active" enables or disables the LaunchAgent.
  • Quitting the app does not stop the Gateway (launchd keeps it alive).
  • If a Gateway is already running on the configured port, the app attaches to it instead of starting a new one.

Logging:

  • launchd stdout: ~/Library/Logs/openclaw/gateway.log (profiles use gateway-<profile>.log)
  • launchd stderr: suppressed
  • If the host loops with repeated EADDRINUSE or fast restarts, check for duplicate ai.openclaw.gateway / ai.openclaw.node LaunchAgents and the launchd-marker workaround in Gateway troubleshooting.

Version compatibility

The macOS app compares the Gateway version against its own version. Onboarding automatically runs managed setup when an existing CLI is missing or incompatible. Use Retry setup to repeat installation, or Check again after repairing an external CLI.

State directory on macOS

Keep OpenClaw state on a local, non-synced disk. Avoid iCloud Drive and other cloud-synced folders. Sync latency and file locks can affect sessions, credentials, and Gateway state.

Set OPENCLAW_STATE_DIR to a local path only when you need an override. openclaw doctor warns about common cloud-synced state paths and recommends moving back to local storage. See environment variables and Doctor.

Debug app connectivity

Use the macOS debug CLI from a source checkout to test the same Gateway WebSocket handshake and discovery logic the app uses:

cd apps/macos
swift run openclaw-mac connect --json
swift run openclaw-mac discover --timeout 3000 --json

connect accepts --url, --token, --timeout, --probe, and --json (plus client-identity overrides; run with --help for the full list). discover accepts --timeout, --json, and --include-local. Compare discovery output with openclaw gateway discover --json when you need to separate CLI discovery from app-side connection issues.

Smoke check

openclaw --version

OPENCLAW_SKIP_CHANNELS=1 \
OPENCLAW_SKIP_CANVAS_HOST=1 \
openclaw gateway --port 18999 --bind loopback

Then:

openclaw gateway call health --url ws://127.0.0.1:18999 --timeout 3000