chore: rename project to clawdbot

This commit is contained in:
Peter Steinberger
2026-01-04 14:32:47 +00:00
parent d48dc71fa4
commit 246adaa119
841 changed files with 4590 additions and 4328 deletions

View File

@@ -1,5 +1,5 @@
---
summary: "Runbook: connect/pair the iOS node to a Clawdis Gateway and drive its Canvas"
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
@@ -21,14 +21,14 @@ The Gateway WebSocket stays loopback-only (`ws://127.0.0.1:18789`). The iOS node
- 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 (`clawdis`) on the gateway machine (or via SSH).
- 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 `CLAWDIS_BRIDGE_ENABLED=0`).
Bridge is enabled by default (disable via `CLAWDBOT_BRIDGE_ENABLED=0`).
```bash
pnpm clawdis gateway --port 18789 --verbose
pnpm clawdbot gateway --port 18789 --verbose
```
Confirm in logs you see something like:
@@ -36,7 +36,7 @@ Confirm in logs you see something like:
For tailnet-only setups (recommended for Vienna ⇄ London), bind the bridge to the gateway machines Tailscale IP instead:
- Set `bridge.bind: "tailnet"` in `~/.clawdis/clawdis.json` on the gateway host.
- 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)
@@ -44,15 +44,15 @@ For tailnet-only setups (recommended for Vienna ⇄ London), bind the bridge to
From the gateway machine:
```bash
dns-sd -B _clawdis-bridge._tcp local.
dns-sd -B _clawdbot-bridge._tcp local.
```
You should see your gateway advertising `_clawdis-bridge._tcp`.
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>" _clawdis-bridge._tcp local.
dns-sd -L "<instance name>" _clawdbot-bridge._tcp local.
```
More debugging notes: `docs/bonjour.md`.
@@ -61,8 +61,8 @@ More debugging notes: `docs/bonjour.md`.
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 `clawdis.internal.`) on the gateway host and publish `_clawdis-bridge._tcp` records.
2) Configure Tailscale split DNS for `clawdis.internal` pointing at that DNS server.
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`.
@@ -85,13 +85,13 @@ The Settings tab icon shows a small status dot:
On the gateway machine:
```bash
clawdis nodes pending
clawdbot nodes pending
```
Approve the request:
```bash
clawdis nodes approve <requestId>
clawdbot nodes approve <requestId>
```
After approval, the iOS node receives/stores the token and reconnects authenticated.
@@ -103,24 +103,24 @@ Pairing details: `docs/gateway/pairing.md`.
- 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
clawdis nodes status
clawdbot nodes status
```
- Via Gateway (paired + connected):
```bash
clawdis gateway call node.list --params "{}"
clawdbot gateway call node.list --params "{}"
```
- Via Gateway presence (legacy-ish, still useful):
```bash
clawdis gateway call system-presence --params "{}"
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.__clawdis.canvas`
- `window.__clawdis.ctx` (2D context)
- `window.__clawdis.setStatus(title, subtitle)`
- `window.__clawdbot.canvas`
- `window.__clawdbot.ctx` (2D context)
- `window.__clawdbot.setStatus(title, subtitle)`
### Gateway Canvas Host (recommended for web content)
@@ -133,20 +133,20 @@ Note: nodes always use the standalone canvas host on `canvasHost.port` (default
2) Navigate the node to it (LAN):
```bash
clawdis nodes invoke --node "iOS Node" --command canvas.navigate --params '{"url":"http://<gateway-hostname>.local:18793/__clawdis__/canvas/"}'
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/__clawdis__/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/__clawdis__/canvas/`.
- 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
clawdis nodes invoke --node "iOS Node" --command canvas.eval --params "$(cat <<'JSON'
{"javaScript":"(() => { const {ctx,setStatus} = window.__clawdis; 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'; })()"}
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
)"
```
@@ -154,7 +154,7 @@ JSON
### Snapshot with `canvas.snapshot`
```bash
clawdis nodes invoke --node 192.168.0.88 --command canvas.snapshot --params '{"maxWidth":900}'
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).

View File

@@ -12,7 +12,7 @@ Status: prototype implemented (internal) · Date: 2025-12-13
Runbook (how to connect/pair + drive Canvas): `docs/ios/connect.md`
## Goals
- Build an **iOS app** that acts as a **remote node** for Clawdis:
- 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.
- **Dead-simple setup**:
@@ -29,8 +29,8 @@ Non-goals (v1):
- Perfect App Store compliance; this is **internal-only** initially.
## Current repo reality (constraints we respect)
- The Gateway WebSocket server binds to `127.0.0.1:18789` (`src/gateway/server.ts`) with an optional `CLAWDIS_GATEWAY_TOKEN`.
- The Gateway exposes a Canvas file server (`canvasHost`) on `canvasHost.port` (default `18793`), so nodes can `canvas.navigate` to `http://<lanHost>:18793/__clawdis__/canvas/` and auto-reload on file changes (`docs/configuration.md`).
- 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`).
@@ -50,13 +50,13 @@ Why:
- **Next:** wrap the bridge in **TLS** and prefer key-pinned or mTLS-like auth after pairing.
### Pairing
- Bonjour discovery shows a candidate “Clawdis Bridge” on the LAN.
- Bonjour discovery shows a candidate “Clawdbot Bridge” on the LAN.
- First connection:
1) iOS generates a keypair (Secure Enclave if available).
2) iOS connects to the bridge and requests pairing.
3) The bridge forwards the pairing request to the **Gateway** as a *pending request*.
4) Approval can happen via:
- **macOS UI** (Clawdis shows an alert with Approve/Reject/Later, including the node IP), or
- **macOS UI** (Clawdbot shows an alert with Approve/Reject/Later, including the node IP), or
- **Terminal/CLI** (headless flows).
5) Once approved, the bridge returns a token to iOS; iOS stores it in Keychain.
- Subsequent connections:
@@ -70,14 +70,14 @@ Key idea:
Desired behavior:
- If the Swift UI is present: show alert with Approve/Reject/Later.
- If the Swift UI is not present: `clawdis` CLI can list pending requests and approve/reject.
- If the Swift UI is not present: `clawdbot` CLI can list pending requests and approve/reject.
See `docs/gateway/pairing.md` for the API/events and storage.
CLI (headless approvals):
- `clawdis nodes pending`
- `clawdis nodes approve <requestId>`
- `clawdis nodes reject <requestId>`
- `clawdbot nodes pending`
- `clawdbot nodes approve <requestId>`
- `clawdbot nodes reject <requestId>`
### Authorization / scope control (bridge-side ACL)
The bridge must not be a raw proxy to every gateway method.
@@ -127,7 +127,7 @@ These are values for `node.invoke.command`:
- `canvas.a2ui.push` with `{ messages: [...] }` (A2UI v0.8 server→client messages)
- `canvas.a2ui.pushJSONL` with `{ jsonl: "..." }` (legacy alias)
- `canvas.a2ui.reset`
- A2UI is hosted by the Gateway canvas host (`/__clawdis__/a2ui/`) on `canvasHost.port`. Commands fail if the host is unreachable.
- A2UI is hosted by the Gateway canvas host (`/__clawdbot__/a2ui/`) on `canvasHost.port`. Commands fail if the host is unreachable.
Result pattern:
- Request is a standard `req/res` with `ok` / `error`.
@@ -138,7 +138,7 @@ As of 2025-12-13, the Gateway supports `node.invoke` for bridge-connected nodes.
Example: draw a diagonal line on the iOS Canvas:
```bash
clawdis nodes invoke --node ios-node --command canvas.eval --params '{"javaScript":"(() => { const {ctx} = window.__clawdis; 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(); return \"ok\"; })()"}'
clawdbot nodes invoke --node ios-node --command canvas.eval --params '{"javaScript":"(() => { const {ctx} = window.__clawdbot; 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(); return \"ok\"; })()"}'
```
### Background behavior requirement
@@ -168,9 +168,9 @@ When iOS is backgrounded:
## Code sharing (macOS + iOS)
Create/expand SwiftPM targets so both apps share:
- `ClawdisProtocol` (generated models; platform-neutral)
- `ClawdisGatewayClient` (shared WS framing + connect/req/res + seq-gap handling)
- `ClawdisKit` (node/canvas command types + deep links + shared utilities)
- `ClawdbotProtocol` (generated models; platform-neutral)
- `ClawdbotGatewayClient` (shared WS framing + connect/req/res + seq-gap handling)
- `ClawdbotKit` (node/canvas command types + deep links + shared utilities)
macOS continues to own:
- local Canvas implementation details (custom scheme handler serving on-disk HTML, window/panel presentation)
@@ -187,29 +187,29 @@ Generate the Xcode project:
```bash
cd apps/ios
xcodegen generate
open Clawdis.xcodeproj
open Clawdbot.xcodeproj
```
## Storage plan (private by default)
### iOS
- Canvas/workspace files (persistent, private):
- `Application Support/Clawdis/canvas/<sessionKey>/...`
- `Application Support/Clawdbot/canvas/<sessionKey>/...`
- Snapshots / temp exports (evictable):
- `Library/Caches/Clawdis/canvas-snapshots/<sessionKey>/...`
- `Library/Caches/Clawdbot/canvas-snapshots/<sessionKey>/...`
- Credentials:
- Keychain (paired identity + bridge trust anchor)
### macOS
- Keep current Canvas root (already implemented):
- `~/Library/Application Support/Clawdis/canvas/<session>/...`
- `~/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.
### Gateway (node)
- Pairing (source of truth):
- `~/.clawdis/nodes/paired.json`
- `~/.clawdis/nodes/pending.json` (or `pending/*.json` for auditability)
- `~/.clawdbot/nodes/paired.json`
- `~/.clawdbot/nodes/pending.json` (or `pending/*.json` for auditability)
## Rollout plan (phased)
1) **Bridge discovery + pairing (mac + iOS)**