Skip to content

10. OpenClaw local dev tool

Run the OpenClaw agent gateway as a companion to the Mnemose dev stack. It joins the same mnemose Docker bridge network, so the gateway can reach kernel-broker:8081, postgres:5432, and the OTEL collector at otel-collector:4318 — and the host reaches the gateway at http://localhost:18789.

Dev tooling only. There is no production deployment target for OpenClaw. The compose services run under the claw profile so they stay out of the default mnemose profile startup.

Prerequisites

  • Docker with the Mnemose compose stack (see 06-local-development.md)
  • A gateway auth token (any long random string; the gateway rejects requests without it)

1. Configure .env

Copy .env.example to .env (or edit the existing file) and enable OpenClaw:

Terminal window
OPENCLAW_ENABLED=true
OPENCLAW_GATEWAY_TOKEN=$(openssl rand -hex 16)

Optional overrides:

Terminal window
# OPENCLAW_IMAGE=openclaw:local # source-built image from an openclaw checkout
# OPENCLAW_GATEWAY_PORT=18789 # host-side port for the gateway HTTP API
# OPENCLAW_BRIDGE_PORT=18790 # host-side port for the bridge
# OPENCLAW_MSTEAMS_PORT=3978 # host-side port for Teams webhook

See docs/setup/environment-variables.md for the full variable reference.

2. Start the stack

Terminal window
docker compose --profile mnemose --profile claw up -d

This starts the usual Mnemose services plus:

ServicePurpose
openclaw-gatewayOpenClaw gateway on :18789 (HTTP API + WebSocket)
openclaw-cliInteractive CLI; shares the gateway’s network namespace via network_mode: "service:openclaw-gateway"

3. Verify

Terminal window
curl -H "Authorization: Bearer $OPENCLAW_GATEWAY_TOKEN" http://localhost:18789/healthz
docker compose exec openclaw-cli node dist/index.js --help
docker compose logs -f openclaw-gateway

The gateway health check runs every 30s against http://127.0.0.1:18789/healthz; wait for openclaw-gateway to report healthy before relying on it.

4. Networking model

┌────────────────────────── host ──────────────────────────┐
│ browser / agent CLI ─── http://localhost:18789 ────────┐ │
└───────────────────────────────────────────────────────────┘
│ published port 18789
╔══════════════════════╗
╔─────╣ mnemose bridge ╠─────╗
│ ╚══════════════════════╝ │
│ │
┌────────────────┴──────────────┐ ┌───────────────┴──────────┐
│ openclaw-gateway │ │ openclaw-cli │
│ network: mnemose │ │ network_mode: service: │
│ ports: 18789/18790/3978 │ │ openclaw-gateway │
│ extra_hosts: host.docker. │ └───────────────────────────┘
│ internal:host-gateway │
│ can reach: kernel-broker:8081│
│ postgres:5432 │
│ otel-collector:4318
└───────────────────────────────┘
  • Bridge network — the gateway resolves sibling services by Docker DNS (kernel-broker, postgres, otel-collector) because all three share the mnemose network.
  • Bonjour/mDNS — bridge networking drops multicast, so OPENCLAW_DISABLE_BONJOUR=1 (default) keeps the gateway from crash-looping retrying discovery.
  • Host sidecar services — extra_hosts maps host.docker.internal to the host gateway so the bundled local-model providers can reach LM Studio / Ollama on the host.
  • OTEL — the gateway emits OTLP/HTTP to otel-collector:4318 (outbound), so traces land in Jaeger alongside the rest of the stack.

5. Using the CLI

The CLI runs inside a container that shares the gateway’s network namespace:

Terminal window
docker compose --profile claw exec openclaw-cli node dist/index.js chat

Because openclaw-cli uses network_mode: "service:openclaw-gateway", it connects to the gateway over localhost:18789 inside the shared namespace — no extra network config needed.

Troubleshooting

SymptomCauseFix
Gateway not starting; logs show multicast / Bonjour retry spammDNS dropped on bridge networkEnsure OPENCLAW_DISABLE_BONJOUR=1 in .env, restart the gateway
EACCES first-reply failures mentioning /Users/...Host paths leaked from .env into container-side state resolutionKeep OPENCLAW_STATE_DIR/OPENCLAW_CONFIG_DIR pinned to /home/node/... inside the container (already done in compose)
fetch http://127.0.0.1:18789/healthz failing in healthcheckGateway still booting or bound to loopback onlyWait for the 20s start_period; check --bind arg (defaults to lan)
Host can’t reach localhost:18789Port mapping collisionChange OPENCLAW_GATEWAY_PORT in .env, restart
error while creating mount source path '<host dir>': chown ... permission deniedDocker Desktop (macOS) cannot chown a bind-mount source under the user’s home; image runs as nodePre-create the mount source dirs on the host (mkdir -p ~/.openclaw ~/.openclaw/workspace ~/.openclaw-auth-profile-secrets) before up, or point OPENCLAW_CONFIG_DIR / OPENCLAW_AUTH_PROFILE_SECRET_DIR at dirs Docker can manage
a network with name mnemose exists but was not created by composeAn orphaned mnemose bridge from a previous non-compose setup occupies the namedocker network rm mnemose (only if no containers are attached), then re-up
Gateway crash-loops with Invalid config at ...openclaw.json: ... Invalid inputThe mounted openclaw.json uses schema fields the pinned image version rejects (config version drift)Run openclaw doctor --fix, or align the config with the image version — pin OPENCLAW_IMAGE to the build your config targets (e.g. openclaw:local from a matching checkout) instead of :latest