openclaw-docker-setup
Install and configure a fully operational Dockerized OpenClaw instance on macOS from scratch. Includes browser pairing, Discord channel setup, and optional Gmail/Google Drive integration. Use when user asks to "install openclaw docker", "set up dockerized openclaw", "openclaw in docker", or "isolated openclaw instance".
What this skill does
# openclaw-docker-setup
Install a fully isolated, production-ready OpenClaw instance inside Docker on macOS.
One session, zero to running. All common pitfalls are handled inline.
**Supports multiple instances on the same machine.** Each instance gets a unique name and port.
**What you end up with:**
- A named container running and auto-restarting
- Persistent data via named Docker volumes (survives container recreation)
- Dashboard accessible at http://127.0.0.1:YOUR_PORT/
- Discord channel configured and responding
- (Optional) Gmail working via Himalaya (supports attachments); Google Drive via gog
---
## Step 0: Pick Your Instance Name and Port
Run this auto-detect script. It scans existing OpenClaw containers, finds the next free port, and suggests a name. Confirm or override.
```bash
# Auto-detect existing instances and suggest next available name+port
python3 - << 'AUTODETECT'
import subprocess, re
# Find all running openclaw containers
result = subprocess.run(
["docker", "ps", "-a", "--format", "{{.Names}} {{.Ports}}"],
capture_output=True, text=True
)
existing = {}
for line in result.stdout.strip().splitlines():
parts = line.split(' ')
name = parts[0]
ports = parts[1] if len(parts) > 1 else ""
if 'openclaw' in name.lower() or '18789' in ports:
m = re.search(r'0\.0\.0\.0:(\d+)->18789', ports)
port = int(m.group(1)) if m else None
existing[name] = port
# Find next free port starting from 19002
used_ports = set(p for p in existing.values() if p)
port = 19002
while port in used_ports:
port += 1
# Suggest name
count = len(existing) + 1
names = ["openclaw-main", "openclaw-work", "openclaw-demo", "openclaw-test", "openclaw-lab"]
suggested_name = names[min(count - 1, len(names) - 1)]
print("\n=== Existing OpenClaw instances ===")
if existing:
for n, p in existing.items():
print(f" {n} → port {p}")
else:
print(" (none found)")
print(f"\n=== Suggested for new instance ===")
print(f" INSTANCE={suggested_name}")
print(f" HOST_PORT={port}")
print(f"\nTo accept, run:")
print(f" export INSTANCE={suggested_name}")
print(f" export HOST_PORT={port}")
print(f"\nTo override, replace the values and run the export commands with your chosen values.")
AUTODETECT
```
Review the output, then set your variables:
```bash
# Accept suggestion (paste the export lines from the output above)
export INSTANCE=openclaw-main
export HOST_PORT=19002
# Or override with your own values:
export INSTANCE=openclaw-demo
export HOST_PORT=19003
```
**All subsequent commands in this guide use `$INSTANCE` and `$HOST_PORT`.** Keep this terminal session open, or re-export the variables if you open a new one.
**Multiple instances example:**
| Instance | Host port | Purpose |
|----------|-----------|---------|
| `openclaw-main` | 19002 | Primary personal assistant |
| `openclaw-demo` | 19003 | Public demo / lecture |
| `openclaw-work` | 19004 | Work projects |
Each instance has its own volumes (`$INSTANCE-data`, `$INSTANCE-home`) — data is fully isolated.
---
## Prerequisites
- macOS (Darwin) — Intel or Apple Silicon
- Docker Desktop installed and running (or Docker Engine + CLI)
- Claude Code CLI installed on the host if using a Claude Max/Pro subscription (`claude` command available). Skip if using a raw API key.
Verify Docker is running:
```bash
docker --version
docker ps
```
Both commands must succeed before continuing.
---
## Step 1: Pull the Image
The official image is on GitHub Container Registry (GHCR), **not Docker Hub**.
```bash
docker pull ghcr.io/openclaw/openclaw:latest
```
> **Pitfall:** `openclaw/openclaw` on Docker Hub does not exist. Always use `ghcr.io/openclaw/openclaw:latest`.
**Success:** Pull completes without error and `docker images | grep openclaw` shows the image.
---
## Step 2: Generate a Claude Setup Token
**Skip this step if you have a raw Anthropic API key** — you will pass it via `-e ANTHROPIC_API_KEY=sk-ant-api03-...` in Step 3 instead.
If you have a Claude Max or Pro subscription, generate a setup token on the host:
```bash
claude setup-token
```
Copy the token (format: `sk-ant-oat01-...`). You will paste it into the container in Step 5.
> **Pitfall:** This is a **setup token**, not an API key. The two are different. A setup token lets the container authenticate using your subscription. An API key charges per token.
---
## Step 3: Launch the Container
Use the `$INSTANCE` and `$HOST_PORT` variables you set in Step 0. Do not reduce the memory — 512 MB and 1024 MB are insufficient and cause crash loops.
```bash
docker run -d \
--name $INSTANCE \
--restart unless-stopped \
-p $HOST_PORT:18789 \
-m 2048m \
--cpus=2 \
--cap-drop=ALL \
--cap-add=NET_BIND_SERVICE \
--security-opt no-new-privileges \
-v ${INSTANCE}-data:/app/data \
-v ${INSTANCE}-home:/home/node \
-e NODE_OPTIONS="--max-old-space-size=1024" \
ghcr.io/openclaw/openclaw:latest
```
If using a raw API key instead of a setup token, add `-e ANTHROPIC_API_KEY=sk-ant-api03-...` before the image name.
Wait 10 seconds, then verify:
```bash
docker ps --filter name=$INSTANCE
```
**Success:** Status shows `Up X seconds` and the container is not restarting.
> **Pitfall — OOM crash loop:** If the container keeps restarting, check logs:
> `docker logs --tail 20 $INSTANCE`
> If you see `JavaScript heap out of memory`, the container needs `-m 2048m` AND `-e NODE_OPTIONS="--max-old-space-size=1024"`. Recreate with the full command above.
> **Pitfall — port conflict:** If the port is in use, you chose the wrong `HOST_PORT` in Step 0. Re-run the conflict check: `lsof -i :$HOST_PORT`. Pick a free port and relaunch.
---
## Step 4: Configure the Gateway
The gateway binds to `127.0.0.1` (loopback) inside the container by default. Docker port-forwarding sends traffic to the container's network interface, not its loopback. You must switch to LAN mode.
### 4a. Set bind to LAN
```bash
docker exec $INSTANCE node /app/openclaw.mjs config set gateway.bind lan
```
### 4b. Set allowed origins
Non-loopback bind requires explicitly allowed origins or the gateway refuses to start:
```bash
docker exec $INSTANCE node /app/openclaw.mjs config set \
gateway.controlUi.allowedOrigins '["http://127.0.0.1:$HOST_PORT"]' --json
```
### 4c. Restart to apply
```bash
docker restart $INSTANCE
```
Wait 10 seconds, then verify:
```bash
curl -s -o /dev/null -w "%{http_code}" http://127.0.0.1:$HOST_PORT/
```
**Success:** Returns `200`.
> **Pitfall — crash after setting LAN bind:** If you set `gateway.bind lan` but forget the `allowedOrigins` step, the container crash-loops with `non-loopback Control UI requires gateway.controlUi.allowedOrigins`. Run step 4b, then restart.
---
## Step 5: Register Authentication
> **Important:** Do NOT paste your token directly in the command line — it would be stored in shell history. The command below prompts interactively.
```bash
docker exec -it $INSTANCE node /app/openclaw.mjs models auth paste-token --provider anthropic
```
When prompted, paste the setup token from Step 2 (or your API key if using one).
**Success:**
```
Updated ~/.openclaw/openclaw.json
Auth profile: anthropic:manual (anthropic/token)
```
> **Pitfall — `openclaw` command not found:** The CLI binary is NOT installed as a global command in this image. Always use `node /app/openclaw.mjs` inside the container:
> ```bash
> docker exec $INSTANCE node /app/openclaw.mjs <command>
> ```
> For interactive commands (pasting tokens, TTY prompts), add `-it`:
> ```bash
> docker exec -it $INSTANCE node /app/openclaw.mjs <command>
> ```
---
## Step 6: Verify Authentication and Gateway
```bash
# Check model auth
docker exec $INSTANCE node /app/openclaw.mjs models status
```
**Success:** Output includes `Providers w/ OAuth/tokens (1): anthropic (1)`
```bash
# Check gateway
docker exec $INSTANCE node /app/openclaw.mjs gateway status
```
**Success:** Output includes `RPC probe: ok`
---
## Step 7Related in Cloud & DevOps
appbuilder-action-scaffolder
IncludedCreate, implement, deploy, and debug Adobe Runtime actions with consistent layout, validation, and error handling. Use this skill whenever the user needs to add actions to an App Builder project, understand action structure (params, response format, web/raw actions), configure actions in the manifest, use App Builder SDKs (State, Files, Events, database), deploy and invoke actions via CLI, debug action issues, or implement patterns such as webhook receivers, custom event providers, journaling consumers, large payload redirects, action sequence pipelines, and Asset Compute workers. Also trigger when users mention serverless functions in Adobe context, action logging, IMS authentication for actions, or cron-style scheduled actions.
orchestrating-datacloud
IncludedSalesforce Data Cloud product orchestrator for connect→prepare→harmonize→segment→act workflows. Use this skill when the user needs a multi-step Data Cloud pipeline, cross-phase troubleshooting, or data space and data kit management. TRIGGER when: user needs a multi-step Data Cloud pipeline, asks to set up or troubleshoot Data Cloud across phases, manages data spaces or data kits, or wants a cross-phase sf data360 workflow. DO NOT TRIGGER when: work is isolated to a single phase (use the matching phase-specific skill), the task is STDM/session tracing/parquet telemetry (use observing-agentforce), standard CRM SOQL (use querying-soql), or Apex implementation (use generating-apex).
github-project-automation
IncludedAutomate GitHub repository setup with CI/CD workflows, issue templates, Dependabot, and CodeQL security scanning. Includes 12 production-tested workflows and prevents 18 errors: YAML syntax, action pinning, and configuration. Use when: setting up GitHub Actions CI/CD, creating issue/PR templates, enabling Dependabot or CodeQL scanning, deploying to Cloudflare Workers, implementing matrix testing, or troubleshooting YAML indentation, action version pinning, secrets syntax, runner versions, or CodeQL configuration. Keywords: github actions, github workflow, ci/cd, issue templates, pull request templates, dependabot, codeql, security scanning, yaml syntax, github automation, repository setup, workflow templates, github actions matrix, secrets management, branch protection, codeowners, github projects, continuous integration, continuous deployment, workflow syntax error, action version pinning, runner version, github context, yaml indentation error
sf-datacloud
IncludedSalesforce Data Cloud product orchestrator for connect→prepare→harmonize→segment→act workflows. TRIGGER when: user needs a multi-step Data Cloud pipeline, asks to set up or troubleshoot Data Cloud across phases, manages data spaces or data kits, or wants a cross-phase `sf data360` workflow. DO NOT TRIGGER when: work is isolated to a single phase (use the matching sf-datacloud-* skill), the task is STDM/session tracing/parquet telemetry (use sf-ai-agentforce-observability), standard CRM SOQL (use sf-soql), or Apex implementation (use sf-apex).
fabric-cli
IncludedUse this skill for Fabric.so CLI workflows with the `fabric` terminal command: diagnose/install/login, search or browse a Fabric library, save notes/links/files, create folders, ask the Fabric AI assistant, manage tasks/workspaces, generate shell completion, check subscription usage, produce JSON output, and use Fabric as persistent agent memory. Do not use for Microsoft Fabric/Azure/Power BI `fab`, Daniel Miessler's Fabric framework, Python Fabric SSH, Fabric.js, or textile/fashion fabric.
lark
IncludedLark/Feishu CLI skills: lark-cli operations for docs, markdown, sheets, base, calendar, im, mail, task, okr, drive, wiki, slides, whiteboard, apps, approval, attendance, contact, vc, minutes, event. Use when the user needs to operate Lark/Feishu resources via lark-cli, send messages, manage documents, spreadsheets, calendars, tasks, OKRs, deploy web pages, or any Feishu/Lark workspace operations.