{ "title": "Android App (Node)", "content": "* Role: companion node app (Android does not host the Gateway).\n* Gateway required: yes (run it on macOS, Linux, or Windows via WSL2).\n* Install: [Getting Started](/start/getting-started) + [Pairing](/gateway/pairing).\n* Gateway: [Runbook](/gateway) + [Configuration](/gateway/configuration).\n * Protocols: [Gateway protocol](/gateway/protocol) (nodes + control plane).\n\nSystem control (launchd/systemd) lives on the Gateway host. See [Gateway](/gateway).\n\n## Connection Runbook\n\nAndroid node app ⇄ (mDNS/NSD + WebSocket) ⇄ **Gateway**\n\nAndroid connects directly to the Gateway WebSocket (default `ws://:18789`) and uses Gateway-owned pairing.\n\n* You can run the Gateway on the “master” machine.\n* Android device/emulator can reach the gateway WebSocket:\n * Same LAN with mDNS/NSD, **or**\n * Same Tailscale tailnet using Wide-Area Bonjour / unicast DNS-SD (see below), **or**\n * Manual gateway host/port (fallback)\n* You can run the CLI (`openclaw`) on the gateway machine (or via SSH).\n\n### 1) Start the Gateway\n\nConfirm in logs you see something like:\n\n* `listening on ws://0.0.0.0:18789`\n\nFor tailnet-only setups (recommended for Vienna ⇄ London), bind the gateway to the tailnet IP:\n\n* Set `gateway.bind: \"tailnet\"` in `~/.openclaw/openclaw.json` on the gateway host.\n* Restart the Gateway / macOS menubar app.\n\n### 2) Verify discovery (optional)\n\nFrom the gateway machine:\n\nMore debugging notes: [Bonjour](/gateway/bonjour).\n\n#### Tailnet (Vienna ⇄ London) discovery via unicast DNS-SD\n\nAndroid NSD/mDNS discovery won’t cross networks. If your Android node and the gateway are on different networks but connected via Tailscale, use Wide-Area Bonjour / unicast DNS-SD instead:\n\n1. Set up a DNS-SD zone (example `openclaw.internal.`) on the gateway host and publish `_openclaw-gw._tcp` records.\n2. Configure Tailscale split DNS for your chosen domain pointing at that DNS server.\n\nDetails and example CoreDNS config: [Bonjour](/gateway/bonjour).\n\n### 3) Connect from Android\n\n* The app keeps its gateway connection alive via a **foreground service** (persistent notification).\n* Open **Settings**.\n* Under **Discovered Gateways**, select your gateway and hit **Connect**.\n* If mDNS is blocked, use **Advanced → Manual Gateway** (host + port) and **Connect (Manual)**.\n\nAfter the first successful pairing, Android auto-reconnects on launch:\n\n* Manual endpoint (if enabled), otherwise\n* The last discovered gateway (best-effort).\n\n### 4) Approve pairing (CLI)\n\nOn the gateway machine:\n\nPairing details: [Gateway pairing](/gateway/pairing).\n\n### 5) Verify the node is connected\n\n* Via nodes status:\n \n* Via Gateway:\n\n### 6) Chat + history\n\nThe Android node’s Chat sheet uses the gateway’s **primary session key** (`main`), so history and replies are shared with WebChat and other clients:\n\n* History: `chat.history`\n* Send: `chat.send`\n* Push updates (best-effort): `chat.subscribe` → `event:\"chat\"`\n\n### 7) Canvas + camera\n\n#### Gateway Canvas Host (recommended for web content)\n\nIf you want the node to show real HTML/CSS/JS that the agent can edit on disk, point the node at the Gateway canvas host.\n\nNote: nodes use the standalone canvas host on `canvasHost.port` (default `18793`).\n\n1. Create `~/.openclaw/workspace/canvas/index.html` on the gateway host.\n\n2. Navigate the node to it (LAN):\n\nTailnet (optional): if both devices are on Tailscale, use a MagicDNS name or tailnet IP instead of `.local`, e.g. `http://:18793/__openclaw__/canvas/`.\n\nThis server injects a live-reload client into HTML and reloads on file changes.\nThe A2UI host lives at `http://:18793/__openclaw__/a2ui/`.\n\nCanvas commands (foreground only):\n\n* `canvas.eval`, `canvas.snapshot`, `canvas.navigate` (use `{\"url\":\"\"}` or `{\"url\":\"/\"}` to return to the default scaffold). `canvas.snapshot` returns `{ format, base64 }` (default `format=\"jpeg\"`).\n* A2UI: `canvas.a2ui.push`, `canvas.a2ui.reset` (`canvas.a2ui.pushJSONL` legacy alias)\n\nCamera commands (foreground only; permission-gated):\n\n* `camera.snap` (jpg)\n* `camera.clip` (mp4)\n\nSee [Camera node](/nodes/camera) for parameters and CLI helpers.", "code_samples": [ { "code": "Confirm in logs you see something like:\n\n* `listening on ws://0.0.0.0:18789`\n\nFor tailnet-only setups (recommended for Vienna ⇄ London), bind the gateway to the tailnet IP:\n\n* Set `gateway.bind: \"tailnet\"` in `~/.openclaw/openclaw.json` on the gateway host.\n* Restart the Gateway / macOS menubar app.\n\n### 2) Verify discovery (optional)\n\nFrom the gateway machine:", "language": "unknown" }, { "code": "More debugging notes: [Bonjour](/gateway/bonjour).\n\n#### Tailnet (Vienna ⇄ London) discovery via unicast DNS-SD\n\nAndroid NSD/mDNS discovery won’t cross networks. If your Android node and the gateway are on different networks but connected via Tailscale, use Wide-Area Bonjour / unicast DNS-SD instead:\n\n1. Set up a DNS-SD zone (example `openclaw.internal.`) on the gateway host and publish `_openclaw-gw._tcp` records.\n2. Configure Tailscale split DNS for your chosen domain pointing at that DNS server.\n\nDetails and example CoreDNS config: [Bonjour](/gateway/bonjour).\n\n### 3) Connect from Android\n\nIn the Android app:\n\n* The app keeps its gateway connection alive via a **foreground service** (persistent notification).\n* Open **Settings**.\n* Under **Discovered Gateways**, select your gateway and hit **Connect**.\n* If mDNS is blocked, use **Advanced → Manual Gateway** (host + port) and **Connect (Manual)**.\n\nAfter the first successful pairing, Android auto-reconnects on launch:\n\n* Manual endpoint (if enabled), otherwise\n* The last discovered gateway (best-effort).\n\n### 4) Approve pairing (CLI)\n\nOn the gateway machine:", "language": "unknown" }, { "code": "Pairing details: [Gateway pairing](/gateway/pairing).\n\n### 5) Verify the node is connected\n\n* Via nodes status:", "language": "unknown" }, { "code": "* Via Gateway:", "language": "unknown" }, { "code": "### 6) Chat + history\n\nThe Android node’s Chat sheet uses the gateway’s **primary session key** (`main`), so history and replies are shared with WebChat and other clients:\n\n* History: `chat.history`\n* Send: `chat.send`\n* Push updates (best-effort): `chat.subscribe` → `event:\"chat\"`\n\n### 7) Canvas + camera\n\n#### Gateway Canvas Host (recommended for web content)\n\nIf you want the node to show real HTML/CSS/JS that the agent can edit on disk, point the node at the Gateway canvas host.\n\nNote: nodes use the standalone canvas host on `canvasHost.port` (default `18793`).\n\n1. Create `~/.openclaw/workspace/canvas/index.html` on the gateway host.\n\n2. Navigate the node to it (LAN):", "language": "unknown" } ], "headings": [ { "level": "h2", "text": "Support snapshot", "id": "support-snapshot" }, { "level": "h2", "text": "System control", "id": "system-control" }, { "level": "h2", "text": "Connection Runbook", "id": "connection-runbook" }, { "level": "h3", "text": "Prerequisites", "id": "prerequisites" }, { "level": "h3", "text": "1) Start the Gateway", "id": "1)-start-the-gateway" }, { "level": "h3", "text": "2) Verify discovery (optional)", "id": "2)-verify-discovery-(optional)" }, { "level": "h3", "text": "3) Connect from Android", "id": "3)-connect-from-android" }, { "level": "h3", "text": "4) Approve pairing (CLI)", "id": "4)-approve-pairing-(cli)" }, { "level": "h3", "text": "5) Verify the node is connected", "id": "5)-verify-the-node-is-connected" }, { "level": "h3", "text": "6) Chat + history", "id": "6)-chat-+-history" }, { "level": "h3", "text": "7) Canvas + camera", "id": "7)-canvas-+-camera" } ], "url": "llms-txt#android-app-(node)", "links": [] }