2025-12-09 17:51:05 +00:00
|
|
|
|
---
|
2026-01-08 23:06:56 +01:00
|
|
|
|
summary: "Clawdbot macOS companion app (menu bar + gateway broker)"
|
2025-12-09 17:51:05 +00:00
|
|
|
|
read_when:
|
|
|
|
|
|
- Implementing macOS app features
|
2025-12-20 02:08:04 +00:00
|
|
|
|
- Changing gateway lifecycle or node bridging on macOS
|
2025-12-09 17:51:05 +00:00
|
|
|
|
---
|
2026-01-04 14:32:47 +00:00
|
|
|
|
# Clawdbot macOS Companion (menu bar + gateway broker)
|
2025-12-05 23:13:53 +01:00
|
|
|
|
|
2026-01-08 23:06:56 +01:00
|
|
|
|
The macOS app is the **menu‑bar companion** for Clawdbot. It owns permissions,
|
|
|
|
|
|
manages the Gateway locally, and exposes macOS capabilities to the agent as a
|
|
|
|
|
|
node.
|
2025-12-05 23:13:53 +01:00
|
|
|
|
|
2026-01-08 23:06:56 +01:00
|
|
|
|
## What it does
|
2026-01-07 21:37:05 +01:00
|
|
|
|
|
2026-01-08 23:06:56 +01:00
|
|
|
|
- Shows native notifications and status in the menu bar.
|
|
|
|
|
|
- Owns TCC prompts (Notifications, Accessibility, Screen Recording, Microphone,
|
|
|
|
|
|
Speech Recognition, Automation/AppleScript).
|
|
|
|
|
|
- Runs or connects to the Gateway (local or remote).
|
|
|
|
|
|
- Exposes macOS‑only tools (Canvas, Camera, Screen Recording, `system.run`).
|
|
|
|
|
|
- Optionally hosts **PeekabooBridge** for UI automation.
|
2026-01-13 07:58:47 +00:00
|
|
|
|
- Installs the global CLI (`clawdbot`) via npm/pnpm on request (bun not recommended for the Gateway runtime).
|
2026-01-08 23:06:56 +01:00
|
|
|
|
|
|
|
|
|
|
## Local vs remote mode
|
|
|
|
|
|
|
|
|
|
|
|
- **Local** (default): the app ensures a local Gateway is running via launchd.
|
|
|
|
|
|
- **Remote**: the app connects to a Gateway over SSH/Tailscale and never starts
|
|
|
|
|
|
a local process.
|
|
|
|
|
|
- **Attach‑only** (debug): the app connects to an already‑running local Gateway
|
|
|
|
|
|
and never spawns its own.
|
|
|
|
|
|
|
|
|
|
|
|
## Launchd control
|
|
|
|
|
|
|
2026-01-11 02:17:10 +01:00
|
|
|
|
The app manages a per‑user LaunchAgent labeled `com.clawdbot.gateway`
|
|
|
|
|
|
(or `com.clawdbot.<profile>` when using `--profile`/`CLAWDBOT_PROFILE`).
|
2026-01-07 21:37:05 +01:00
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
launchctl kickstart -k gui/$UID/com.clawdbot.gateway
|
|
|
|
|
|
launchctl bootout gui/$UID/com.clawdbot.gateway
|
|
|
|
|
|
```
|
|
|
|
|
|
|
2026-01-11 02:17:10 +01:00
|
|
|
|
Replace the label with `com.clawdbot.<profile>` when running a named profile.
|
|
|
|
|
|
|
2026-01-08 23:06:56 +01:00
|
|
|
|
If the LaunchAgent isn’t installed, enable it from the app or run
|
|
|
|
|
|
`clawdbot daemon install`.
|
2025-12-20 02:08:04 +00:00
|
|
|
|
|
2026-01-08 23:06:56 +01:00
|
|
|
|
## Node capabilities (mac)
|
2025-12-20 02:08:04 +00:00
|
|
|
|
|
2026-01-08 23:06:56 +01:00
|
|
|
|
The macOS app presents itself as a node. Common commands:
|
2025-12-20 02:08:04 +00:00
|
|
|
|
|
2026-01-08 23:06:56 +01:00
|
|
|
|
- Canvas: `canvas.present`, `canvas.navigate`, `canvas.eval`, `canvas.snapshot`, `canvas.a2ui.*`
|
|
|
|
|
|
- Camera: `camera.snap`, `camera.clip`
|
|
|
|
|
|
- Screen: `screen.record`
|
|
|
|
|
|
- System: `system.run`, `system.notify`
|
2025-12-05 23:13:53 +01:00
|
|
|
|
|
2026-01-08 23:06:56 +01:00
|
|
|
|
The node reports a `permissions` map so agents can decide what’s allowed.
|
2025-12-12 23:22:40 +00:00
|
|
|
|
|
2026-01-08 23:06:56 +01:00
|
|
|
|
## Deep links
|
2025-12-12 23:22:40 +00:00
|
|
|
|
|
2026-01-08 23:06:56 +01:00
|
|
|
|
The app registers the `clawdbot://` URL scheme for local actions.
|
2025-12-12 23:22:40 +00:00
|
|
|
|
|
2026-01-04 14:32:47 +00:00
|
|
|
|
### `clawdbot://agent`
|
2025-12-12 23:22:40 +00:00
|
|
|
|
|
2026-01-08 23:06:56 +01:00
|
|
|
|
Triggers a Gateway `agent` request.
|
2025-12-12 23:22:40 +00:00
|
|
|
|
|
|
|
|
|
|
```bash
|
2026-01-04 14:32:47 +00:00
|
|
|
|
open 'clawdbot://agent?message=Hello%20from%20deep%20link'
|
2025-12-12 23:22:40 +00:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
Query parameters:
|
2026-01-08 23:06:56 +01:00
|
|
|
|
- `message` (required)
|
|
|
|
|
|
- `sessionKey` (optional)
|
|
|
|
|
|
- `thinking` (optional)
|
2026-01-13 07:15:57 +00:00
|
|
|
|
- `deliver` / `to` / `channel` (optional)
|
2026-01-08 23:06:56 +01:00
|
|
|
|
- `timeoutSeconds` (optional)
|
|
|
|
|
|
- `key` (optional unattended mode key)
|
|
|
|
|
|
|
|
|
|
|
|
Safety:
|
|
|
|
|
|
- Without `key`, the app prompts for confirmation.
|
|
|
|
|
|
- With a valid `key`, the run is unattended (intended for personal automations).
|
|
|
|
|
|
|
|
|
|
|
|
## Onboarding flow (typical)
|
|
|
|
|
|
|
|
|
|
|
|
1) Install and launch **Clawdbot.app**.
|
|
|
|
|
|
2) Complete the permissions checklist (TCC prompts).
|
|
|
|
|
|
3) Ensure **Local** mode is active and the Gateway is running.
|
2026-01-11 10:15:37 +00:00
|
|
|
|
4) Install the CLI if you want terminal access.
|
2025-12-12 23:22:40 +00:00
|
|
|
|
|
2025-12-05 23:13:53 +01:00
|
|
|
|
## Build & dev workflow (native)
|
2026-01-08 23:06:56 +01:00
|
|
|
|
|
|
|
|
|
|
- `cd apps/macos && swift build`
|
|
|
|
|
|
- `swift run Clawdbot` (or Xcode)
|
2026-01-11 10:15:37 +00:00
|
|
|
|
- Package app: `scripts/package-mac-app.sh`
|
2026-01-08 23:06:56 +01:00
|
|
|
|
|
2026-01-10 23:39:14 +01:00
|
|
|
|
## Debug gateway discovery (macOS CLI)
|
|
|
|
|
|
|
|
|
|
|
|
Use the debug CLI to exercise the same Bonjour + wide‑area discovery code that the
|
|
|
|
|
|
macOS app uses, without launching the app.
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
cd apps/macos
|
|
|
|
|
|
swift run clawdbot-mac-discovery --timeout 3000 --json
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
Options:
|
|
|
|
|
|
- `--include-local`: include gateways that would be filtered as “local”
|
|
|
|
|
|
- `--timeout <ms>`: overall discovery window (default `2000`)
|
|
|
|
|
|
- `--json`: structured output for diffing
|
|
|
|
|
|
|
|
|
|
|
|
Tip: compare against `pnpm clawdbot gateway discover --json` to see whether the
|
|
|
|
|
|
macOS app’s discovery pipeline (NWBrowser + tailnet DNS‑SD fallback) differs from
|
|
|
|
|
|
the Node CLI’s `dns-sd` based discovery.
|
|
|
|
|
|
|
2026-01-16 01:59:14 +00:00
|
|
|
|
## Remote connection plumbing (SSH tunnels)
|
|
|
|
|
|
|
|
|
|
|
|
When the macOS app runs in **Remote** mode, it opens SSH tunnels so local UI
|
|
|
|
|
|
components can talk to a remote Gateway as if it were on localhost. There are
|
|
|
|
|
|
two independent tunnels:
|
|
|
|
|
|
|
|
|
|
|
|
### Control tunnel (Gateway control/WebSocket port)
|
|
|
|
|
|
- **Purpose:** health checks, status, Web Chat, config, and other control-plane calls.
|
|
|
|
|
|
- **Local port:** the Gateway port (default `18789`), always stable.
|
|
|
|
|
|
- **Remote port:** the same Gateway port on the remote host.
|
|
|
|
|
|
- **Behavior:** no random local port; the app reuses an existing healthy tunnel
|
|
|
|
|
|
or restarts it if needed.
|
|
|
|
|
|
- **SSH shape:** `ssh -N -L <local>:127.0.0.1:<remote>` with BatchMode +
|
|
|
|
|
|
ExitOnForwardFailure + keepalive options.
|
|
|
|
|
|
|
|
|
|
|
|
### Node bridge tunnel (macOS node mode)
|
|
|
|
|
|
- **Purpose:** connect the macOS node to the Gateway **Bridge** protocol (TCP JSONL).
|
|
|
|
|
|
- **Remote port:** `gatewayPort + 1` (default `18790`), derived from the Gateway port.
|
|
|
|
|
|
- **Local port preference:** `CLAWDBOT_BRIDGE_PORT` or the default `18790`.
|
|
|
|
|
|
- **Behavior:** prefer the default bridge port for consistency; fall back to a
|
|
|
|
|
|
random local port if the preferred one is busy. The node then connects to the
|
|
|
|
|
|
resolved local port.
|
|
|
|
|
|
|
|
|
|
|
|
For setup steps, see [macOS remote access](/platforms/mac/remote). For protocol
|
|
|
|
|
|
details, see [Bridge protocol](/gateway/bridge-protocol).
|
|
|
|
|
|
|
2026-01-08 23:06:56 +01:00
|
|
|
|
## Related docs
|
|
|
|
|
|
|
|
|
|
|
|
- [Gateway runbook](/gateway)
|
2026-01-11 10:15:37 +00:00
|
|
|
|
- [Gateway (macOS)](/platforms/mac/bundled-gateway)
|
2026-01-08 23:06:56 +01:00
|
|
|
|
- [macOS permissions](/platforms/mac/permissions)
|
|
|
|
|
|
- [Canvas](/platforms/mac/canvas)
|