From 14d7da6ec231a20cec21d74b743fcd69ae8a1603 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Mon, 5 Jan 2026 20:59:54 +0100 Subject: [PATCH] docs: unify app docs --- docs/{android/connect.md => android.md} | 26 +-- docs/architecture.md | 2 +- docs/clawd.md | 6 +- docs/index.md | 6 + docs/{ios/spec.md => ios.md} | 236 +++++++++++++++++++----- docs/ios/connect.md | 177 ------------------ docs/linux.md | 11 ++ docs/mac/canvas.md | 2 +- docs/{clawdbot-mac.md => macos.md} | 0 docs/refactor/canvas-a2ui.md | 2 +- docs/setup.md | 2 +- docs/windows.md | 11 ++ 12 files changed, 237 insertions(+), 244 deletions(-) rename docs/{android/connect.md => android.md} (89%) rename docs/{ios/spec.md => ios.md} (54%) delete mode 100644 docs/ios/connect.md create mode 100644 docs/linux.md rename docs/{clawdbot-mac.md => macos.md} (100%) create mode 100644 docs/windows.md diff --git a/docs/android/connect.md b/docs/android.md similarity index 89% rename from docs/android/connect.md rename to docs/android.md index 75964a729..ea09269e5 100644 --- a/docs/android/connect.md +++ b/docs/android.md @@ -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 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: @@ -56,7 +58,7 @@ Android NSD/mDNS discovery won’t 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 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 node’s Chat sheet uses the gateway’s **primary session key** (`main`), so history and replies are shared with WebChat and other clients: @@ -99,9 +101,9 @@ The Android node’s Chat sheet uses the gateway’s **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. diff --git a/docs/architecture.md b/docs/architecture.md index 720450732..fce9f0768 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -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** diff --git a/docs/clawd.md b/docs/clawd.md index 7bbadfaad..77a3cdf05 100644 --- a/docs/clawd.md +++ b/docs/clawd.md @@ -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) diff --git a/docs/index.md b/docs/index.md index ea92072ac..156262657 100644 --- a/docs/index.md +++ b/docs/index.md @@ -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) diff --git a/docs/ios/spec.md b/docs/ios.md similarity index 54% rename from docs/ios/spec.md rename to docs/ios.md index 0baf04e52..ecdf3db01 100644 --- a/docs/ios/spec.md +++ b/docs/ios.md @@ -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 machine’s 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 can’t connect, try resolving one instance: + +```bash +dns-sd -L "" _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 won’t 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 +``` + +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://.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://:18793/__clawdbot__/a2ui/`. +- Tailnet (optional): if both devices are on Tailscale, use a MagicDNS name or tailnet IP instead of `.local`, e.g. `http://: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 app’s 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 it’s 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://: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 ` - `clawdbot nodes reject ` -### 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//...` -- 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) diff --git a/docs/ios/connect.md b/docs/ios/connect.md deleted file mode 100644 index b6a6f9ada..000000000 --- a/docs/ios/connect.md +++ /dev/null @@ -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 machine’s 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 can’t connect, try resolving one instance: - -```bash -dns-sd -L "" _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 won’t 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 -``` - -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://.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://:18793/__clawdbot__/a2ui/`. -- Tailnet (optional): if both devices are on Tailscale, use a MagicDNS name or tailnet IP instead of `.local`, e.g. `http://: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 app’s 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 it’s 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) diff --git a/docs/linux.md b/docs/linux.md new file mode 100644 index 000000000..b5e27e4cb --- /dev/null +++ b/docs/linux.md @@ -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. diff --git a/docs/mac/canvas.md b/docs/mac/canvas.md index 56fcf9428..3dc2458aa 100644 --- a/docs/mac/canvas.md +++ b/docs/mac/canvas.md @@ -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) diff --git a/docs/clawdbot-mac.md b/docs/macos.md similarity index 100% rename from docs/clawdbot-mac.md rename to docs/macos.md diff --git a/docs/refactor/canvas-a2ui.md b/docs/refactor/canvas-a2ui.md index d79ce1733..bca37c1d5 100644 --- a/docs/refactor/canvas-a2ui.md +++ b/docs/refactor/canvas-a2ui.md @@ -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 diff --git a/docs/setup.md b/docs/setup.md index 9a187e111..e8d230c5c 100644 --- a/docs/setup.md +++ b/docs/setup.md @@ -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”) diff --git a/docs/windows.md b/docs/windows.md new file mode 100644 index 000000000..5987541a3 --- /dev/null +++ b/docs/windows.md @@ -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.