Merge branch 'main' into feat/mattermost-channel

This commit is contained in:
Dominic Damoah
2026-01-22 18:17:40 -05:00
committed by GitHub
149 changed files with 5513 additions and 672 deletions

View File

@@ -122,7 +122,7 @@ clawdbot gateway probe --ssh user@gateway-host
Options:
- `--ssh <target>`: `user@host` or `user@host:port` (port defaults to `22`).
- `--ssh-identity <path>`: identity file.
- `--ssh-auto`: pick the first discovered bridge host as SSH target (LAN/WAB only).
- `--ssh-auto`: pick the first discovered gateway host as SSH target (LAN/WAB only).
Config (optional, used as defaults):
- `gateway.remote.sshTarget`

View File

@@ -293,7 +293,7 @@ Options:
- `--reset` (reset config + credentials + sessions + workspace before wizard)
- `--non-interactive`
- `--mode <local|remote>`
- `--flow <quickstart|advanced>`
- `--flow <quickstart|advanced|manual>` (manual is an alias for advanced)
- `--auth-choice <setup-token|claude-cli|token|openai-codex|openai-api-key|openrouter-api-key|ai-gateway-api-key|moonshot-api-key|kimi-code-api-key|codex-cli|gemini-api-key|zai-api-key|apiKey|minimax-api|opencode-zen|skip>`
- `--token-provider <id>` (non-interactive; used with `--auth-choice token`)
- `--token <token>` (non-interactive; used with `--auth-choice token`)
@@ -791,11 +791,10 @@ All `cron` commands accept `--url`, `--token`, `--timeout`, `--expect-final`.
[`clawdbot node`](/cli/node).
Subcommands:
- `node run --host <gateway-host> --port 18790`
- `node run --host <gateway-host> --port 18789`
- `node status`
- `node install [--host <gateway-host>] [--port <port>] [--tls] [--tls-fingerprint <sha256>] [--node-id <id>] [--display-name <name>] [--runtime <node|bun>] [--force]`
- `node uninstall`
- `node run`
- `node stop`
- `node restart`

View File

@@ -7,7 +7,7 @@ read_when:
# `clawdbot node`
Run a **headless node host** that connects to the Gateway bridge and exposes
Run a **headless node host** that connects to the Gateway WebSocket and exposes
`system.run` / `system.which` on this machine.
## Why use a node host?
@@ -26,14 +26,14 @@ node host, so you can keep command access scoped and explicit.
## Run (foreground)
```bash
clawdbot node run --host <gateway-host> --port 18790
clawdbot node run --host <gateway-host> --port 18789
```
Options:
- `--host <host>`: Gateway bridge host (default: `127.0.0.1`)
- `--port <port>`: Gateway bridge port (default: `18790`)
- `--tls`: Use TLS for the bridge connection
- `--tls-fingerprint <sha256>`: Pin the bridge certificate fingerprint
- `--host <host>`: Gateway WebSocket host (default: `127.0.0.1`)
- `--port <port>`: Gateway WebSocket port (default: `18789`)
- `--tls`: Use TLS for the gateway connection
- `--tls-fingerprint <sha256>`: Expected TLS certificate fingerprint (sha256)
- `--node-id <id>`: Override node id (clears pairing token)
- `--display-name <name>`: Override the node display name
@@ -42,14 +42,14 @@ Options:
Install a headless node host as a user service.
```bash
clawdbot node install --host <gateway-host> --port 18790
clawdbot node install --host <gateway-host> --port 18789
```
Options:
- `--host <host>`: Gateway bridge host (default: `127.0.0.1`)
- `--port <port>`: Gateway bridge port (default: `18790`)
- `--tls`: Use TLS for the bridge connection
- `--tls-fingerprint <sha256>`: Pin the bridge certificate fingerprint
- `--host <host>`: Gateway WebSocket host (default: `127.0.0.1`)
- `--port <port>`: Gateway WebSocket port (default: `18789`)
- `--tls`: Use TLS for the gateway connection
- `--tls-fingerprint <sha256>`: Expected TLS certificate fingerprint (sha256)
- `--node-id <id>`: Override node id (clears pairing token)
- `--display-name <name>`: Override the node display name
- `--runtime <runtime>`: Service runtime (`node` or `bun`)
@@ -65,6 +65,8 @@ clawdbot node restart
clawdbot node uninstall
```
Service commands accept `--json` for machine-readable output.
## Pairing
The first connection creates a pending node pair request on the Gateway.
@@ -75,7 +77,8 @@ clawdbot nodes pending
clawdbot nodes approve <requestId>
```
The node host stores its node id + token in `~/.clawdbot/node.json`.
The node host stores its node id, token, display name, and gateway connection info in
`~/.clawdbot/node.json`.
## Exec approvals

View File

@@ -14,6 +14,9 @@ Related:
- Camera: [Camera nodes](/nodes/camera)
- Images: [Image nodes](/nodes/images)
Common options:
- `--url`, `--token`, `--timeout`, `--json`
## Common commands
```bash
@@ -40,6 +43,11 @@ clawdbot nodes run --raw "git status"
clawdbot nodes run --agent main --node <id|name|ip> --raw "git status"
```
Invoke flags:
- `--params <json>`: JSON object string (default `{}`).
- `--invoke-timeout <ms>`: node invoke timeout (default `15000`).
- `--idempotency-key <key>`: optional idempotency key.
### Exec-style defaults
`nodes run` mirrors the models exec behavior (defaults + approvals):
@@ -47,8 +55,14 @@ clawdbot nodes run --agent main --node <id|name|ip> --raw "git status"
- Reads `tools.exec.*` (plus `agents.list[].tools.exec.*` overrides).
- Uses exec approvals (`exec.approval.request`) before invoking `system.run`.
- `--node` can be omitted when `tools.exec.node` is set.
- Requires a node that advertises `system.run` (macOS companion app or headless node host).
Flags:
- `--cwd <path>`: working directory.
- `--env <key=val>`: env override (repeatable).
- `--command-timeout <ms>`: command timeout.
- `--invoke-timeout <ms>`: node invoke timeout (default `30000`).
- `--needs-screen-recording`: require screen recording permission.
- `--raw <command>`: run a shell string (`/bin/sh -lc` or `cmd.exe /c`).
- `--agent <id>`: agent-scoped approvals/allowlists (defaults to configured agent).
- `--ask <off|on-miss|always>`, `--security <deny|allowlist|full>`: overrides.

View File

@@ -16,6 +16,10 @@ Related:
```bash
clawdbot onboard
clawdbot onboard --flow quickstart
clawdbot onboard --flow manual
clawdbot onboard --mode remote --remote-url ws://gateway-host:18789
```
Flow notes:
- `quickstart`: minimal prompts, auto-generates a gateway token.
- `manual`: full prompts for port/bind/auth (alias of `advanced`).

View File

@@ -5,7 +5,7 @@ read_when:
---
# Gateway architecture
Last updated: 2026-01-19
Last updated: 2026-01-22
## Overview
@@ -34,7 +34,8 @@ Last updated: 2026-01-19
### Nodes (macOS / iOS / Android / headless)
- Connect to the **same WS server** with `role: node`.
- Pair with the Gateway to receive a token.
- Provide a device identity in `connect`; pairing is **devicebased** (role `node`) and
approval lives in the device pairing store.
- Expose commands like `canvas.*`, `camera.*`, `screen.record`, `location.get`.
Protocol details:

View File

@@ -52,10 +52,9 @@ Instances list, `client.mode === "cli"` is **not** turned into a presence entry.
Clients can send richer periodic beacons via the `system-event` method. The mac
app uses this to report host name, IP, and `lastInputSeconds`.
### 4) Node bridge beacons
When a node bridge connection authenticates, the Gateway emits a presence entry
for that node and refreshes it periodically so it doesnt expire.
### 4) Node connects (role: node)
When a node connects over the Gateway WebSocket with `role: node`, the Gateway
upserts a presence entry for that node (same flow as other WS clients).
## Merge + dedupe rules (why `instanceId` matters)

View File

@@ -19,7 +19,7 @@ Goal: small, hard-to-misuse tool set so agents can list sessions, fetch history,
- Group chats use `agent:<agentId>:<channel>:group:<id>` or `agent:<agentId>:<channel>:channel:<id>` (pass the full key).
- Cron jobs use `cron:<job.id>`.
- Hooks use `hook:<uuid>` unless explicitly set.
- Node bridge uses `node-<nodeId>` unless explicitly set.
- Node sessions use `node-<nodeId>` unless explicitly set.
`global` and `unknown` are reserved values and are never listed. If `session.scope = "global"`, we alias it to `main` for all tools so callers never see `global`.

View File

@@ -52,7 +52,7 @@ the workspace is writable. See [Memory](/concepts/memory) and
- Other sources:
- Cron jobs: `cron:<job.id>`
- Webhooks: `hook:<uuid>` (unless explicitly set by the hook)
- Node bridge runs: `node-<nodeId>`
- Node runs: `node-<nodeId>`
## Lifecycle
- Reset policy: sessions are reused until they expire, and expiry is evaluated on the next inbound message.

View File

@@ -46,7 +46,7 @@ Common methods + events:
| Messaging | `send`, `poll`, `agent`, `agent.wait` | side-effects need `idempotencyKey` |
| Chat | `chat.history`, `chat.send`, `chat.abort`, `chat.inject` | WebChat uses these |
| Sessions | `sessions.list`, `sessions.patch`, `sessions.delete` | session admin |
| Nodes | `node.list`, `node.invoke`, `node.pair.*` | bridge + node actions |
| Nodes | `node.list`, `node.invoke`, `node.pair.*` | Gateway WS + node actions |
| Events | `tick`, `presence`, `agent`, `chat`, `health`, `shutdown` | server push |
Authoritative list lives in `src/gateway/server.ts` (`METHODS`, `EVENTS`).

View File

@@ -70,7 +70,7 @@ What this does:
- `CLAWDBOT_PROFILE=dev`
- `CLAWDBOT_STATE_DIR=~/.clawdbot-dev`
- `CLAWDBOT_CONFIG_PATH=~/.clawdbot-dev/clawdbot.json`
- `CLAWDBOT_GATEWAY_PORT=19001` (bridge/canvas/browser shift accordingly)
- `CLAWDBOT_GATEWAY_PORT=19001` (browser/canvas shift accordingly)
2) **Dev bootstrap** (`gateway --dev`)
- Writes a minimal config if missing (`gateway.mode=local`, bind loopback).

View File

@@ -7,7 +7,7 @@ read_when:
# Bonjour / mDNS discovery
Clawdbot uses Bonjour (mDNS / DNSSD) as a **LANonly convenience** to discover
an active Gateway bridge. It is besteffort and does **not** replace SSH or
an active Gateway (WebSocket endpoint). It is besteffort and does **not** replace SSH or
Tailnet-based connectivity.
## Widearea Bonjour (Unicast DNSSD) over Tailscale
@@ -31,7 +31,7 @@ browse both `local.` and `clawdbot.internal.` automatically.
```json5
{
bridge: { bind: "tailnet" }, // tailnet-only (recommended)
gateway: { bind: "tailnet" }, // tailnet-only (recommended)
discovery: { wideArea: { enabled: true } } // enables clawdbot.internal DNS-SD publishing
}
```
@@ -63,13 +63,13 @@ In the Tailscale admin console:
Once clients accept tailnet DNS, iOS nodes can browse
`_clawdbot-gw._tcp` in `clawdbot.internal.` without multicast.
### Bridge listener security (recommended)
### Gateway listener security (recommended)
The bridge port (default `18790`) is a plain TCP service. By default it binds to
`0.0.0.0`, which makes it reachable from any interface on the gateway host.
The Gateway WS port (default `18789`) binds to loopback by default. For LAN/tailnet
access, bind explicitly and keep auth enabled.
For tailnetonly setups:
- Set `bridge.bind: "tailnet"` in `~/.clawdbot/clawdbot.json`.
- Set `gateway.bind: "tailnet"` in `~/.clawdbot/clawdbot.json`.
- Restart the Gateway (or restart the macOS menubar app).
## What advertises
@@ -87,11 +87,12 @@ The Gateway advertises small nonsecret hints to make UI flows convenient:
- `role=gateway`
- `displayName=<friendly name>`
- `lanHost=<hostname>.local`
- `gatewayPort=<port>` (informational; Gateway WS is usually loopbackonly)
- `bridgePort=<port>` (only when bridge is enabled)
- `gatewayPort=<port>` (Gateway WS + HTTP)
- `gatewayTls=1` (only when TLS is enabled)
- `gatewayTlsSha256=<sha256>` (only when TLS is enabled and fingerprint is available)
- `canvasPort=<port>` (only when the canvas host is enabled; default `18793`)
- `sshPort=<port>` (defaults to 22 when not overridden)
- `transport=bridge`
- `transport=gateway`
- `cliPath=<path>` (optional; absolute path to a runnable `clawdbot` entrypoint)
- `tailnetDns=<magicdns>` (optional hint when Tailnet is available)
@@ -125,8 +126,8 @@ The Gateway writes a rolling log file (printed on startup as
The iOS node uses `NWBrowser` to discover `_clawdbot-gw._tcp`.
To capture logs:
- Settings → Bridge → Advanced → **Discovery Debug Logs**
- Settings → Bridge → Advanced → **Discovery Logs** → reproduce → **Copy**
- Settings → Gateway → Advanced → **Discovery Debug Logs**
- Settings → Gateway → Advanced → **Discovery Logs** → reproduce → **Copy**
The log includes browser state transitions and resultset changes.
@@ -136,7 +137,7 @@ The log includes browser state transitions and resultset changes.
- **Multicast blocked**: some WiFi networks disable mDNS.
- **Sleep / interface churn**: macOS may temporarily drop mDNS results; retry.
- **Browse works but resolve fails**: keep machine names simple (avoid emojis or
punctuation), then restart the Gateway. The bridge instance name derives from
punctuation), then restart the Gateway. The service instance name derives from
the host name, so overly complex names can confuse some resolvers.
## Escaped instance names (`\032`)
@@ -150,9 +151,7 @@ sequences (e.g. spaces become `\032`).
## Disabling / configuration
- `CLAWDBOT_DISABLE_BONJOUR=1` disables advertising.
- `CLAWDBOT_BRIDGE_ENABLED=0` disables the bridge listener (and the bridge beacon).
- `bridge.bind` / `bridge.port` in `~/.clawdbot/clawdbot.json` control bridge bind/port.
- `CLAWDBOT_BRIDGE_HOST` / `CLAWDBOT_BRIDGE_PORT` still work as backcompat overrides.
- `gateway.bind` in `~/.clawdbot/clawdbot.json` controls the Gateway bind mode.
- `CLAWDBOT_SSH_PORT` overrides the SSH port advertised in TXT.
- `CLAWDBOT_TAILNET_DNS` publishes a MagicDNS hint in TXT.
- `CLAWDBOT_CLI_PATH` overrides the advertised CLI path.

View File

@@ -14,6 +14,9 @@ should use the unified Gateway WebSocket protocol instead.
If you are building an operator or node client, use the
[Gateway protocol](/gateway/protocol).
**Note:** Current Clawdbot builds no longer ship the TCP bridge listener; this document is kept for historical reference.
Legacy `bridge.*` config keys are no longer part of the config schema.
## Why we have both
- **Security boundary**: the bridge exposes a small allowlist instead of the
@@ -28,7 +31,7 @@ If you are building an operator or node client, use the
- TCP, one JSON object per line (JSONL).
- Optional TLS (when `bridge.tls.enabled` is true).
- Gateway owns the listener (default `18790`).
- Legacy default listener port was `18790` (current builds do not start a TCP bridge).
When TLS is enabled, discovery TXT records include `bridgeTls=1` plus
`bridgeTlsSha256` so nodes can pin the certificate.
@@ -54,7 +57,7 @@ Gateway → Client:
- `event`: chat updates for subscribed sessions
- `ping` / `pong`: keepalive
Exact allowlist is enforced in `src/gateway/server-bridge.ts`.
Legacy allowlist enforcement lived in `src/gateway/server-bridge.ts` (removed).
## Exec lifecycle events

View File

@@ -568,5 +568,5 @@ Save to `~/.clawdbot/clawdbot.json` and you can DM the bot from that number.
- If you set `dmPolicy: "open"`, the matching `allowFrom` list must include `"*"`.
- Provider IDs differ (phone numbers, user IDs, channel IDs). Use the provider docs to confirm the format.
- Optional sections to add later: `web`, `browser`, `ui`, `bridge`, `discovery`, `canvasHost`, `talk`, `signal`, `imessage`.
- Optional sections to add later: `web`, `browser`, `ui`, `discovery`, `canvasHost`, `talk`, `signal`, `imessage`.
- See [Providers](/channels/whatsapp) and [Troubleshooting](/gateway/troubleshooting) for deeper setup notes.

View File

@@ -1719,7 +1719,7 @@ auto-compaction, instructing the model to store durable memories on disk (e.g.
`memory/YYYY-MM-DD.md`). It triggers when the session token estimate crosses a
soft threshold below the compaction limit.
Defaults:
Legacy defaults:
- `memoryFlush.enabled`: `true`
- `memoryFlush.softThresholdTokens`: `4000`
- `memoryFlush.prompt` / `memoryFlush.systemPrompt`: built-in defaults with `NO_REPLY`
@@ -2814,7 +2814,7 @@ Hot-applied (no full gateway restart):
Requires full Gateway restart:
- `gateway` (port/bind/auth/control UI/tailscale)
- `bridge`
- `bridge` (legacy)
- `discovery`
- `canvasHost`
- `plugins`
@@ -2832,7 +2832,7 @@ Convenience flags (CLI):
- `clawdbot --dev …` → uses `~/.clawdbot-dev` + shifts ports from base `19001`
- `clawdbot --profile <name> …` → uses `~/.clawdbot-<name>` (port via config/env/flags)
See [Gateway runbook](/gateway) for the derived port mapping (gateway/bridge/browser/canvas).
See [Gateway runbook](/gateway) for the derived port mapping (gateway/browser/canvas).
See [Multiple gateways](/gateway/multiple-gateways) for browser/CDP port isolation details.
Example:
@@ -2951,7 +2951,7 @@ The Gateway serves a directory of HTML/CSS/JS over HTTP so iOS/Android nodes can
Default root: `~/clawd/canvas`
Default port: `18793` (chosen to avoid the clawd browser CDP port `18792`)
The server listens on the **bridge bind host** (LAN or Tailnet) so nodes can reach it.
The server listens on the **gateway bind host** (LAN or Tailnet) so nodes can reach it.
The server:
- serves files under `canvasHost.root`
@@ -2980,9 +2980,13 @@ Disable with:
- config: `canvasHost: { enabled: false }`
- env: `CLAWDBOT_SKIP_CANVAS_HOST=1`
### `bridge` (node bridge server)
### `bridge` (legacy TCP bridge, removed)
The Gateway can expose a simple TCP bridge for nodes (iOS/Android), typically on port `18790`.
Current builds no longer include the TCP bridge listener; `bridge.*` config keys are ignored.
Nodes connect over the Gateway WebSocket. This section is kept for historical reference.
Legacy behavior:
- The Gateway could expose a simple TCP bridge for nodes (iOS/Android), typically on port `18790`.
Defaults:
- enabled: `true`

View File

@@ -3,7 +3,7 @@ summary: "Node discovery and transports (Bonjour, Tailscale, SSH) for finding th
read_when:
- Implementing or changing Bonjour discovery/advertising
- Adjusting remote connection modes (direct vs SSH)
- Designing bridge + pairing for remote nodes
- Designing node discovery + pairing for remote nodes
---
# Discovery & transports
@@ -17,17 +17,18 @@ The design goal is to keep all network discovery/advertising in the **Node Gatew
## Terms
- **Gateway**: a single long-running gateway process that owns state (sessions, pairing, node registry) and runs channels. Most setups use one per host; isolated multi-gateway setups are possible.
- **Gateway WS (loopback)**: the existing gateway WebSocket control endpoint on `127.0.0.1:18789`.
- **Bridge (direct transport)**: a LAN/tailnet-facing endpoint owned by the gateway that allows authenticated clients/nodes to call a scoped subset of gateway methods. The bridge exists so the gateway can remain loopback-only.
- **Gateway WS (control plane)**: the WebSocket endpoint on `127.0.0.1:18789` by default; can be bound to LAN/tailnet via `gateway.bind`.
- **Direct WS transport**: a LAN/tailnet-facing Gateway WS endpoint (no SSH).
- **SSH transport (fallback)**: remote control by forwarding `127.0.0.1:18789` over SSH.
- **Legacy TCP bridge (deprecated/removed)**: older node transport (see [Bridge protocol](/gateway/bridge-protocol)); no longer advertised for discovery.
Protocol details:
- [Gateway protocol](/gateway/protocol)
- [Bridge protocol](/gateway/bridge-protocol)
- [Bridge protocol (legacy)](/gateway/bridge-protocol)
## Why we keep both “direct” and SSH
- **Direct bridge** is the best UX on the same network and within a tailnet:
- **Direct WS** is the best UX on the same network and within a tailnet:
- auto-discovery on LAN via Bonjour
- pairing tokens + ACLs owned by the gateway
- no shell access required; protocol surface can stay tight and auditable
@@ -43,7 +44,7 @@ Protocol details:
Bonjour is best-effort and does not cross networks. It is only used for “same LAN” convenience.
Target direction:
- The **gateway** advertises its bridge via Bonjour.
- The **gateway** advertises its WS endpoint via Bonjour.
- Clients browse and show a “pick a gateway” list, then store the chosen endpoint.
Troubleshooting and beacon details: [Bonjour](/gateway/bonjour).
@@ -56,19 +57,19 @@ Troubleshooting and beacon details: [Bonjour](/gateway/bonjour).
- `role=gateway`
- `lanHost=<hostname>.local`
- `sshPort=22` (or whatever is advertised)
- `gatewayPort=18789` (loopback WS port; informational)
- `bridgePort=18790` (when bridge is enabled)
- `gatewayPort=18789` (Gateway WS + HTTP)
- `gatewayTls=1` (only when TLS is enabled)
- `gatewayTlsSha256=<sha256>` (only when TLS is enabled and fingerprint is available)
- `canvasPort=18793` (default canvas host port; serves `/__clawdbot__/canvas/`)
- `cliPath=<path>` (optional; absolute path to a runnable `clawdbot` entrypoint or binary)
- `tailnetDns=<magicdns>` (optional hint; auto-detected when Tailscale is available)
Disable/override:
- `CLAWDBOT_DISABLE_BONJOUR=1` disables advertising.
- `CLAWDBOT_BRIDGE_ENABLED=0` disables the bridge listener.
- `bridge.bind` / `bridge.port` in `~/.clawdbot/clawdbot.json` control bridge bind/port (preferred).
- `CLAWDBOT_BRIDGE_HOST` / `CLAWDBOT_BRIDGE_PORT` still work as a back-compat override when `bridge.bind` / `bridge.port` are not set.
- `CLAWDBOT_SSH_PORT` overrides the SSH port advertised in the bridge beacon (defaults to 22).
- `CLAWDBOT_TAILNET_DNS` publishes a `tailnetDns` hint (MagicDNS) in the bridge beacon (auto-detected if unset).
- `gateway.bind` in `~/.clawdbot/clawdbot.json` controls the Gateway bind mode.
- `CLAWDBOT_SSH_PORT` overrides the SSH port advertised in TXT (defaults to 22).
- `CLAWDBOT_TAILNET_DNS` publishes a `tailnetDns` hint (MagicDNS).
- `CLAWDBOT_CLI_PATH` overrides the advertised CLI path.
### 2) Tailnet (cross-network)
@@ -97,13 +98,13 @@ Recommended client behavior:
The gateway is the source of truth for node/client admission.
- Pairing requests are created/approved/rejected in the gateway (see [Gateway pairing](/gateway/pairing)).
- The bridge enforces:
- The gateway enforces:
- auth (token / keypair)
- scopes/ACLs (bridge is not a raw proxy to every gateway method)
- scopes/ACLs (the gateway is not a raw proxy to every method)
- rate limits
## Responsibilities by component
- **Gateway**: advertises discovery beacons, owns pairing decisions, runs the bridge listener.
- **Gateway**: advertises discovery beacons, owns pairing decisions, and hosts the WS endpoint.
- **macOS app**: helps you pick a gateway, shows pairing prompts, and uses SSH only as a fallback.
- **iOS/Android nodes**: browse Bonjour as a convenience and connect via the paired bridge.
- **iOS/Android nodes**: browse Bonjour as a convenience and connect to the paired Gateway WS.

View File

@@ -82,14 +82,12 @@ Defaults (can be overridden via env/flags/config):
- `CLAWDBOT_STATE_DIR=~/.clawdbot-dev`
- `CLAWDBOT_CONFIG_PATH=~/.clawdbot-dev/clawdbot.json`
- `CLAWDBOT_GATEWAY_PORT=19001` (Gateway WS + HTTP)
- `bridge.port=19002` (derived: `gateway.port+1`)
- `browser.controlUrl=http://127.0.0.1:19003` (derived: `gateway.port+2`)
- `canvasHost.port=19005` (derived: `gateway.port+4`)
- `agents.defaults.workspace` default becomes `~/clawd-dev` when you run `setup`/`onboard` under `--dev`.
Derived ports (rules of thumb):
- Base port = `gateway.port` (or `CLAWDBOT_GATEWAY_PORT` / `--port`)
- `bridge.port = base + 1` (or `CLAWDBOT_BRIDGE_PORT` / config override)
- `browser.controlUrl port = base + 2` (or `CLAWDBOT_BROWSER_CONTROL_URL` / config override)
- `canvasHost.port = base + 4` (or `CLAWDBOT_CANVAS_HOST_PORT` / config override)
- Browser profile CDP ports auto-allocate from `browser.controlPort + 9 .. + 108` (persisted per profile).
@@ -114,7 +112,7 @@ CLAWDBOT_CONFIG_PATH=~/.clawdbot/b.json CLAWDBOT_STATE_DIR=~/.clawdbot-b clawdbo
```
## Protocol (operator view)
- Full docs: [Gateway protocol](/gateway/protocol) and [Bridge protocol](/gateway/bridge-protocol).
- Full docs: [Gateway protocol](/gateway/protocol) and [Bridge protocol (legacy)](/gateway/bridge-protocol).
- Mandatory first frame from client: `req {type:"req", id, method:"connect", params:{minProtocol,maxProtocol,client:{id,displayName?,version,platform,deviceFamily?,modelIdentifier?,mode,instanceId?}, caps, auth?, locale?, userAgent? } }`.
- Gateway replies `res {type:"res", id, ok:true, payload:hello-ok }` (or `ok:false` with an error, then closes).
- After handshake:
@@ -130,7 +128,7 @@ CLAWDBOT_CONFIG_PATH=~/.clawdbot/b.json CLAWDBOT_STATE_DIR=~/.clawdbot-b clawdbo
- `system-event` — post a presence/system note (structured).
- `send` — send a message via the active channel(s).
- `agent` — run an agent turn (streams events back on same connection).
- `node.list` — list paired + currently-connected bridge nodes (includes `caps`, `deviceFamily`, `modelIdentifier`, `paired`, `connected`, and advertised `commands`).
- `node.list` — list paired + currently-connected nodes (includes `caps`, `deviceFamily`, `modelIdentifier`, `paired`, `connected`, and advertised `commands`).
- `node.describe` — describe a node (capabilities + supported `node.invoke` commands; works for paired nodes and for currently-connected unpaired nodes).
- `node.invoke` — invoke a command on a node (e.g. `canvas.*`, `camera.*`).
- `node.pair.*` — pairing lifecycle (`request`, `list`, `approve`, `reject`, `verify`).

View File

@@ -13,7 +13,7 @@ Most setups should use one Gateway because a single Gateway can handle multiple
- `CLAWDBOT_STATE_DIR` — per-instance sessions, creds, caches
- `agents.defaults.workspace` — per-instance workspace root
- `gateway.port` (or `--port`) — unique per instance
- Derived ports (bridge/browser/canvas) must not overlap
- Derived ports (browser/canvas) must not overlap
If these are shared, you will hit config races and port conflicts.
@@ -47,7 +47,7 @@ Run a second Gateway on the same host with its own:
This keeps the rescue bot isolated from the main bot so it can debug or apply config changes if the primary bot is down.
Port spacing: leave at least 20 ports between base ports so the derived bridge/browser/canvas/CDP ports never collide.
Port spacing: leave at least 20 ports between base ports so the derived browser/canvas/CDP ports never collide.
### How to install (rescue bot)
@@ -73,7 +73,6 @@ clawdbot --profile rescue gateway install
Base port = `gateway.port` (or `CLAWDBOT_GATEWAY_PORT` / `--port`).
- `bridge.port = base + 1`
- `browser.controlUrl port = base + 2`
- `canvasHost.port = base + 4`
- Browser profile CDP ports auto-allocate from `browser.controlPort + 9 .. + 108`

View File

@@ -11,16 +11,20 @@ In Gateway-owned pairing, the **Gateway** is the source of truth for which nodes
are allowed to join. UIs (macOS app, future clients) are just frontends that
approve or reject pending requests.
**Important:** WS nodes use **device pairing** (role `node`) during `connect`.
`node.pair.*` is a separate pairing store and does **not** gate the WS handshake.
Only clients that explicitly call `node.pair.*` use this flow.
## Concepts
- **Pending request**: a node asked to join; requires approval.
- **Paired node**: approved node with an issued auth token.
- **Bridge**: transport endpoint only; it forwards requests but does not decide
membership.
- **Transport**: the Gateway WS endpoint forwards requests but does not decide
membership. (Legacy TCP bridge support is deprecated/removed.)
## How pairing works
1. A node connects to the bridge and requests pairing.
1. A node connects to the Gateway WS and requests pairing.
2. The Gateway stores a **pending request** and emits `node.pair.requested`.
3. You approve or reject the request (CLI or UI).
4. On approval, the Gateway issues a **new token** (tokens are rotated on repair).
@@ -81,9 +85,8 @@ Security notes:
- Tokens are secrets; treat `paired.json` as sensitive.
- Rotating a token requires re-approval (or deleting the node entry).
## Bridge behavior
## Transport behavior
- The bridge is **transport only**; it does not store membership.
- The transport is **stateless**; it does not store membership.
- If the Gateway is offline or pairing is disabled, nodes cannot pair.
- If the bridge is running but the Gateway is in remote mode, pairing still
happens against the remote Gateways store.
- If the Gateway is in remote mode, pairing still happens against the remote Gateways store.

View File

@@ -94,8 +94,9 @@ clawdbot gateway --tailscale funnel --auth password
or `tailscale funnel` configuration on shutdown.
- `gateway.bind: "tailnet"` is a direct Tailnet bind (no HTTPS, no Serve/Funnel).
- `gateway.bind: "auto"` prefers loopback; use `tailnet` if you want Tailnet-only.
- Serve/Funnel only expose the **Gateway control UI + WS**. Node **bridge** traffic
uses the separate bridge port (default `18790`) and is **not** proxied by Serve.
- Serve/Funnel only expose the **Gateway control UI + WS**. Nodes connect over
the same Gateway WS endpoint, so Serve can work for node access. (Legacy TCP
bridge traffic is not proxied by Serve.)
## Browser control server (remote Gateway + local browser)

View File

@@ -49,7 +49,7 @@ WhatsApp / Telegram / Discord / Mattermost
┌───────────────────────────┐
│ Gateway │ ws://127.0.0.1:18789 (loopback-only)
│ (single source) │ tcp://0.0.0.0:18790 (Bridge)
│ (single source) │
│ │ http://<gateway-host>:18793
│ │ /__clawdbot__/canvas/ (Canvas host)
└───────────┬───────────────┘
@@ -58,8 +58,8 @@ WhatsApp / Telegram / Discord / Mattermost
├─ CLI (clawdbot …)
├─ Chat UI (SwiftUI)
├─ macOS app (Clawdbot.app)
├─ iOS node via Bridge + pairing
└─ Android node via Bridge + pairing
├─ iOS node via Gateway WS + pairing
└─ Android node via Gateway WS + pairing
```
Most operations flow through the **Gateway** (`clawdbot gateway`), a single long-running process that owns channel connections and the WebSocket control plane.
@@ -70,7 +70,7 @@ Most operations flow through the **Gateway** (`clawdbot gateway`), a single long
- **Loopback-first**: Gateway WS defaults to `ws://127.0.0.1:18789`.
- The wizard now generates a gateway token by default (even for loopback).
- For Tailnet access, run `clawdbot gateway --bind tailnet --token ...` (token is required for non-loopback binds).
- **Bridge for nodes**: optional LAN/tailnet-facing bridge on `tcp://0.0.0.0:18790` for paired nodes (Bonjour-discoverable).
- **Nodes**: connect to the Gateway WebSocket (LAN/tailnet/SSH as needed); legacy TCP bridge is deprecated/removed.
- **Canvas host**: HTTP file server on `canvasHost.port` (default `18793`), serving `/__clawdbot__/canvas/` for node WebViews; see [Gateway configuration](/gateway/configuration) (`canvasHost`).
- **Remote use**: SSH tunnel or tailnet/VPN; see [Remote access](/gateway/remote) and [Discovery](/gateway/discovery).

View File

@@ -36,7 +36,7 @@ Local trust:
- [Remote access (SSH)](/gateway/remote)
- [Tailscale](/gateway/tailscale)
## Nodes + bridge
## Nodes + transports
- [Nodes overview](/nodes)
- [Bridge protocol (legacy nodes)](/gateway/bridge-protocol)

View File

@@ -138,7 +138,7 @@ Notes:
## Safety + practical limits
- Camera and microphone access trigger the usual OS permission prompts (and require usage strings in Info.plist).
- Video clips are capped (currently `<= 60s`) to avoid oversized bridge payloads (base64 overhead + message limits).
- Video clips are capped (currently `<= 60s`) to avoid oversized node payloads (base64 overhead + message limits).
## macOS screen video (OS-level)

View File

@@ -8,9 +8,11 @@ read_when:
# Nodes
A **node** is a companion device (iOS/Android today) that connects to the Gateway over the **Bridge** and exposes a command surface (e.g. `canvas.*`, `camera.*`, `system.*`) via `node.invoke`. Bridge protocol details: [Bridge protocol](/gateway/bridge-protocol).
A **node** is a companion device (macOS/iOS/Android/headless) that connects to the Gateway **WebSocket** (same port as operators) with `role: "node"` and exposes a command surface (e.g. `canvas.*`, `camera.*`, `system.*`) via `node.invoke`. Protocol details: [Gateway protocol](/gateway/protocol).
macOS can also run in **node mode**: the menubar app connects to the Gateways bridge and exposes its local canvas/camera commands as a node (so `clawdbot nodes …` works against this Mac).
Legacy transport: [Bridge protocol](/gateway/bridge-protocol) (TCP JSONL; deprecated/removed for current nodes).
macOS can also run in **node mode**: the menubar app connects to the Gateways WS server and exposes its local canvas/camera commands as a node (so `clawdbot nodes …` works against this Mac).
Notes:
- Nodes are **peripherals**, not gateways. They dont run the gateway service.
@@ -18,21 +20,23 @@ Notes:
## Pairing + status
Pairing is gateway-owned and approval-based. See [Gateway pairing](/gateway/pairing) for the full flow.
**WS nodes use device pairing.** Nodes present a device identity during `connect`; the Gateway
creates a device pairing request for `role: node`. Approve via the devices CLI (or UI).
Quick CLI:
```bash
clawdbot nodes pending
clawdbot nodes approve <requestId>
clawdbot nodes reject <requestId>
clawdbot devices list
clawdbot devices approve <requestId>
clawdbot devices reject <requestId>
clawdbot nodes status
clawdbot nodes describe --node <idOrNameOrIp>
clawdbot nodes rename --node <idOrNameOrIp> --name "Kitchen iPad"
```
Notes:
- `nodes rename` stores a display name override in the gateway pairing store.
- `nodes status` marks a node as **paired** when its device pairing role includes `node`.
- `node.pair.*` (CLI: `clawdbot nodes pending/approve/reject`) is a separate gateway-owned
node pairing store; it does **not** gate the WS `connect` handshake.
## Remote node host (system.run)
@@ -57,7 +61,7 @@ clawdbot node run --host <gateway-host> --port 18789 --display-name "Build Node"
```bash
clawdbot node install --host <gateway-host> --port 18789 --display-name "Build Node"
clawdbot node start
clawdbot node restart
```
### Pair + name
@@ -239,6 +243,7 @@ Notes:
- `system.notify` respects notification permission state on the macOS app.
- `system.run` supports `--cwd`, `--env KEY=VAL`, `--command-timeout`, and `--needs-screen-recording`.
- `system.notify` supports `--priority <passive|active|timeSensitive>` and `--delivery <system|overlay|auto>`.
- macOS nodes drop `PATH` overrides; headless node hosts only accept `PATH` when it prepends the node host PATH.
- On macOS node mode, `system.run` is gated by exec approvals in the macOS app (Settings → Exec approvals).
Ask/allowlist/full behave the same as the headless node host; denied prompts return `SYSTEM_RUN_DENIED`.
- On headless node host, `system.run` is gated by exec approvals (`~/.clawdbot/exec-approvals.json`).
@@ -275,26 +280,40 @@ Nodes may include a `permissions` map in `node.list` / `node.describe`, keyed by
## Headless node host (cross-platform)
Clawdbot can run a **headless node host** (no UI) that connects to the Gateway
bridge and exposes `system.run` / `system.which`. This is useful on Linux/Windows
WebSocket and exposes `system.run` / `system.which`. This is useful on Linux/Windows
or for running a minimal node alongside a server.
Start it:
```bash
clawdbot node run --host <gateway-host> --port 18790
clawdbot node run --host <gateway-host> --port 18789
```
Notes:
- Pairing is still required (the Gateway will show a node approval prompt).
- The node host stores its node id + pairing token in `~/.clawdbot/node.json`.
- The node host stores its node id, token, display name, and gateway connection info in `~/.clawdbot/node.json`.
- Exec approvals are enforced locally via `~/.clawdbot/exec-approvals.json`
(see [Exec approvals](/tools/exec-approvals)).
- On macOS, the headless node host prefers the companion app exec host when reachable and falls
back to local execution if the app is unavailable. Set `CLAWDBOT_NODE_EXEC_HOST=app` to require
the app, or `CLAWDBOT_NODE_EXEC_FALLBACK=0` to disable fallback.
<<<<<<< HEAD
- Add `--tls` / `--tls-fingerprint` when the Gateway WS uses TLS.
||||||| parent of 2ab821adc (docs: align node transport with gateway ws)
- Add `--tls` / `--tls-fingerprint` when the bridge requires TLS.
=======
- Add `--tls` / `--tls-fingerprint` when the gateway requires TLS.
>>>>>>> 2ab821adc (docs: align node transport with gateway ws)
## Mac node mode
<<<<<<< HEAD
- The macOS menubar app connects to the Gateway WS server as a node (so `clawdbot nodes …` works against this Mac).
- In remote mode, the app opens an SSH tunnel for the Gateway port and connects to `localhost`.
||||||| parent of 2ab821adc (docs: align node transport with gateway ws)
- The macOS menubar app connects to the Gateway bridge as a node (so `clawdbot nodes …` works against this Mac).
- In remote mode, the app opens an SSH tunnel for the bridge port and connects to `localhost`.
=======
- The macOS menubar app connects to the Gateway WebSocket as a node (so `clawdbot nodes …` works against this Mac).
- In remote mode, the app opens an SSH tunnel for the gateway port and connects to `localhost`.
>>>>>>> 2ab821adc (docs: align node transport with gateway ws)

View File

@@ -41,7 +41,7 @@ Notes:
Who receives it:
- All WebSocket clients (macOS app, WebChat, etc.)
- All connected bridge nodes (iOS/Android), and also on node connect as an initial “current state” push.
- All connected nodes (iOS/Android), and also on node connect as an initial “current state” push.
## Client behavior
@@ -53,9 +53,9 @@ Who receives it:
### iOS node
- Uses the global list for `VoiceWakeManager` trigger detection.
- Editing Wake Words in Settings calls `voicewake.set` (over the bridge) and also keeps local wake-word detection responsive.
- Editing Wake Words in Settings calls `voicewake.set` (over the Gateway WS) and also keeps local wake-word detection responsive.
### Android node
- Exposes a Wake Words editor in Settings.
- Calls `voicewake.set` over the bridge so edits sync everywhere.
- Calls `voicewake.set` over the Gateway WS so edits sync everywhere.

View File

@@ -129,7 +129,6 @@ CLAWDBOT_IMAGE=clawdbot:latest
CLAWDBOT_GATEWAY_TOKEN=change-me-now
CLAWDBOT_GATEWAY_BIND=lan
CLAWDBOT_GATEWAY_PORT=18789
CLAWDBOT_BRIDGE_PORT=18790
CLAWDBOT_CONFIG_DIR=/root/.clawdbot
CLAWDBOT_WORKSPACE_DIR=/root/clawd
@@ -166,7 +165,6 @@ services:
- TERM=xterm-256color
- CLAWDBOT_GATEWAY_BIND=${CLAWDBOT_GATEWAY_BIND}
- CLAWDBOT_GATEWAY_PORT=${CLAWDBOT_GATEWAY_PORT}
- CLAWDBOT_BRIDGE_PORT=${CLAWDBOT_BRIDGE_PORT}
- CLAWDBOT_GATEWAY_TOKEN=${CLAWDBOT_GATEWAY_TOKEN}
- GOG_KEYRING_PASSWORD=${GOG_KEYRING_PASSWORD}
- XDG_CONFIG_HOME=${XDG_CONFIG_HOME}
@@ -179,9 +177,8 @@ services:
# To expose it publicly, remove the `127.0.0.1:` prefix and firewall accordingly.
- "127.0.0.1:${CLAWDBOT_GATEWAY_PORT}:18789"
# Optional: only if you run iOS/Android nodes against this VPS.
# If you expose these publicly, read /gateway/security and firewall accordingly.
# - "${CLAWDBOT_BRIDGE_PORT}:18790"
# Optional: only if you run iOS/Android nodes against this VPS and need Canvas host.
# If you expose this publicly, read /gateway/security and firewall accordingly.
# - "18793:18793"
command:
[

View File

@@ -40,7 +40,7 @@ node commands return `CANVAS_DISABLED`.
## Agent API surface
Canvas is exposed via the **node bridge**, so the agent can:
Canvas is exposed via the **Gateway WebSocket**, so the agent can:
- show/hide the panel
- navigate to a path or URL

View File

@@ -45,6 +45,13 @@ present. To reset manually:
rm ~/.clawdbot/disable-launchagent
```
## Attach-only mode
To force the macOS app to **never install or manage launchd**, launch it with
`--attach-only` (or `--no-launchd`). This sets `~/.clawdbot/disable-launchagent`,
so the app only attaches to an already running Gateway. You can toggle the same
behavior in Debug Settings.
## Remote mode
Remote mode never starts a local Gateway. The app uses an SSH tunnel to the

View File

@@ -8,7 +8,7 @@ read_when:
## What is shown
- We surface the current agent work state in the menu bar icon and in the first status row of the menu.
- Health status is hidden while work is active; it returns when all sessions are idle.
- The “Nodes” block in the menu lists **devices** only (gateway bridge nodes via `node.list`), not client/presence entries.
- The “Nodes” block in the menu lists **devices** only (paired nodes via `node.list`), not client/presence entries.
- A “Usage” section appears under Context when provider usage snapshots are available.
## State model

View File

@@ -1,5 +1,5 @@
---
summary: "macOS IPC architecture for Clawdbot app, gateway node bridge, and PeekabooBridge"
summary: "macOS IPC architecture for Clawdbot app, gateway node transport, and PeekabooBridge"
read_when:
- Editing IPC contracts or menu bar app IPC
---
@@ -13,21 +13,21 @@ read_when:
- Predictable permissions: always the same signed bundle ID, launched by launchd, so TCC grants stick.
## How it works
### Gateway + node bridge
### Gateway + node transport
- The app runs the Gateway (local mode) and connects to it as a node.
- Agent actions are performed via `node.invoke` (e.g. `system.run`, `system.notify`, `canvas.*`).
### Node service + app IPC
- A headless node host service connects to the Gateway bridge.
- A headless node host service connects to the Gateway WebSocket.
- `system.run` requests are forwarded to the macOS app over a local Unix socket.
- The app performs the exec in UI context, prompts if needed, and returns output.
Diagram (SCI):
```
Agent -> Gateway -> Bridge -> Node Service (TS)
| IPC (UDS + token + HMAC + TTL)
v
Mac App (UI + TCC + system.run)
Agent -> Gateway -> Node Service (WS)
| IPC (UDS + token + HMAC + TTL)
v
Mac App (UI + TCC + system.run)
```
### PeekabooBridge (UI automation)

View File

@@ -62,7 +62,7 @@ Node service + app IPC:
Diagram (SCI):
```
Gateway -> Bridge -> Node Service (TS)
Gateway -> Node Service (WS)
| IPC (UDS + token + HMAC + TTL)
v
Mac App (UI + TCC + system.run)
@@ -99,7 +99,7 @@ Example:
```
Notes:
- `allowlist` entries are JSON-encoded argv arrays.
- `allowlist` entries are glob patterns for resolved binary paths.
- Choosing “Always Allow” in the prompt adds that command to the allowlist.
- `system.run` environment overrides are filtered (drops `PATH`, `DYLD_*`, `LD_*`, `NODE_OPTIONS`, `PYTHON*`, `PERL*`, `RUBYOPT`) and then merged with the apps environment.

View File

@@ -7,6 +7,8 @@ read_when:
*You just woke up. Time to figure out who you are.*
There is no memory yet. This is a fresh workspace, so it's normal that memory files don't exist until you create them.
## The Conversation
Don't interrogate. Don't be robotic. Just... talk.

View File

@@ -719,11 +719,11 @@ See the full config examples in [Browser](/tools/browser#use-brave-or-another-ch
### How do commands propagate between Telegram, the gateway, and nodes?
Telegram messages are handled by the **gateway**. The gateway runs the agent and
only then calls nodes over the **Bridge** when a node tool is needed:
only then calls nodes over the **Gateway WebSocket** when a node tool is needed:
Telegram → Gateway → Agent → `node.*` → Node → Gateway → Telegram
Nodes dont see inbound provider traffic; they only receive bridge RPC calls.
Nodes dont see inbound provider traffic; they only receive node RPC calls.
### How can my agent access my computer if the Gateway is hosted remotely?
@@ -733,29 +733,28 @@ call `node.*` tools (screen, camera, system) on your local machine over the Brid
Typical setup:
1) Run the Gateway on the alwayson host (VPS/home server).
2) Put the Gateway host + your computer on the same tailnet.
3) Enable the bridge on the Gateway host:
```json5
{ bridge: { enabled: true, bind: "auto" } }
```
4) Open the macOS app locally and connect in **Remote over SSH** mode so it can tunnel
the bridge port and register as a node.
3) Ensure the Gateway WS is reachable (tailnet bind or SSH tunnel).
4) Open the macOS app locally and connect in **Remote over SSH** mode (or direct tailnet)
so it can register as a node.
5) Approve the node on the Gateway:
```bash
clawdbot nodes pending
clawdbot nodes approve <requestId>
```
No separate TCP bridge is required; nodes connect over the Gateway WebSocket.
Security reminder: pairing a macOS node allows `system.run` on that machine. Only
pair devices you trust, and review [Security](/gateway/security).
Docs: [Nodes](/nodes), [Bridge protocol](/gateway/bridge-protocol), [macOS remote mode](/platforms/mac/remote), [Security](/gateway/security).
Docs: [Nodes](/nodes), [Gateway protocol](/gateway/protocol), [macOS remote mode](/platforms/mac/remote), [Security](/gateway/security).
### Do nodes run a gateway service?
No. Only **one gateway** should run per host unless you intentionally run isolated profiles (see [Multiple gateways](/gateway/multiple-gateways)). Nodes are peripherals that connect
to the gateway (iOS/Android nodes, or macOS “node mode” in the menubar app).
A full restart is required for `gateway`, `bridge`, `discovery`, and `canvasHost` changes.
A full restart is required for `gateway`, `discovery`, and `canvasHost` changes.
### Is there an API / RPC way to apply config?
@@ -797,26 +796,19 @@ This keeps the gateway bound to loopback and exposes HTTPS via Tailscale. See [T
### How do I connect a Mac node to a remote Gateway (Tailscale Serve)?
Serve only exposes the **Gateway Control UI**. Nodes use the **bridge port**.
Serve exposes the **Gateway Control UI + WS**. Nodes connect over the same Gateway WS endpoint.
Recommended setup:
1) **Enable the bridge on the gateway host**:
```json5
{
bridge: { enabled: true, bind: "auto" }
}
```
`auto` prefers a tailnet IP when Tailscale is present.
2) **Make sure the VPS + Mac are on the same tailnet**.
3) **Use the macOS app in Remote mode** (SSH target can be the tailnet hostname).
The app will tunnel the bridge port and connect as a node.
4) **Approve the node** on the gateway:
1) **Make sure the VPS + Mac are on the same tailnet**.
2) **Use the macOS app in Remote mode** (SSH target can be the tailnet hostname).
The app will tunnel the Gateway port and connect as a node.
3) **Approve the node** on the gateway:
```bash
clawdbot nodes pending
clawdbot nodes approve <requestId>
```
Docs: [Bridge protocol](/gateway/bridge-protocol), [Discovery](/gateway/discovery), [macOS remote mode](/platforms/mac/remote).
Docs: [Gateway protocol](/gateway/protocol), [Discovery](/gateway/discovery), [macOS remote mode](/platforms/mac/remote).
## Env vars and .env loading
@@ -1067,6 +1059,17 @@ You can also force a specific auth profile for the provider (per session):
Tip: `/model status` shows which agent is active, which `auth-profiles.json` file is being used, and which auth profile will be tried next.
It also shows the configured provider endpoint (`baseUrl`) and API mode (`api`) when available.
### How do I unpin a profile I set with `@profile`?
Re-run `/model` **without** the `@profile` suffix:
```
/model anthropic/claude-opus-4-5
```
If you want to return to the default, pick it from `/model` (or send `/model <default provider/model>`).
Use `/model status` to confirm which auth profile is active.
### Why do I see “Model … is not allowed” and then no reply?
If `agents.defaults.models` is set, it becomes the **allowlist** for `/model` and any
@@ -1276,7 +1279,7 @@ Fix: either provide Google auth, or remove/avoid Google models in `agents.defaul
Cause: the session history contains **thinking blocks without signatures** (often from
an aborted/partial stream). Google Antigravity requires signatures for thinking blocks.
Fix: start a **new session** or set `/thinking off` for that agent.
Fix: Clawdbot now strips unsigned thinking blocks for Google Antigravity Claude. If it still appears, start a **new session** or set `/thinking off` for that agent.
## Auth profiles: what they are and how to manage them

View File

@@ -45,27 +45,29 @@ Stored under `~/.clawdbot/credentials/`:
Treat these as sensitive (they gate access to your assistant).
## 2) Node pairing (iOS/Android nodes joining the gateway)
## 2) Node device pairing (iOS/Android/macOS/headless nodes)
Nodes (iOS/Android, future hardware, etc.) connect to the Gateway and request to join.
The Gateway keeps an authoritative allowlist; new nodes require explicit approve/reject.
Nodes connect to the Gateway as **devices** with `role: node`. The Gateway
creates a device pairing request that must be approved.
### Approve a node
### Approve a node device
```bash
clawdbot nodes pending
clawdbot nodes approve <requestId>
clawdbot devices list
clawdbot devices approve <requestId>
clawdbot devices reject <requestId>
```
### Where the state lives
Stored under `~/.clawdbot/nodes/`:
Stored under `~/.clawdbot/devices/`:
- `pending.json` (short-lived; pending requests expire)
- `paired.json` (paired nodes + tokens)
- `paired.json` (paired devices + tokens)
### Details
### Notes
Full protocol + design notes: [Gateway pairing](/gateway/pairing)
- The legacy `node.pair.*` API (CLI: `clawdbot nodes pending/approve`) is a
separate gateway-owned pairing store. WS nodes still require device pairing.
## Related docs

View File

@@ -22,7 +22,7 @@ Exec approvals are enforced locally on the execution host:
- **gateway host** → `clawdbot` process on the gateway machine
- **node host** → node runner (macOS companion app or headless node host)
Planned macOS split:
macOS split:
- **node host service** forwards `system.run` to the **macOS app** over local IPC.
- **macOS app** enforces approvals + executes the command in UI context.
@@ -103,8 +103,8 @@ Each allowlist entry tracks:
## Auto-allow skill CLIs
When **Auto-allow skill CLIs** is enabled, executables referenced by known skills
are treated as allowlisted on nodes (macOS node or headless node host). This uses the Bridge RPC to ask the
gateway for the skill bin list. Disable this if you want strict manual allowlists.
are treated as allowlisted on nodes (macOS node or headless node host). This uses
`skills.bins` over the Gateway RPC to fetch the skill bin list. Disable this if you want strict manual allowlists.
## Safe bins (stdin-only)
@@ -151,12 +151,12 @@ Actions:
- **Always allow** → add to allowlist + run
- **Deny** → block
### macOS IPC flow (planned)
### macOS IPC flow
```
Gateway -> Bridge -> Node Service (TS)
| IPC (UDS + token + HMAC + TTL)
v
Mac App (UI + approvals + system.run)
Gateway -> Node Service (WS)
| IPC (UDS + token + HMAC + TTL)
v
Mac App (UI + approvals + system.run)
```
Security notes:

View File

@@ -66,8 +66,8 @@ Example:
- `host=sandbox`: runs `sh -lc` (login shell) inside the container, so `/etc/profile` may reset `PATH`.
Clawdbot prepends `env.PATH` after profile sourcing; `tools.exec.pathPrepend` applies here too.
- `host=node`: only env overrides you pass are sent to the node. `tools.exec.pathPrepend` only applies
if the exec call already sets `env.PATH`. Node PATH overrides are accepted only when they prepend
the node host PATH (no replacement).
if the exec call already sets `env.PATH`. Headless node hosts accept `PATH` only when it prepends
the node host PATH (no replacement). macOS nodes drop `PATH` overrides entirely.
Per-agent node binding (use the agent list index in config):