docs: unify app docs

This commit is contained in:
Peter Steinberger
2026-01-05 20:59:54 +01:00
parent 79e4354e5c
commit 14d7da6ec2
12 changed files with 237 additions and 244 deletions

View File

@@ -1,18 +1,20 @@
---
summary: "Runbook: connect/pair the Android node to a Clawdbot Gateway and use Canvas/Chat/Camera"
summary: "Android app (node): connection runbook + Canvas/Chat/Camera"
read_when:
- Pairing or reconnecting the Android node
- Debugging Android bridge discovery or auth
- Verifying chat history parity across clients
---
# Android Node Connection Runbook
# Android App (Node)
## Connection Runbook
Android node app ⇄ (mDNS/NSD + TCP bridge) ⇄ **Gateway bridge** ⇄ (loopback WS) ⇄ **Gateway**
The Gateway WebSocket stays loopback-only (`ws://127.0.0.1:18789`). Android talks to the LAN-facing **bridge** (default `tcp://0.0.0.0:18790`) and uses Gateway-owned pairing.
## Prerequisites
### Prerequisites
- You can run the Gateway on the “master” machine.
- Android device/emulator can reach the gateway bridge:
@@ -21,7 +23,7 @@ The Gateway WebSocket stays loopback-only (`ws://127.0.0.1:18789`). Android talk
- Manual bridge host/port (fallback)
- You can run the CLI (`clawdbot`) on the gateway machine (or via SSH).
## 1) Start the Gateway (with bridge enabled)
### 1) Start the Gateway (with bridge enabled)
Bridge is enabled by default (disable via `CLAWDBOT_BRIDGE_ENABLED=0`).
@@ -37,7 +39,7 @@ For tailnet-only setups (recommended for Vienna ⇄ London), bind the bridge to
- Set `bridge.bind: "tailnet"` in `~/.clawdbot/clawdbot.json` on the gateway host.
- Restart the Gateway / macOS menubar app.
## 2) Verify discovery (optional)
### 2) Verify discovery (optional)
From the gateway machine:
@@ -47,7 +49,7 @@ dns-sd -B _clawdbot-bridge._tcp local.
More debugging notes: `docs/bonjour.md`.
### Tailnet (Vienna ⇄ London) discovery via unicast DNS-SD
#### Tailnet (Vienna ⇄ London) discovery via unicast DNS-SD
Android NSD/mDNS discovery wont 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:
@@ -56,7 +58,7 @@ Android NSD/mDNS discovery wont cross networks. If your Android node and the
Details and example CoreDNS config: `docs/bonjour.md`.
## 3) Connect from Android
### 3) Connect from Android
In the Android app:
@@ -69,7 +71,7 @@ After the first successful pairing, Android auto-reconnects on launch:
- Manual endpoint (if enabled), otherwise
- The last discovered bridge (best-effort).
## 4) Approve pairing (CLI)
### 4) Approve pairing (CLI)
On the gateway machine:
@@ -80,7 +82,7 @@ clawdbot nodes approve <requestId>
Pairing details: `docs/gateway/pairing.md`.
## 5) Verify the node is connected
### 5) Verify the node is connected
- Via nodes status:
```bash
@@ -91,7 +93,7 @@ Pairing details: `docs/gateway/pairing.md`.
clawdbot gateway call node.list --params "{}"
```
## 6) Chat + history
### 6) Chat + history
The Android nodes Chat sheet uses the gateways **primary session key** (`main`), so history and replies are shared with WebChat and other clients:
@@ -99,9 +101,9 @@ The Android nodes Chat sheet uses the gateways **primary session key** (`m
- Send: `chat.send`
- Push updates (best-effort): `chat.subscribe``event:"chat"`
## 7) Canvas + camera
### 7) Canvas + camera
### Gateway Canvas Host (recommended for web content)
#### Gateway Canvas Host (recommended for web content)
If 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.

View File

@@ -40,7 +40,7 @@ Last updated: 2026-01-05
- **Clients (mac app / CLI / web admin)**
- One WS connection per client.
- Send requests (`health`, `status`, `send`, `agent`, `system-presence`, toggles) and subscribe to events (`tick`, `agent`, `presence`, `shutdown`).
- On macOS, the app can also be invoked via deep links (`clawdbot://agent?...`) which translate into the same Gateway `agent` request path (see `docs/clawdbot-mac.md`).
- On macOS, the app can also be invoked via deep links (`clawdbot://agent?...`) which translate into the same Gateway `agent` request path (see `docs/macos.md`).
- **Agent process (Pi)**
- Spawned by the Gateway on demand for `agent` calls; streams events back over the same WS connection.
- **WebChat**

View File

@@ -193,5 +193,9 @@ Logs live under `/tmp/clawdbot/` (default: `clawdbot-YYYY-MM-DD.log`).
- WebChat: [WebChat](./webchat.md)
- Gateway ops: [Gateway runbook](./gateway.md)
- Cron + wakeups: [Cron + wakeups](./cron.md)
- macOS menu bar companion: [Clawdbot macOS app](./clawdbot-mac.md)
- macOS menu bar companion: [Clawdbot macOS app](./macos.md)
- iOS node app: [iOS app](./ios.md)
- Android node app: [Android app](./android.md)
- Windows status: [Windows app](./windows.md)
- Linux status: [Linux app](./linux.md)
- Security: [Security](./security.md)

View File

@@ -149,6 +149,12 @@ Example:
- [WhatsApp group messages](./group-messages.md)
- [Media: images](./images.md)
- [Media: audio](./audio.md)
- Companion apps:
- [macOS app](./macos.md)
- [iOS app](./ios.md)
- [Android app](./android.md)
- [Windows app](./windows.md)
- [Linux app](./linux.md)
- Ops and safety:
- [Sessions](./session.md)
- [Cron + wakeups](./cron.md)

View File

@@ -1,17 +1,182 @@
---
summary: "Plan for an iOS voice + canvas node that connects via a secure Bonjour-discovered macOS bridge"
summary: "iOS app (node): architecture + connection runbook"
read_when:
- Pairing or reconnecting the iOS node
- Debugging iOS bridge discovery or auth
- Sending screen/canvas commands to iOS
- Designing iOS node + gateway integration
- Extending the Gateway protocol for node/canvas commands
- Implementing Bonjour pairing or transport security
---
# iOS Node (internal) — Voice Trigger + Canvas
# iOS App (Node)
Status: prototype implemented (internal) · Date: 2025-12-13
Runbook (how to connect/pair + drive Canvas): `docs/ios/connect.md`
## Connection Runbook
## Goals
This is the practical “how do I connect the iOS node” guide:
**iOS app** ⇄ (Bonjour + TCP bridge) ⇄ **Gateway bridge** ⇄ (loopback WS) ⇄ **Gateway**
The Gateway WebSocket stays loopback-only (`ws://127.0.0.1:18789`). The iOS node talks to the LAN-facing **bridge** (default `tcp://0.0.0.0:18790`) and uses Gateway-owned pairing.
### Prerequisites
- You can run the Gateway on the “master” machine.
- iOS node app can reach the gateway bridge:
- Same LAN with Bonjour/mDNS, **or**
- Same Tailscale tailnet using Wide-Area Bonjour / unicast DNS-SD (see below), **or**
- Manual bridge host/port (fallback)
- You can run the CLI (`clawdbot`) on the gateway machine (or via SSH).
### 1) Start the Gateway (with bridge enabled)
Bridge is enabled by default (disable via `CLAWDBOT_BRIDGE_ENABLED=0`).
```bash
pnpm clawdbot gateway --port 18789 --verbose
```
Confirm in logs you see something like:
- `bridge listening on tcp://0.0.0.0:18790 (node)`
For tailnet-only setups (recommended for Vienna ⇄ London), bind the bridge to the gateway machines Tailscale IP instead:
- Set `bridge.bind: "tailnet"` in `~/.clawdbot/clawdbot.json` on the gateway host.
- Restart the Gateway / macOS menubar app.
### 2) Verify Bonjour discovery (optional but recommended)
From the gateway machine:
```bash
dns-sd -B _clawdbot-bridge._tcp local.
```
You should see your gateway advertising `_clawdbot-bridge._tcp`.
If browse works, but the iOS node cant connect, try resolving one instance:
```bash
dns-sd -L "<instance name>" _clawdbot-bridge._tcp local.
```
More debugging notes: `docs/bonjour.md`.
#### Tailnet (Vienna ⇄ London) discovery via unicast DNS-SD
If the iOS node and the gateway are on different networks but connected via Tailscale, multicast mDNS wont cross the boundary. Use Wide-Area Bonjour / unicast DNS-SD instead:
1) Set up a DNS-SD zone (example `clawdbot.internal.`) on the gateway host and publish `_clawdbot-bridge._tcp` records.
2) Configure Tailscale split DNS for `clawdbot.internal` pointing at that DNS server.
Details and example CoreDNS config: `docs/bonjour.md`.
### 3) Connect from the iOS node app
In the iOS node app:
- Pick the discovered bridge (or hit refresh).
- If not paired yet, it will initiate pairing automatically.
- After the first successful pairing, it will auto-reconnect **strictly to the last discovered gateway** on launch (including after reinstall), as long as the iOS Keychain entry is still present.
#### Connection indicator (always visible)
The Settings tab icon shows a small status dot:
- **Green**: connected to the bridge
- **Yellow**: connecting (subtle pulse)
- **Red**: not connected / error
### 4) Approve pairing (CLI)
On the gateway machine:
```bash
clawdbot nodes pending
```
Approve the request:
```bash
clawdbot nodes approve <requestId>
```
After approval, the iOS node receives/stores the token and reconnects authenticated.
Pairing details: `docs/gateway/pairing.md`.
### 5) Verify the node is connected
- In the macOS app: **Instances** tab should show something like `iOS Node (...)` with a green “Active” presence dot shortly after connect.
- Via nodes status (paired + connected):
```bash
clawdbot nodes status
```
- Via Gateway (paired + connected):
```bash
clawdbot gateway call node.list --params "{}"
```
- Via Gateway presence (legacy-ish, still useful):
```bash
clawdbot gateway call system-presence --params "{}"
```
Look for the node `instanceId` (often a UUID).
### 6) Drive the iOS Canvas (draw / snapshot)
The iOS node runs a WKWebView “Canvas” scaffold which exposes:
- `window.__clawdbot.canvas`
- `window.__clawdbot.ctx` (2D context)
- `window.__clawdbot.setStatus(title, subtitle)`
#### Gateway Canvas Host (recommended for web content)
If you want the node to show real HTML/CSS/JS that the agent can edit on disk, point it at the Gateway canvas host.
Note: nodes always use the standalone canvas host on `canvasHost.port` (default `18793`), bound to the bridge interface.
1) Create `~/clawd/canvas/index.html` on the gateway host.
2) Navigate the node to it (LAN):
```bash
clawdbot nodes invoke --node "iOS Node" --command canvas.navigate --params '{"url":"http://<gateway-hostname>.local:18793/__clawdbot__/canvas/"}'
```
Notes:
- The server injects a live-reload client into HTML and reloads on file changes.
- A2UI is hosted on the same canvas host at `http://<gateway-host>:18793/__clawdbot__/a2ui/`.
- Tailnet (optional): if both devices are on Tailscale, use a MagicDNS name or tailnet IP instead of `.local`, e.g. `http://<gateway-magicdns>:18793/__clawdbot__/canvas/`.
- iOS may require App Transport Security allowances to load plain `http://` URLs; if it fails to load, prefer HTTPS or adjust the iOS apps ATS config.
#### Draw with `canvas.eval`
```bash
clawdbot nodes invoke --node "iOS Node" --command canvas.eval --params "$(cat <<'JSON'
{"javaScript":"(() => { const {ctx,setStatus} = window.__clawdbot; setStatus('Drawing','…'); ctx.clearRect(0,0,innerWidth,innerHeight); ctx.lineWidth=6; ctx.strokeStyle='#ff2d55'; ctx.beginPath(); ctx.moveTo(40,40); ctx.lineTo(innerWidth-40, innerHeight-40); ctx.stroke(); setStatus(null,null); return 'ok'; })()"}
JSON
)"
```
#### Snapshot with `canvas.snapshot`
```bash
clawdbot nodes invoke --node 192.168.0.88 --command canvas.snapshot --params '{"maxWidth":900}'
```
The response includes `{ format, base64 }` image data (default `format="jpeg"`; pass `{"format":"png"}` when you specifically need lossless PNG).
### Common gotchas
- **iOS in background:** all `canvas.*` commands fail fast with `NODE_BACKGROUND_UNAVAILABLE` (bring the iOS node app to foreground).
- **Return to default scaffold:** `canvas.navigate` with `{"url":""}` or `{"url":"/"}` returns to the built-in scaffold page.
- **mDNS blocked:** some networks block multicast; use a different LAN or plan a tailnet-capable bridge (see `docs/discovery.md`).
- **Wrong node selector:** `--node` can be the node id (UUID), display name (e.g. `iOS Node`), IP, or an unambiguous prefix. If its ambiguous, the CLI will tell you.
- **Stale pairing / Keychain cleared:** if the pairing token is missing (or iOS Keychain was wiped), the node must pair again; approve a new pending request.
- **App reinstall but no reconnect:** the node restores `instanceId` + last bridge preference from Keychain; if it still comes up “unpaired”, verify Keychain persistence on your device/simulator and re-pair once.
## Design + Architecture
### Goals
- Build an **iOS app** that acts as a **remote node** for Clawdbot:
- **Voice trigger** (wake-word / always-listening intent) that forwards transcripts to the Gateway `agent` method.
- **Canvas** surface that the agent can control: navigate, draw/render, evaluate JS, snapshot.
@@ -28,13 +193,13 @@ Non-goals (v1):
- Supporting arbitrary third-party “plugins” on iOS.
- Perfect App Store compliance; this is **internal-only** initially.
## Current repo reality (constraints we respect)
### Current repo reality (constraints we respect)
- The Gateway WebSocket server binds to `127.0.0.1:18789` (`src/gateway/server.ts`) with an optional `CLAWDBOT_GATEWAY_TOKEN`.
- The Gateway exposes a Canvas file server (`canvasHost`) on `canvasHost.port` (default `18793`), so nodes can `canvas.navigate` to `http://<lanHost>:18793/__clawdbot__/canvas/` and auto-reload on file changes (`docs/configuration.md`).
- macOS “Canvas” is controlled via the Gateway node protocol (`canvas.*`), matching iOS/Android (`docs/mac/canvas.md`).
- Voice wake forwards via `GatewayChannel` to Gateway `agent` (mac app: `VoiceWakeForwarder``GatewayConnection.sendAgent`).
## Recommended topology (B): Gateway-owned Bridge + loopback Gateway
### Recommended topology (B): Gateway-owned Bridge + loopback Gateway
Keep the Node gateway loopback-only; expose a dedicated **gateway-owned bridge** to the LAN/tailnet.
**iOS App** ⇄ (TLS + pairing) ⇄ **Bridge (in gateway)** ⇄ (loopback) ⇄ **Gateway WS** (`ws://127.0.0.1:18789`)
@@ -44,12 +209,12 @@ Why:
- Centralizes auth, rate limiting, and allowlisting in the bridge.
- Lets us unify “canvas node” semantics across mac + iOS without exposing raw gateway methods.
## Security plan (internal, but still robust)
### Transport
### Security plan (internal, but still robust)
#### Transport
- **Current (v0):** bridge is a LAN-facing **TCP** listener with token-based auth after pairing.
- **Next:** wrap the bridge in **TLS** and prefer key-pinned or mTLS-like auth after pairing.
### Pairing
#### Pairing
- Bonjour discovery shows a candidate “Clawdbot Bridge” on the LAN.
- First connection:
1) iOS generates a keypair (Secure Enclave if available).
@@ -62,7 +227,7 @@ Why:
- Subsequent connections:
- The bridge requires the paired identity. Unpaired clients get a structured “not paired” error and no access.
#### Gateway-owned pairing (Option B details)
##### Gateway-owned pairing (Option B details)
Pairing decisions must be owned by the Gateway (`clawd` / Node) so nodes can be approved without the macOS app running.
Key idea:
@@ -79,7 +244,7 @@ CLI (headless approvals):
- `clawdbot nodes approve <requestId>`
- `clawdbot nodes reject <requestId>`
### Authorization / scope control (bridge-side ACL)
#### Authorization / scope control (bridge-side ACL)
The bridge must not be a raw proxy to every gateway method.
- Allow by default:
@@ -93,15 +258,15 @@ The bridge must not be a raw proxy to every gateway method.
- voice forwards per minute
- snapshot frequency / payload size
## Protocol unification: add “node/canvas” to Gateway protocol
### Principle
### Protocol unification: add “node/canvas” to Gateway protocol
#### Principle
Unify mac Canvas + iOS Canvas under a single conceptual surface:
- The agent talks to the Gateway using a stable method set (typed protocol).
- The Gateway routes node-targeted requests to:
- local mac Canvas implementation, or
- remote iOS node via the bridge
### Minimal protocol additions (v1)
#### Minimal protocol additions (v1)
Add to `src/gateway/protocol/schema.ts` (and regenerate Swift models):
**Identity**
@@ -117,7 +282,7 @@ Add to `src/gateway/protocol/schema.ts` (and regenerate Swift models):
- `node.event` → async node status/errors
- e.g. background/foreground transitions, voice availability, canvas availability
### Node command set (canvas)
#### Node command set (canvas)
These are values for `node.invoke.command`:
- `canvas.present` / `canvas.hide`
- `canvas.navigate` with `{ url }` (loads a URL; use `""` or `"/"` to return to the default scaffold)
@@ -133,7 +298,7 @@ Result pattern:
- Request is a standard `req/res` with `ok` / `error`.
- Long operations (loads, streaming drawing, etc.) may also emit `node.event` progress.
#### Current (implemented)
##### Current (implemented)
As of 2025-12-13, the Gateway supports `node.invoke` for bridge-connected nodes.
Example: draw a diagonal line on the iOS Canvas:
@@ -199,38 +364,9 @@ open Clawdbot.xcodeproj
- Credentials:
- Keychain (paired identity + bridge trust anchor)
### macOS
- Keep current Canvas root (already implemented):
- `~/Library/Application Support/Clawdbot/canvas/<session>/...`
- Bridge state:
- No local pairing store (pairing is gateway-owned).
- Any local bridge-only state should remain private under Application Support.
## Related docs
### Gateway (node)
- Pairing (source of truth):
- `~/.clawdbot/nodes/paired.json`
- `~/.clawdbot/nodes/pending.json` (or `pending/*.json` for auditability)
## Rollout plan (phased)
1) **Bridge discovery + pairing (mac + iOS)**
- Bonjour browse + resolve
- Approve prompt on mac
- Persist pairing in Keychain/App Support
2) **Voice-only node**
- iOS voice wake toggle
- Forward transcript to Gateway `agent` via bridge
- Presence beacons via `system-event` (or node.event)
3) **Protocol additions for nodes**
- Add `node.list` / `node.invoke` / `node.event` to Gateway
- Implement bridge routing + ACLs
4) **iOS canvas**
- WKWebView canvas surface
- `canvas.navigate/eval/snapshot`
- Background fast-fail for `canvas.*`
5) **Unify mac Canvas under the same node.invoke**
- Keep existing implementation, but expose it through the unified protocol path so the agent uses one API.
## Open questions
- Should `connect.params.client.mode` be `"node"` with `platform="ios ..."` or a distinct mode `"ios-node"`? (Presence filtering currently excludes `"cli"` only.)
- Do we want a “permissions” model per node (voice only vs voice+canvas) at pairing time?
- Should loading arbitrary websites via `canvas.navigate` allow any https URL, or enforce an allowlist to reduce risk?
- `docs/gateway.md` (gateway runbook)
- `docs/gateway/pairing.md` (approval + storage)
- `docs/bonjour.md` (discovery debugging)
- `docs/discovery.md` (LAN vs tailnet vs SSH)

View File

@@ -1,177 +0,0 @@
---
summary: "Runbook: connect/pair the iOS node to a Clawdbot Gateway and drive its Canvas"
read_when:
- Pairing or reconnecting the iOS node
- Debugging iOS bridge discovery or auth
- Sending screen/canvas commands to iOS
---
# iOS Node Connection Runbook
This is the practical “how do I connect the iOS node” guide:
**iOS app** ⇄ (Bonjour + TCP bridge) ⇄ **Gateway bridge** ⇄ (loopback WS) ⇄ **Gateway**
The Gateway WebSocket stays loopback-only (`ws://127.0.0.1:18789`). The iOS node talks to the LAN-facing **bridge** (default `tcp://0.0.0.0:18790`) and uses Gateway-owned pairing.
## Prerequisites
- You can run the Gateway on the “master” machine.
- iOS node app can reach the gateway bridge:
- Same LAN with Bonjour/mDNS, **or**
- Same Tailscale tailnet using Wide-Area Bonjour / unicast DNS-SD (see below), **or**
- Manual bridge host/port (fallback)
- You can run the CLI (`clawdbot`) on the gateway machine (or via SSH).
## 1) Start the Gateway (with bridge enabled)
Bridge is enabled by default (disable via `CLAWDBOT_BRIDGE_ENABLED=0`).
```bash
pnpm clawdbot gateway --port 18789 --verbose
```
Confirm in logs you see something like:
- `bridge listening on tcp://0.0.0.0:18790 (node)`
For tailnet-only setups (recommended for Vienna ⇄ London), bind the bridge to the gateway machines Tailscale IP instead:
- Set `bridge.bind: "tailnet"` in `~/.clawdbot/clawdbot.json` on the gateway host.
- Restart the Gateway / macOS menubar app.
## 2) Verify Bonjour discovery (optional but recommended)
From the gateway machine:
```bash
dns-sd -B _clawdbot-bridge._tcp local.
```
You should see your gateway advertising `_clawdbot-bridge._tcp`.
If browse works, but the iOS node cant connect, try resolving one instance:
```bash
dns-sd -L "<instance name>" _clawdbot-bridge._tcp local.
```
More debugging notes: `docs/bonjour.md`.
### Tailnet (Vienna ⇄ London) discovery via unicast DNS-SD
If the iOS node and the gateway are on different networks but connected via Tailscale, multicast mDNS wont cross the boundary. Use Wide-Area Bonjour / unicast DNS-SD instead:
1) Set up a DNS-SD zone (example `clawdbot.internal.`) on the gateway host and publish `_clawdbot-bridge._tcp` records.
2) Configure Tailscale split DNS for `clawdbot.internal` pointing at that DNS server.
Details and example CoreDNS config: `docs/bonjour.md`.
## 3) Connect from the iOS node app
In the iOS node app:
- Pick the discovered bridge (or hit refresh).
- If not paired yet, it will initiate pairing automatically.
- After the first successful pairing, it will auto-reconnect **strictly to the last discovered gateway** on launch (including after reinstall), as long as the iOS Keychain entry is still present.
### Connection indicator (always visible)
The Settings tab icon shows a small status dot:
- **Green**: connected to the bridge
- **Yellow**: connecting (subtle pulse)
- **Red**: not connected / error
## 4) Approve pairing (CLI)
On the gateway machine:
```bash
clawdbot nodes pending
```
Approve the request:
```bash
clawdbot nodes approve <requestId>
```
After approval, the iOS node receives/stores the token and reconnects authenticated.
Pairing details: `docs/gateway/pairing.md`.
## 5) Verify the node is connected
- In the macOS app: **Instances** tab should show something like `iOS Node (...)` with a green “Active” presence dot shortly after connect.
- Via nodes status (paired + connected):
```bash
clawdbot nodes status
```
- Via Gateway (paired + connected):
```bash
clawdbot gateway call node.list --params "{}"
```
- Via Gateway presence (legacy-ish, still useful):
```bash
clawdbot gateway call system-presence --params "{}"
```
Look for the node `instanceId` (often a UUID).
## 6) Drive the iOS Canvas (draw / snapshot)
The iOS node runs a WKWebView “Canvas” scaffold which exposes:
- `window.__clawdbot.canvas`
- `window.__clawdbot.ctx` (2D context)
- `window.__clawdbot.setStatus(title, subtitle)`
### Gateway Canvas Host (recommended for web content)
If you want the node to show real HTML/CSS/JS that the agent can edit on disk, point it at the Gateway canvas host.
Note: nodes always use the standalone canvas host on `canvasHost.port` (default `18793`), bound to the bridge interface.
1) Create `~/clawd/canvas/index.html` on the gateway host.
2) Navigate the node to it (LAN):
```bash
clawdbot nodes invoke --node "iOS Node" --command canvas.navigate --params '{"url":"http://<gateway-hostname>.local:18793/__clawdbot__/canvas/"}'
```
Notes:
- The server injects a live-reload client into HTML and reloads on file changes.
- A2UI is hosted on the same canvas host at `http://<gateway-host>:18793/__clawdbot__/a2ui/`.
- Tailnet (optional): if both devices are on Tailscale, use a MagicDNS name or tailnet IP instead of `.local`, e.g. `http://<gateway-magicdns>:18793/__clawdbot__/canvas/`.
- iOS may require App Transport Security allowances to load plain `http://` URLs; if it fails to load, prefer HTTPS or adjust the iOS apps ATS config.
### Draw with `canvas.eval`
```bash
clawdbot nodes invoke --node "iOS Node" --command canvas.eval --params "$(cat <<'JSON'
{"javaScript":"(() => { const {ctx,setStatus} = window.__clawdbot; setStatus('Drawing','…'); ctx.clearRect(0,0,innerWidth,innerHeight); ctx.lineWidth=6; ctx.strokeStyle='#ff2d55'; ctx.beginPath(); ctx.moveTo(40,40); ctx.lineTo(innerWidth-40, innerHeight-40); ctx.stroke(); setStatus(null,null); return 'ok'; })()"}
JSON
)"
```
### Snapshot with `canvas.snapshot`
```bash
clawdbot nodes invoke --node 192.168.0.88 --command canvas.snapshot --params '{"maxWidth":900}'
```
The response includes `{ format, base64 }` image data (default `format="jpeg"`; pass `{"format":"png"}` when you specifically need lossless PNG).
## Common gotchas
- **iOS in background:** all `canvas.*` commands fail fast with `NODE_BACKGROUND_UNAVAILABLE` (bring the iOS node app to foreground).
- **Return to default scaffold:** `canvas.navigate` with `{"url":""}` or `{"url":"/"}` returns to the built-in scaffold page.
- **mDNS blocked:** some networks block multicast; use a different LAN or plan a tailnet-capable bridge (see `docs/discovery.md`).
- **Wrong node selector:** `--node` can be the node id (UUID), display name (e.g. `iOS Node`), IP, or an unambiguous prefix. If its ambiguous, the CLI will tell you.
- **Stale pairing / Keychain cleared:** if the pairing token is missing (or iOS Keychain was wiped), the node must pair again; approve a new pending request.
- **App reinstall but no reconnect:** the node restores `instanceId` + last bridge preference from Keychain; if it still comes up “unpaired”, verify Keychain persistence on your device/simulator and re-pair once.
## Related docs
- `docs/ios/spec.md` (design + architecture)
- `docs/gateway.md` (gateway runbook)
- `docs/gateway/pairing.md` (approval + storage)
- `docs/bonjour.md` (discovery debugging)
- `docs/discovery.md` (LAN vs tailnet vs SSH)

11
docs/linux.md Normal file
View File

@@ -0,0 +1,11 @@
---
summary: "Linux app status + contribution call"
read_when:
- Looking for Linux companion app status
- Planning platform coverage or contributions
---
# Linux App
Clawdbot core is fully supported on Linux. The core is written in TypeScript, so it runs anywhere Node runs.
We do not have a Linux companion app yet. It is planned, and we would love contributions to make it happen.

View File

@@ -81,7 +81,7 @@ Canvas is exposed via the Gateway **node bridge**, so the agent can:
This should be modeled after `WebChatManager`/`WebChatSwiftUIWindowController` but targeting `clawdbot-canvas://…` URLs.
Related:
- For “invoke the agent again from UI” flows, prefer the macOS deep link scheme (`clawdbot://agent?...`) so *any* UI surface (Canvas, WebChat, native views) can trigger a new agent run. See `docs/clawdbot-mac.md`.
- For “invoke the agent again from UI” flows, prefer the macOS deep link scheme (`clawdbot://agent?...`) so *any* UI surface (Canvas, WebChat, native views) can trigger a new agent run. See `docs/macos.md`.
## Agent commands (current)

View File

@@ -86,7 +86,7 @@ If `canvasHostUrl` is missing or unreachable:
- TS: verify `/__clawdbot__/a2ui/` responds with HTML + JS.
- Node: verify A2UI fails when host is unreachable and succeeds when reachable.
4) Docs
- Update `docs/mac/canvas.md`, `docs/ios/spec.md`, `docs/android/connect.md`
- Update `docs/mac/canvas.md`, `docs/ios.md`, `docs/android.md`
to remove local fallback assumptions and point to gateway-hosted A2UI.
## Notes

View File

@@ -115,4 +115,4 @@ pnpm clawdbot health
- `docs/configuration.md` (config schema + examples)
- `docs/discord.md` and `docs/telegram.md` (reply tags + replyToMode settings)
- `docs/clawd.md` (personal assistant setup)
- `docs/clawdbot-mac.md` (macOS app behavior; gateway lifecycle + “Attach only”)
- `docs/macos.md` (macOS app behavior; gateway lifecycle + “Attach only”)

11
docs/windows.md Normal file
View File

@@ -0,0 +1,11 @@
---
summary: "Windows app status + contribution call"
read_when:
- Looking for Windows companion app status
- Planning platform coverage or contributions
---
# Windows App
Clawdbot core is fully supported on Windows. The core is written in TypeScript, so it runs anywhere Node runs.
We do not have a Windows companion app yet. It is planned, and we would love contributions to make it happen.