chore: rename project to clawdbot
This commit is contained in:
@@ -1,31 +1,31 @@
|
||||
---
|
||||
summary: "Bundled bun gateway: packaging, launchd, signing, and bytecode"
|
||||
read_when:
|
||||
- Packaging Clawdis.app
|
||||
- Packaging Clawdbot.app
|
||||
- Debugging the bundled gateway binary
|
||||
- Changing bun build flags or codesigning
|
||||
---
|
||||
|
||||
# Bundled bun Gateway (macOS)
|
||||
|
||||
Goal: ship **Clawdis.app** with a self-contained relay binary that can run both the CLI and the Gateway daemon. No global `npm install -g clawdis`, no system Node requirement.
|
||||
Goal: ship **Clawdbot.app** with a self-contained relay binary that can run both the CLI and the Gateway daemon. No global `npm install -g clawdbot`, no system Node requirement.
|
||||
|
||||
## What gets bundled
|
||||
|
||||
App bundle layout:
|
||||
|
||||
- `Clawdis.app/Contents/Resources/Relay/clawdis`
|
||||
- `Clawdbot.app/Contents/Resources/Relay/clawdbot`
|
||||
- bun `--compile` relay executable built from `dist/macos/relay.js`
|
||||
- Supports:
|
||||
- `clawdis …` (CLI)
|
||||
- `clawdis gateway-daemon …` (LaunchAgent daemon)
|
||||
- `Clawdis.app/Contents/Resources/Relay/package.json`
|
||||
- `clawdbot …` (CLI)
|
||||
- `clawdbot gateway-daemon …` (LaunchAgent daemon)
|
||||
- `Clawdbot.app/Contents/Resources/Relay/package.json`
|
||||
- tiny “p runtime compatibility” file (see below)
|
||||
- `Clawdis.app/Contents/Resources/Relay/theme/`
|
||||
- `Clawdbot.app/Contents/Resources/Relay/theme/`
|
||||
- p TUI theme payload (optional, but strongly recommended)
|
||||
|
||||
Why the sidecar files matter:
|
||||
- The embedded p runtime detects “bun binary mode” and then looks for `package.json` + `theme/` **next to `process.execPath`** (i.e. next to `clawdis`).
|
||||
- The embedded p runtime detects “bun binary mode” and then looks for `package.json` + `theme/` **next to `process.execPath`** (i.e. next to `clawdbot`).
|
||||
- So even if bun can embed assets, the runtime expects filesystem paths. Keep the sidecar files.
|
||||
|
||||
## Build pipeline
|
||||
@@ -46,29 +46,29 @@ Important bundler flags:
|
||||
- Reason: avoid bundling Electron stubs in the relay binary
|
||||
|
||||
Version injection:
|
||||
- `--define "__CLAWDIS_VERSION__=\"<pkg version>\""`
|
||||
- `src/version.ts` also supports `__CLAWDIS_VERSION__` (and `CLAWDIS_BUNDLED_VERSION`) so `--version` doesn’t depend on reading `package.json` at runtime.
|
||||
- `--define "__CLAWDBOT_VERSION__=\"<pkg version>\""`
|
||||
- `src/version.ts` also supports `__CLAWDBOT_VERSION__` (and `CLAWDBOT_BUNDLED_VERSION`) so `--version` doesn’t depend on reading `package.json` at runtime.
|
||||
|
||||
## Launchd (Gateway as LaunchAgent)
|
||||
|
||||
Label:
|
||||
- `com.clawdis.gateway`
|
||||
- `com.clawdbot.gateway`
|
||||
|
||||
Plist location (per-user):
|
||||
- `~/Library/LaunchAgents/com.clawdis.gateway.plist`
|
||||
- `~/Library/LaunchAgents/com.clawdbot.gateway.plist`
|
||||
|
||||
Manager:
|
||||
- `apps/macos/Sources/Clawdis/GatewayLaunchAgentManager.swift`
|
||||
- `apps/macos/Sources/Clawdbot/GatewayLaunchAgentManager.swift`
|
||||
|
||||
Behavior:
|
||||
- “Clawdis Active” enables/disables the LaunchAgent.
|
||||
- “Clawdbot Active” enables/disables the LaunchAgent.
|
||||
- App quit does **not** stop the gateway (launchd keeps it alive).
|
||||
|
||||
Logging:
|
||||
- launchd stdout/err: `/tmp/clawdis/clawdis-gateway.log`
|
||||
- launchd stdout/err: `/tmp/clawdbot/clawdbot-gateway.log`
|
||||
|
||||
Default LaunchAgent env:
|
||||
- `CLAWDIS_IMAGE_BACKEND=sips` (avoid sharp native addon under bun)
|
||||
- `CLAWDBOT_IMAGE_BACKEND=sips` (avoid sharp native addon under bun)
|
||||
|
||||
## Codesigning (hardened runtime + bun)
|
||||
|
||||
@@ -77,7 +77,7 @@ Symptom (when mis-signed):
|
||||
|
||||
Fix:
|
||||
- The bun executable needs JIT-ish permissions under hardened runtime.
|
||||
- `scripts/codesign-mac-app.sh` signs `Relay/clawdis` with:
|
||||
- `scripts/codesign-mac-app.sh` signs `Relay/clawdbot` with:
|
||||
- `com.apple.security.cs.allow-jit`
|
||||
- `com.apple.security.cs.allow-unsigned-executable-memory`
|
||||
|
||||
@@ -105,17 +105,17 @@ It’s started from the relay daemon process, so the relay binary includes Playw
|
||||
From a packaged app (local build):
|
||||
|
||||
```bash
|
||||
dist/Clawdis.app/Contents/Resources/Relay/clawdis --version
|
||||
dist/Clawdbot.app/Contents/Resources/Relay/clawdbot --version
|
||||
|
||||
CLAWDIS_SKIP_PROVIDERS=1 \
|
||||
CLAWDIS_SKIP_CANVAS_HOST=1 \
|
||||
dist/Clawdis.app/Contents/Resources/Relay/clawdis gateway-daemon --port 18999 --bind loopback
|
||||
CLAWDBOT_SKIP_PROVIDERS=1 \
|
||||
CLAWDBOT_SKIP_CANVAS_HOST=1 \
|
||||
dist/Clawdbot.app/Contents/Resources/Relay/clawdbot gateway-daemon --port 18999 --bind loopback
|
||||
```
|
||||
|
||||
Then, in another shell:
|
||||
|
||||
```bash
|
||||
pnpm -s clawdis gateway call health --url ws://127.0.0.1:18999 --timeout 3000
|
||||
pnpm -s clawdbot gateway call health --url ws://127.0.0.1:18999 --timeout 3000
|
||||
```
|
||||
|
||||
## Repo hygiene
|
||||
|
||||
@@ -12,7 +12,7 @@ Status: draft spec · Date: 2025-12-12
|
||||
|
||||
Note: for iOS/Android nodes that should render agent-edited HTML/CSS/JS over the network, prefer the Gateway `canvasHost` (serves `~/clawd/canvas` over LAN/tailnet with live reload). A2UI is also **hosted by the Gateway** over HTTP. This doc focuses on the macOS in-app canvas panel. See `docs/configuration.md`.
|
||||
|
||||
Clawdis can embed an agent-controlled “visual workspace” panel (“Canvas”) inside the macOS app using `WKWebView`, served via a **custom URL scheme** (no loopback HTTP port required).
|
||||
Clawdbot can embed an agent-controlled “visual workspace” panel (“Canvas”) inside the macOS app using `WKWebView`, served via a **custom URL scheme** (no loopback HTTP port required).
|
||||
|
||||
This is designed for:
|
||||
- Agent-written HTML/CSS/JS on disk (per-session directory).
|
||||
@@ -32,12 +32,12 @@ If a Canvas page truly needs “real web” semantics (CORS, fetch to loopback e
|
||||
## URL ↔ directory mapping
|
||||
|
||||
The Canvas scheme is:
|
||||
- `clawdis-canvas://<session>/<path>`
|
||||
- `clawdbot-canvas://<session>/<path>`
|
||||
|
||||
Routing model:
|
||||
- `clawdis-canvas://main/` → `<canvasRoot>/main/index.html` (or `index.htm`)
|
||||
- `clawdis-canvas://main/yolo` → `<canvasRoot>/main/yolo/index.html` (or `index.htm`)
|
||||
- `clawdis-canvas://main/assets/app.css` → `<canvasRoot>/main/assets/app.css`
|
||||
- `clawdbot-canvas://main/` → `<canvasRoot>/main/index.html` (or `index.htm`)
|
||||
- `clawdbot-canvas://main/yolo` → `<canvasRoot>/main/yolo/index.html` (or `index.htm`)
|
||||
- `clawdbot-canvas://main/assets/app.css` → `<canvasRoot>/main/assets/app.css`
|
||||
|
||||
Directory listings are not served.
|
||||
|
||||
@@ -47,9 +47,9 @@ This is a visual placeholder only (no A2UI renderer).
|
||||
### Suggested on-disk location
|
||||
|
||||
Store Canvas state under the app support directory:
|
||||
- `~/Library/Application Support/Clawdis/canvas/<session>/…`
|
||||
- `~/Library/Application Support/Clawdbot/canvas/<session>/…`
|
||||
|
||||
This keeps it alongside other app-owned state and avoids mixing with `~/.clawdis/` gateway config.
|
||||
This keeps it alongside other app-owned state and avoids mixing with `~/.clawdbot/` gateway config.
|
||||
|
||||
## Panel behavior (agent-controlled)
|
||||
|
||||
@@ -78,34 +78,34 @@ Canvas is exposed via the Gateway **node bridge**, so the agent can:
|
||||
- Capture a snapshot image of the current canvas view.
|
||||
- Optionally set panel placement (screen `x/y` + `width/height`) when showing/navigating.
|
||||
|
||||
This should be modeled after `WebChatManager`/`WebChatSwiftUIWindowController` but targeting `clawdis-canvas://…` URLs.
|
||||
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 (`clawdis://agent?...`) so *any* UI surface (Canvas, WebChat, native views) can trigger a new agent run. See `docs/clawdis-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/clawdbot-mac.md`.
|
||||
|
||||
## Agent commands (current)
|
||||
|
||||
Use the main `clawdis` CLI; it invokes canvas commands via `node.invoke`.
|
||||
Use the main `clawdbot` CLI; it invokes canvas commands via `node.invoke`.
|
||||
|
||||
- `clawdis canvas present [--node <id>] [--target <...>] [--x/--y/--width/--height]`
|
||||
- `clawdbot canvas present [--node <id>] [--target <...>] [--x/--y/--width/--height]`
|
||||
- Local targets map into the session directory via the custom scheme (directory targets resolve `index.html|index.htm`).
|
||||
- If `/` has no index file, Canvas shows the built-in scaffold page and returns `status: "welcome"`.
|
||||
- `clawdis canvas hide [--node <id>]`
|
||||
- `clawdis canvas eval --js <code> [--node <id>]`
|
||||
- `clawdis canvas snapshot [--node <id>]`
|
||||
- `clawdbot canvas hide [--node <id>]`
|
||||
- `clawdbot canvas eval --js <code> [--node <id>]`
|
||||
- `clawdbot canvas snapshot [--node <id>]`
|
||||
|
||||
### Canvas A2UI
|
||||
|
||||
Canvas A2UI is hosted by the **Gateway canvas host** at:
|
||||
|
||||
```
|
||||
http://<gateway-host>:18793/__clawdis__/a2ui/
|
||||
http://<gateway-host>:18793/__clawdbot__/a2ui/
|
||||
```
|
||||
|
||||
The macOS app simply renders that page in the Canvas panel. The agent can drive it with JSONL **server→client protocol messages** (one JSON object per line):
|
||||
|
||||
- `clawdis canvas a2ui push --jsonl <path> [--node <id>]`
|
||||
- `clawdis canvas a2ui reset [--node <id>]`
|
||||
- `clawdbot canvas a2ui push --jsonl <path> [--node <id>]`
|
||||
- `clawdbot canvas a2ui reset [--node <id>]`
|
||||
|
||||
`push` expects a JSONL file where **each line is a single JSON object** (parsed and forwarded to the in-page A2UI renderer).
|
||||
|
||||
@@ -117,31 +117,31 @@ cat > /tmp/a2ui-v0.8.jsonl <<'EOF'
|
||||
{"beginRendering":{"surfaceId":"main","root":"root"}}
|
||||
EOF
|
||||
|
||||
clawdis canvas a2ui push --jsonl /tmp/a2ui-v0.8.jsonl --node <id>
|
||||
clawdbot canvas a2ui push --jsonl /tmp/a2ui-v0.8.jsonl --node <id>
|
||||
```
|
||||
|
||||
Notes:
|
||||
- This does **not** support the A2UI v0.9 examples using `createSurface`.
|
||||
- A2UI **fails** if the Gateway canvas host is unreachable (no local fallback).
|
||||
- `canvas a2ui push` validates JSONL (line numbers on errors) and rejects v0.9 payloads.
|
||||
- Quick smoke: `clawdis canvas a2ui push --text "Hello from A2UI"` renders a minimal v0.8 view.
|
||||
- Quick smoke: `clawdbot canvas a2ui push --text "Hello from A2UI"` renders a minimal v0.8 view.
|
||||
|
||||
## Triggering agent runs from Canvas (deep links)
|
||||
|
||||
Canvas can trigger new agent runs via the macOS app deep-link scheme:
|
||||
- `clawdis://agent?...`
|
||||
- `clawdbot://agent?...`
|
||||
|
||||
This is intentionally separate from `clawdis-canvas://…` (which is only for serving local Canvas files into the `WKWebView`).
|
||||
This is intentionally separate from `clawdbot-canvas://…` (which is only for serving local Canvas files into the `WKWebView`).
|
||||
|
||||
Suggested patterns:
|
||||
- HTML: render links/buttons that navigate to `clawdis://agent?message=...`.
|
||||
- JS: set `window.location.href = 'clawdis://agent?...'` for “run this now” actions.
|
||||
- HTML: render links/buttons that navigate to `clawdbot://agent?message=...`.
|
||||
- JS: set `window.location.href = 'clawdbot://agent?...'` for “run this now” actions.
|
||||
|
||||
Implementation note (important):
|
||||
- In `WKWebView`, intercept `clawdis://…` navigations in `WKNavigationDelegate` and forward them to the app, e.g. by calling `DeepLinkHandler.shared.handle(url:)` and returning `.cancel` for the navigation.
|
||||
- In `WKWebView`, intercept `clawdbot://…` navigations in `WKNavigationDelegate` and forward them to the app, e.g. by calling `DeepLinkHandler.shared.handle(url:)` and returning `.cancel` for the navigation.
|
||||
|
||||
Safety:
|
||||
- Deep links (`clawdis://agent?...`) are always enabled.
|
||||
- Deep links (`clawdbot://agent?...`) are always enabled.
|
||||
- Without a `key` query param, the app will prompt for confirmation before invoking the agent.
|
||||
- With a valid `key`, the run is unattended (no prompt). For Canvas-originated actions, the app injects an internal key automatically.
|
||||
|
||||
@@ -149,7 +149,7 @@ Safety:
|
||||
|
||||
Recommended defaults:
|
||||
- `WKWebsiteDataStore.nonPersistent()` for Canvas (ephemeral).
|
||||
- Navigation policy: allow only `clawdis-canvas://…` (and optionally `about:blank`); open `http/https` externally.
|
||||
- Navigation policy: allow only `clawdbot-canvas://…` (and optionally `about:blank`); open `http/https` externally.
|
||||
- Scheme handler must prevent directory traversal: resolved file paths must stay under `<canvasRoot>/<session>/`.
|
||||
- Disable or tightly scope any JS bridge; prefer query-string/bootstrap config over `window.webkit.messageHandlers` for sensitive data.
|
||||
|
||||
@@ -157,5 +157,5 @@ Recommended defaults:
|
||||
|
||||
Suggested debugging hooks:
|
||||
- Enable Web Inspector for Canvas builds (same approach as WebChat).
|
||||
- Log scheme requests + resolution decisions to OSLog (subsystem `com.clawdis`, category `Canvas`).
|
||||
- Log scheme requests + resolution decisions to OSLog (subsystem `com.clawdbot`, category `Canvas`).
|
||||
- Provide a “copy canvas dir” action in debug settings to quickly reveal the session directory in Finder.
|
||||
|
||||
@@ -3,17 +3,17 @@ summary: "Running the gateway as a child process of the macOS app and why"
|
||||
read_when:
|
||||
- Integrating the mac app with the gateway lifecycle
|
||||
---
|
||||
# Clawdis gateway as a child process of the macOS app
|
||||
# Clawdbot gateway as a child process of the macOS app
|
||||
|
||||
Date: 2025-12-06 · Status: draft · Owner: steipete
|
||||
|
||||
Note (2025-12-19): the current implementation prefers a **launchd LaunchAgent** that runs the **bundled bun-compiled gateway**. This doc remains as an alternative mode for tighter coupling to the UI.
|
||||
|
||||
## Goal
|
||||
Run the Node-based Clawdis/clawdis gateway as a direct child of the LSUIElement app (instead of a launchd agent) while keeping all TCC-sensitive work inside the Swift app/broker layer and wiring the existing “Clawdis Active” toggle to start/stop the child.
|
||||
Run the Node-based Clawdbot/clawdbot gateway as a direct child of the LSUIElement app (instead of a launchd agent) while keeping all TCC-sensitive work inside the Swift app/broker layer and wiring the existing “Clawdbot Active” toggle to start/stop the child.
|
||||
|
||||
## When to prefer the child-process mode
|
||||
- You want gateway lifetime strictly coupled to the menu-bar app (dies when the app quits) and controlled by the “Clawdis Active” toggle without touching launchd.
|
||||
- You want gateway lifetime strictly coupled to the menu-bar app (dies when the app quits) and controlled by the “Clawdbot Active” toggle without touching launchd.
|
||||
- You’re okay giving up login persistence/auto-restart that launchd provides, or you’ll add your own backoff loop.
|
||||
- You want simpler log capture and supervision inside the app (no external plist or user-visible LaunchAgent).
|
||||
|
||||
@@ -34,11 +34,11 @@ Run the Node-based Clawdis/clawdis gateway as a direct child of the LSUIElement
|
||||
## Process manager design (Swift Subprocess)
|
||||
- Add a small `GatewayProcessManager` (Swift) that owns:
|
||||
- `execution: Execution?` from `Swift Subprocess` to track the child.
|
||||
- `start(config)` called when “Clawdis Active” flips ON:
|
||||
- binary: host Node running the bundled gateway under `Clawdis.app/Contents/Resources/Gateway/`
|
||||
- args: current clawdis entrypoint and flags
|
||||
- cwd/env: point to `~/.clawdis` as today; inject the expanded PATH so Homebrew Node resolves under launchd
|
||||
- output: stream stdout/stderr to `/tmp/clawdis-gateway.log` (cap buffer via Subprocess OutputLimits)
|
||||
- `start(config)` called when “Clawdbot Active” flips ON:
|
||||
- binary: host Node running the bundled gateway under `Clawdbot.app/Contents/Resources/Gateway/`
|
||||
- args: current clawdbot entrypoint and flags
|
||||
- cwd/env: point to `~/.clawdbot` as today; inject the expanded PATH so Homebrew Node resolves under launchd
|
||||
- output: stream stdout/stderr to `/tmp/clawdbot-gateway.log` (cap buffer via Subprocess OutputLimits)
|
||||
- restart: optional linear/backoff restart if exit was non-zero and Active is still true
|
||||
- `stop()` called when Active flips OFF or app terminates: cancel the execution and `waitUntilExit`.
|
||||
- Wire SwiftUI toggle:
|
||||
@@ -52,14 +52,14 @@ Run the Node-based Clawdis/clawdis gateway as a direct child of the LSUIElement
|
||||
- Host runtime should not call TCC APIs directly; keep privileged work inside the app/broker.
|
||||
|
||||
## Logging and observability
|
||||
- Stream child stdout/stderr to `/tmp/clawdis-gateway.log`; surface the last N lines in the Debug tab.
|
||||
- Stream child stdout/stderr to `/tmp/clawdbot-gateway.log`; surface the last N lines in the Debug tab.
|
||||
- Emit a user notification (via existing NotificationManager) on crash/exit while Active is true.
|
||||
- Add a lightweight heartbeat from Node → app (e.g., ping over stdout) so the app can show status in the menu.
|
||||
|
||||
## Failure/edge cases
|
||||
- App crash/quit kills the gateway. Decide if that is acceptable for the deployment tier; otherwise, stick with launchd for production and keep child-process for dev/experiments.
|
||||
- If the gateway exits repeatedly, back off (e.g., 1s/2s/5s/10s) and give up after N attempts with a menu warning.
|
||||
- Respect the existing pause semantics: when paused, the broker should return `ok=false, "clawdis paused"`; the gateway should avoid calling privileged routes while paused.
|
||||
- Respect the existing pause semantics: when paused, the broker should return `ok=false, "clawdbot paused"`; the gateway should avoid calling privileged routes while paused.
|
||||
|
||||
## Open questions / follow-ups
|
||||
- Do we need dual-mode (launchd for prod, child for dev)? If yes, gate via a setting or build flag.
|
||||
@@ -68,5 +68,5 @@ Run the Node-based Clawdis/clawdis gateway as a direct child of the LSUIElement
|
||||
|
||||
## Decision snapshot (current recommendation)
|
||||
- Keep all TCC surfaces in the Swift app/broker (node commands + PeekabooBridgeHost).
|
||||
- Implement `GatewayProcessManager` with Swift Subprocess to start/stop the gateway on the “Clawdis Active” toggle.
|
||||
- Implement `GatewayProcessManager` with Swift Subprocess to start/stop the gateway on the “Clawdbot Active” toggle.
|
||||
- Maintain the launchd path as a fallback for uptime/login persistence until child-mode proves stable.
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
---
|
||||
summary: "Setup guide for developers working on the Clawdis macOS app"
|
||||
summary: "Setup guide for developers working on the Clawdbot macOS app"
|
||||
read_when:
|
||||
- Setting up the macOS development environment
|
||||
---
|
||||
# macOS Developer Setup
|
||||
|
||||
This guide covers the necessary steps to build and run the Clawdis macOS application from source.
|
||||
This guide covers the necessary steps to build and run the Clawdbot macOS application from source.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
@@ -20,7 +20,7 @@ Before building the app, ensure you have the following installed:
|
||||
|
||||
## 1. Initialize Submodules
|
||||
|
||||
Clawdis depends on several submodules (like `Peekaboo`). You must initialize these recursively:
|
||||
Clawdbot depends on several submodules (like `Peekaboo`). You must initialize these recursively:
|
||||
|
||||
```bash
|
||||
git submodule update --init --recursive
|
||||
@@ -36,7 +36,7 @@ pnpm install
|
||||
|
||||
## 3. Build and Package the App
|
||||
|
||||
To build the macOS app and package it into `dist/Clawdis.app`, run:
|
||||
To build the macOS app and package it into `dist/Clawdbot.app`, run:
|
||||
|
||||
```bash
|
||||
./scripts/package-mac-app.sh
|
||||
@@ -48,16 +48,16 @@ If you don't have an Apple Developer ID certificate, the script will automatical
|
||||
|
||||
## 4. Install the CLI Helper
|
||||
|
||||
The macOS app requires a symlink named `clawdis` in `/usr/local/bin` or `/opt/homebrew/bin` to manage background tasks.
|
||||
The macOS app requires a symlink named `clawdbot` in `/usr/local/bin` or `/opt/homebrew/bin` to manage background tasks.
|
||||
|
||||
**To install it:**
|
||||
1. Open the Clawdis app.
|
||||
1. Open the Clawdbot app.
|
||||
2. Go to the **General** settings tab.
|
||||
3. Click **"Install CLI helper"** (requires administrator privileges).
|
||||
|
||||
Alternatively, you can manually link it from your Admin account:
|
||||
```bash
|
||||
sudo ln -sf "/Users/$(whoami)/clawdis/dist/Clawdis.app/Contents/Resources/Relay/clawdis" /usr/local/bin/clawdis
|
||||
sudo ln -sf "/Users/$(whoami)/clawdbot/dist/Clawdbot.app/Contents/Resources/Relay/clawdbot" /usr/local/bin/clawdbot
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
@@ -68,7 +68,7 @@ If the app crashes when you try to allow **Speech Recognition** or **Microphone*
|
||||
**Fix:**
|
||||
1. Reset the TCC permissions:
|
||||
```bash
|
||||
tccutil reset All com.clawdis.mac.debug
|
||||
tccutil reset All com.clawdbot.mac.debug
|
||||
```
|
||||
2. If that fails, change the `BUNDLE_ID` temporarily in `scripts/package-mac-app.sh` to force a "clean slate" from macOS.
|
||||
|
||||
@@ -78,4 +78,4 @@ If the gateway status stays on "Starting...", check if a zombie process is holdi
|
||||
```bash
|
||||
lsof -nP -i :18789
|
||||
```
|
||||
Kill any existing `node` or `clawdis` processes listening on that port and restart the app.
|
||||
Kill any existing `node` or `clawdbot` processes listening on that port and restart the app.
|
||||
|
||||
@@ -21,8 +21,8 @@ How to see whether the WhatsApp Web/Baileys bridge is healthy from the menu bar
|
||||
- **Connections tab** surfaces provider status + controls for WhatsApp/Telegram (login QR, logout, probe, last disconnect/error).
|
||||
|
||||
## How the probe works
|
||||
- App runs `clawdis health --json` via `ShellExecutor` every ~60s and on demand. The probe loads creds, attempts a short Baileys connect, and reports status without sending messages.
|
||||
- App runs `clawdbot health --json` via `ShellExecutor` every ~60s and on demand. The probe loads creds, attempts a short Baileys connect, and reports status without sending messages.
|
||||
- Cache the last good snapshot and the last error separately to avoid flicker; show the timestamp of each.
|
||||
|
||||
## When in doubt
|
||||
- You can still use the CLI flow in `docs/health.md` (`clawdis status`, `clawdis status --deep`, `clawdis health --json`) and tail `/tmp/clawdis/clawdis-*.log` for `web-heartbeat` / `web-reconnect`.
|
||||
- You can still use the CLI flow in `docs/health.md` (`clawdbot status`, `clawdbot status --deep`, `clawdbot health --json`) and tail `/tmp/clawdbot/clawdbot-*.log` for `web-heartbeat` / `web-reconnect`.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
summary: "Menu bar icon states and animations for Clawdis on macOS"
|
||||
summary: "Menu bar icon states and animations for Clawdbot on macOS"
|
||||
read_when:
|
||||
- Changing menu bar icon behavior
|
||||
---
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
summary: "Clawdis logging: rolling diagnostics file log + unified log privacy flags"
|
||||
summary: "Clawdbot logging: rolling diagnostics file log + unified log privacy flags"
|
||||
read_when:
|
||||
- Capturing macOS logs or investigating private data logging
|
||||
- Debugging voice wake/session lifecycle issues
|
||||
@@ -7,11 +7,11 @@ read_when:
|
||||
# Logging (macOS)
|
||||
|
||||
## Rolling diagnostics file log (Debug pane)
|
||||
Clawdis routes macOS app logs through swift-log (unified logging by default) and can write a local, rotating file log to disk when you need a durable capture.
|
||||
Clawdbot routes macOS app logs through swift-log (unified logging by default) and can write a local, rotating file log to disk when you need a durable capture.
|
||||
|
||||
- Verbosity: **Debug pane → Logs → App logging → Verbosity**
|
||||
- Enable: **Debug pane → Logs → App logging → “Write rolling diagnostics log (JSONL)”**
|
||||
- Location: `~/Library/Logs/Clawdis/diagnostics.jsonl` (rotates automatically; old files are suffixed with `.1`, `.2`, …)
|
||||
- Location: `~/Library/Logs/Clawdbot/diagnostics.jsonl` (rotates automatically; old files are suffixed with `.1`, `.2`, …)
|
||||
- Clear: **Debug pane → Logs → App logging → “Clear”**
|
||||
|
||||
Notes:
|
||||
@@ -22,11 +22,11 @@ Notes:
|
||||
|
||||
Unified logging redacts most payloads unless a subsystem opts into `privacy -off`. Per Peter's write-up on macOS [logging privacy shenanigans](https://steipete.me/posts/2025/logging-privacy-shenanigans) (2025) this is controlled by a plist in `/Library/Preferences/Logging/Subsystems/` keyed by the subsystem name. Only new log entries pick up the flag, so enable it before reproducing an issue.
|
||||
|
||||
## Enable for Clawdis (`com.clawdis`)
|
||||
## Enable for Clawdbot (`com.clawdbot`)
|
||||
- Write the plist to a temp file first, then install it atomically as root:
|
||||
|
||||
```bash
|
||||
cat <<'EOF' >/tmp/com.clawdis.plist
|
||||
cat <<'EOF' >/tmp/com.clawdbot.plist
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
@@ -39,13 +39,13 @@ cat <<'EOF' >/tmp/com.clawdis.plist
|
||||
</dict>
|
||||
</plist>
|
||||
EOF
|
||||
sudo install -m 644 -o root -g wheel /tmp/com.clawdis.plist /Library/Preferences/Logging/Subsystems/com.clawdis.plist
|
||||
sudo install -m 644 -o root -g wheel /tmp/com.clawdbot.plist /Library/Preferences/Logging/Subsystems/com.clawdbot.plist
|
||||
```
|
||||
|
||||
- No reboot is required; logd notices the file quickly, but only new log lines will include private payloads.
|
||||
- View the richer output with the existing helper, e.g. `./scripts/clawlog.sh --category WebChat --last 5m`.
|
||||
|
||||
## Disable after debugging
|
||||
- Remove the override: `sudo rm /Library/Preferences/Logging/Subsystems/com.clawdis.plist`.
|
||||
- Remove the override: `sudo rm /Library/Preferences/Logging/Subsystems/com.clawdbot.plist`.
|
||||
- Optionally run `sudo log config --reload` to force logd to drop the override immediately.
|
||||
- Remember this surface can include phone numbers and message bodies; keep the plist in place only while you actively need the extra detail.
|
||||
|
||||
@@ -39,7 +39,7 @@ read_when:
|
||||
|
||||
## Status row text (menu)
|
||||
- While work is active: `<Session role> · <activity label>`
|
||||
- Examples: `Main · bash: pnpm test`, `Other · read: apps/macos/Sources/Clawdis/AppState.swift`.
|
||||
- Examples: `Main · bash: pnpm test`, `Other · read: apps/macos/Sources/Clawdbot/AppState.swift`.
|
||||
- When idle: falls back to the health summary.
|
||||
|
||||
## Event ingestion
|
||||
|
||||
@@ -1,26 +1,26 @@
|
||||
---
|
||||
summary: "Plan for integrating Peekaboo automation into Clawdis via PeekabooBridge (socket-based TCC broker)"
|
||||
summary: "Plan for integrating Peekaboo automation into Clawdbot via PeekabooBridge (socket-based TCC broker)"
|
||||
read_when:
|
||||
- Hosting PeekabooBridge in Clawdis.app
|
||||
- Hosting PeekabooBridge in Clawdbot.app
|
||||
- Integrating Peekaboo as a submodule
|
||||
- Changing PeekabooBridge protocol/paths
|
||||
---
|
||||
# Peekaboo Bridge in Clawdis (macOS UI automation broker)
|
||||
# Peekaboo Bridge in Clawdbot (macOS UI automation broker)
|
||||
|
||||
## TL;DR
|
||||
- **Peekaboo removed its XPC helper** and now exposes privileged automation via a **UNIX domain socket bridge** (`PeekabooBridge` / `PeekabooBridgeHost`, socket name `bridge.sock`).
|
||||
- Clawdis integrates by **optionally hosting the same bridge** inside **Clawdis.app** (user-toggleable). The primary client is the **`peekaboo` CLI** (installed via npm); Clawdis does not need its own `ui …` CLI surface.
|
||||
- For **visualizations**, we keep them in **Peekaboo.app** (best UX); Clawdis stays a thin broker host. No visualizer toggle in Clawdis.
|
||||
- Clawdbot integrates by **optionally hosting the same bridge** inside **Clawdbot.app** (user-toggleable). The primary client is the **`peekaboo` CLI** (installed via npm); Clawdbot does not need its own `ui …` CLI surface.
|
||||
- For **visualizations**, we keep them in **Peekaboo.app** (best UX); Clawdbot stays a thin broker host. No visualizer toggle in Clawdbot.
|
||||
|
||||
Non-goals:
|
||||
- No auto-launching Peekaboo.app.
|
||||
- No onboarding deep links from the automation endpoint (Clawdis onboarding already handles permissions).
|
||||
- No AI provider/agent runtime dependencies in Clawdis (avoid pulling Tachikoma/MCP into the Clawdis app/CLI).
|
||||
- No onboarding deep links from the automation endpoint (Clawdbot onboarding already handles permissions).
|
||||
- No AI provider/agent runtime dependencies in Clawdbot (avoid pulling Tachikoma/MCP into the Clawdbot app/CLI).
|
||||
|
||||
## Big refactor (Dec 2025): XPC → Bridge
|
||||
Peekaboo’s privileged execution moved from “CLI → XPC helper” to “CLI → socket bridge host”. For Clawdis this is a win:
|
||||
Peekaboo’s privileged execution moved from “CLI → XPC helper” to “CLI → socket bridge host”. For Clawdbot this is a win:
|
||||
- It matches the existing “local socket + codesign checks” approach.
|
||||
- It lets us piggyback on **either** Peekaboo.app’s permissions **or** Clawdis.app’s permissions (whichever is running).
|
||||
- It lets us piggyback on **either** Peekaboo.app’s permissions **or** Clawdbot.app’s permissions (whichever is running).
|
||||
- It avoids “two apps with two TCC bubbles” unless needed.
|
||||
|
||||
Reference (Peekaboo submodule): `docs/bridge-host.md`.
|
||||
@@ -30,23 +30,23 @@ Reference (Peekaboo submodule): `docs/bridge-host.md`.
|
||||
- **Bridge hosts** (provide TCC-backed automation):
|
||||
- **Peekaboo.app** (preferred; also provides visualizations + controls)
|
||||
- **Claude.app** (secondary; lets `peekaboo` reuse Claude Desktop’s granted permissions)
|
||||
- **Clawdis.app** (secondary; “thin host” only)
|
||||
- **Clawdbot.app** (secondary; “thin host” only)
|
||||
- **Bridge clients** (trigger single actions):
|
||||
- `peekaboo …` (preferred; humans + agents)
|
||||
- Optional: Clawdis/Node shells out to `peekaboo` when it needs UI automation/capture
|
||||
- Optional: Clawdbot/Node shells out to `peekaboo` when it needs UI automation/capture
|
||||
|
||||
### Host discovery (client-side)
|
||||
Order is deliberate:
|
||||
1. Peekaboo.app host (full UX)
|
||||
2. Claude.app host (piggyback on Claude Desktop permissions)
|
||||
3. Clawdis.app host (piggyback on Clawdis permissions)
|
||||
3. Clawdbot.app host (piggyback on Clawdbot permissions)
|
||||
|
||||
Socket paths (convention; exact paths must match Peekaboo):
|
||||
- Peekaboo: `~/Library/Application Support/Peekaboo/bridge.sock`
|
||||
- Claude: `~/Library/Application Support/Claude/bridge.sock`
|
||||
- Clawdis: `~/Library/Application Support/clawdis/bridge.sock`
|
||||
- Clawdbot: `~/Library/Application Support/clawdbot/bridge.sock`
|
||||
|
||||
No auto-launch: if a host isn’t reachable, the command fails with a clear error (start Peekaboo.app, Claude.app, or Clawdis.app).
|
||||
No auto-launch: if a host isn’t reachable, the command fails with a clear error (start Peekaboo.app, Claude.app, or Clawdbot.app).
|
||||
|
||||
Override (debugging): set `PEEKABOO_BRIDGE_SOCKET=/path/to/bridge.sock`.
|
||||
|
||||
@@ -58,22 +58,22 @@ Override (debugging): set `PEEKABOO_BRIDGE_SOCKET=/path/to/bridge.sock`.
|
||||
## Dependency strategy (submodule)
|
||||
Integrate Peekaboo via git submodule (nested submodules are OK).
|
||||
|
||||
Path in Clawdis repo:
|
||||
Path in Clawdbot repo:
|
||||
- `./Peekaboo` (Swabble-style; keep stable so SwiftPM path deps don’t churn).
|
||||
|
||||
What Clawdis should use:
|
||||
What Clawdbot should use:
|
||||
- **Client side**: `PeekabooBridge` (socket client + protocol models).
|
||||
- **Host side (Clawdis.app)**: `PeekabooBridgeHost` + the minimal Peekaboo services needed to implement operations.
|
||||
- **Host side (Clawdbot.app)**: `PeekabooBridgeHost` + the minimal Peekaboo services needed to implement operations.
|
||||
|
||||
What Clawdis should *not* embed:
|
||||
What Clawdbot should *not* embed:
|
||||
- **Visualizer UI**: keep it in Peekaboo.app for now (toggle + controls live there).
|
||||
- **XPC**: don’t reintroduce helper targets; use the bridge.
|
||||
|
||||
## IPC / CLI surface
|
||||
### No `clawdis ui …`
|
||||
We avoid a parallel “Clawdis UI automation CLI”. Instead:
|
||||
### No `clawdbot ui …`
|
||||
We avoid a parallel “Clawdbot UI automation CLI”. Instead:
|
||||
- `peekaboo` is the user/agent-facing CLI surface for automation and capture.
|
||||
- Clawdis.app can host PeekabooBridge as a **thin TCC broker** so Peekaboo can piggyback on Clawdis permissions when Peekaboo.app isn’t running.
|
||||
- Clawdbot.app can host PeekabooBridge as a **thin TCC broker** so Peekaboo can piggyback on Clawdbot permissions when Peekaboo.app isn’t running.
|
||||
|
||||
### Diagnostics
|
||||
Use Peekaboo’s built-in diagnostics to see which host would be used:
|
||||
@@ -94,7 +94,7 @@ Standardize for the CLI (agent-friendly): **top-left origin per screen**.
|
||||
|
||||
Proposed request shape:
|
||||
- Requests accept `screenIndex` + `{x, y}` in that screen’s local coordinate space.
|
||||
- Clawdis.app converts to global CG coordinates using `NSScreen.screens[screenIndex].frame.origin`.
|
||||
- Clawdbot.app converts to global CG coordinates using `NSScreen.screens[screenIndex].frame.origin`.
|
||||
- Responses should echo both:
|
||||
- The resolved `screenIndex`
|
||||
- The local `{x, y}` and bounds
|
||||
@@ -136,15 +136,15 @@ Practical flow (agent-friendly):
|
||||
|
||||
## Visualizer integration
|
||||
Keep visualizations in **Peekaboo.app** for now.
|
||||
- Clawdis hosts the bridge, but does not render overlays.
|
||||
- Clawdbot hosts the bridge, but does not render overlays.
|
||||
- Any “visualizer enabled/disabled” setting is controlled in Peekaboo.app.
|
||||
|
||||
## Screenshots (legacy → Peekaboo takeover)
|
||||
Clawdis should not grow a separate screenshot CLI surface.
|
||||
Clawdbot should not grow a separate screenshot CLI surface.
|
||||
|
||||
Migration plan:
|
||||
- Use `peekaboo capture …` / `peekaboo see …` (returns a file path, default temp directory).
|
||||
- Once Clawdis’ legacy screenshot plumbing is replaced, remove it cleanly (no aliases).
|
||||
- Once Clawdbot’ legacy screenshot plumbing is replaced, remove it cleanly (no aliases).
|
||||
|
||||
## Permissions behavior
|
||||
If required permissions are missing:
|
||||
@@ -164,7 +164,7 @@ Debug-only escape hatch (development convenience):
|
||||
|
||||
## Next integration steps (after this doc)
|
||||
1. Add Peekaboo as a git submodule (nested submodules OK).
|
||||
2. Host `PeekabooBridgeHost` inside Clawdis.app behind a single setting (“Enable Peekaboo Bridge”, default on).
|
||||
3. Ensure Clawdis hosts the bridge at `~/Library/Application Support/clawdis/bridge.sock` and speaks the PeekabooBridge JSON protocol.
|
||||
4. Validate with `peekaboo bridge status --verbose` that Peekaboo can select Clawdis as the fallback host (no auto-launch).
|
||||
2. Host `PeekabooBridgeHost` inside Clawdbot.app behind a single setting (“Enable Peekaboo Bridge”, default on).
|
||||
3. Ensure Clawdbot hosts the bridge at `~/Library/Application Support/clawdbot/bridge.sock` and speaks the PeekabooBridge JSON protocol.
|
||||
4. Validate with `peekaboo bridge status --verbose` that Peekaboo can select Clawdbot as the fallback host (no auto-launch).
|
||||
5. Keep all protocol decisions aligned with Peekaboo (coordinate system, element IDs, snapshot scoping, error envelopes).
|
||||
|
||||
@@ -12,7 +12,7 @@ app's code signature, bundle identifier, and on-disk path. If any of those chang
|
||||
macOS treats the app as new and may drop or hide prompts.
|
||||
|
||||
## Requirements for stable permissions
|
||||
- Same path: run the app from a fixed location (for Clawdis, `dist/Clawdis.app`).
|
||||
- Same path: run the app from a fixed location (for Clawdbot, `dist/Clawdbot.app`).
|
||||
- Same bundle identifier: changing the bundle ID creates a new permission identity.
|
||||
- Signed app: unsigned or ad-hoc signed builds do not persist permissions.
|
||||
- Consistent signature: use a real Apple Development or Developer ID certificate
|
||||
@@ -31,8 +31,8 @@ grants, and prompts can disappear entirely until the stale entries are cleared.
|
||||
Example resets (replace bundle ID as needed):
|
||||
|
||||
```bash
|
||||
sudo tccutil reset Accessibility com.clawdis.mac
|
||||
sudo tccutil reset ScreenCapture com.clawdis.mac
|
||||
sudo tccutil reset Accessibility com.clawdbot.mac
|
||||
sudo tccutil reset ScreenCapture com.clawdbot.mac
|
||||
sudo tccutil reset AppleEvents
|
||||
```
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
---
|
||||
summary: "Clawdis macOS release checklist (Sparkle feed, packaging, signing)"
|
||||
summary: "Clawdbot macOS release checklist (Sparkle feed, packaging, signing)"
|
||||
read_when:
|
||||
- Cutting or validating a Clawdis macOS release
|
||||
- Cutting or validating a Clawdbot macOS release
|
||||
- Updating the Sparkle appcast or feed assets
|
||||
---
|
||||
|
||||
# Clawdis macOS release (Sparkle)
|
||||
# Clawdbot macOS release (Sparkle)
|
||||
|
||||
This app now ships Sparkle auto-updates. Release builds must be Developer ID–signed, zipped, and published with a signed appcast entry.
|
||||
|
||||
@@ -13,10 +13,10 @@ This app now ships Sparkle auto-updates. Release builds must be Developer ID–s
|
||||
- Developer ID Application cert installed (`Developer ID Application: Peter Steinberger (Y5PE65HELJ)` is expected).
|
||||
- Sparkle private key path set in the environment as `SPARKLE_PRIVATE_KEY_FILE`; key lives in `/Users/steipete/Library/CloudStorage/Dropbox/Backup/Sparkle` (same key as Trimmy; public key baked into Info.plist).
|
||||
- Notary credentials (keychain profile or API key) for `xcrun notarytool` if you want Gatekeeper-safe DMG/zip distribution.
|
||||
- We use a Keychain profile named `clawdis-notary`, created from App Store Connect API key env vars in your shell profile:
|
||||
- We use a Keychain profile named `clawdbot-notary`, created from App Store Connect API key env vars in your shell profile:
|
||||
- `APP_STORE_CONNECT_API_KEY_P8`, `APP_STORE_CONNECT_KEY_ID`, `APP_STORE_CONNECT_ISSUER_ID`
|
||||
- `echo "$APP_STORE_CONNECT_API_KEY_P8" | sed 's/\\n/\n/g' > /tmp/clawdis-notary.p8`
|
||||
- `xcrun notarytool store-credentials "clawdis-notary" --key /tmp/clawdis-notary.p8 --key-id "$APP_STORE_CONNECT_KEY_ID" --issuer "$APP_STORE_CONNECT_ISSUER_ID"`
|
||||
- `echo "$APP_STORE_CONNECT_API_KEY_P8" | sed 's/\\n/\n/g' > /tmp/clawdbot-notary.p8`
|
||||
- `xcrun notarytool store-credentials "clawdbot-notary" --key /tmp/clawdbot-notary.p8 --key-id "$APP_STORE_CONNECT_KEY_ID" --issuer "$APP_STORE_CONNECT_ISSUER_ID"`
|
||||
- `pnpm` deps installed (`pnpm install --config.node-linker=hoisted`).
|
||||
- Sparkle tools are fetched automatically via SwiftPM at `apps/macos/.build/artifacts/sparkle/Sparkle/bin/` (`sign_update`, `generate_appcast`, etc.).
|
||||
|
||||
@@ -28,7 +28,7 @@ Notes:
|
||||
```bash
|
||||
# From repo root; set release IDs so Sparkle feed is enabled.
|
||||
# APP_BUILD must be numeric + monotonic for Sparkle compare.
|
||||
BUNDLE_ID=com.clawdis.mac \
|
||||
BUNDLE_ID=com.clawdbot.mac \
|
||||
APP_VERSION=0.1.0 \
|
||||
APP_BUILD="$(git rev-list --count HEAD)" \
|
||||
BUILD_CONFIG=release \
|
||||
@@ -36,17 +36,17 @@ SIGN_IDENTITY="Developer ID Application: Peter Steinberger (Y5PE65HELJ)" \
|
||||
scripts/package-mac-app.sh
|
||||
|
||||
# Zip for distribution (includes resource forks for Sparkle delta support)
|
||||
ditto -c -k --sequesterRsrc --keepParent dist/Clawdis.app dist/Clawdis-0.1.0.zip
|
||||
ditto -c -k --sequesterRsrc --keepParent dist/Clawdbot.app dist/Clawdbot-0.1.0.zip
|
||||
|
||||
# Optional: also build a styled DMG for humans (drag to /Applications)
|
||||
scripts/create-dmg.sh dist/Clawdis.app dist/Clawdis-0.1.0.dmg
|
||||
scripts/create-dmg.sh dist/Clawdbot.app dist/Clawdbot-0.1.0.dmg
|
||||
|
||||
# Recommended: build + notarize/staple zip + DMG
|
||||
# First, create a keychain profile once:
|
||||
# xcrun notarytool store-credentials "clawdis-notary" \
|
||||
# xcrun notarytool store-credentials "clawdbot-notary" \
|
||||
# --apple-id "<apple-id>" --team-id "<team-id>" --password "<app-specific-password>"
|
||||
NOTARIZE=1 NOTARYTOOL_PROFILE=clawdis-notary \
|
||||
BUNDLE_ID=com.clawdis.mac \
|
||||
NOTARIZE=1 NOTARYTOOL_PROFILE=clawdbot-notary \
|
||||
BUNDLE_ID=com.clawdbot.mac \
|
||||
APP_VERSION=0.1.0 \
|
||||
APP_BUILD="$(git rev-list --count HEAD)" \
|
||||
BUILD_CONFIG=release \
|
||||
@@ -54,22 +54,22 @@ SIGN_IDENTITY="Developer ID Application: Peter Steinberger (Y5PE65HELJ)" \
|
||||
scripts/package-mac-dist.sh
|
||||
|
||||
# Optional: ship dSYM alongside the release
|
||||
ditto -c -k --keepParent apps/macos/.build/release/Clawdis.app.dSYM dist/Clawdis-0.1.0.dSYM.zip
|
||||
ditto -c -k --keepParent apps/macos/.build/release/Clawdbot.app.dSYM dist/Clawdbot-0.1.0.dSYM.zip
|
||||
```
|
||||
|
||||
## Appcast entry
|
||||
Use the release note generator so Sparkle renders formatted HTML notes:
|
||||
```bash
|
||||
SPARKLE_PRIVATE_KEY_FILE=/Users/steipete/Library/CloudStorage/Dropbox/Backup/Sparkle/ed25519-private-key scripts/make_appcast.sh dist/Clawdis-0.1.0.zip https://raw.githubusercontent.com/steipete/clawdis/main/appcast.xml
|
||||
SPARKLE_PRIVATE_KEY_FILE=/Users/steipete/Library/CloudStorage/Dropbox/Backup/Sparkle/ed25519-private-key scripts/make_appcast.sh dist/Clawdbot-0.1.0.zip https://raw.githubusercontent.com/clawdbot/clawdbot/main/appcast.xml
|
||||
```
|
||||
Generates HTML release notes from `CHANGELOG.md` (via `scripts/changelog-to-html.sh`) and embeds them in the appcast entry.
|
||||
Commit the updated `appcast.xml` alongside the release assets (zip + dSYM) when publishing.
|
||||
|
||||
## Publish & verify
|
||||
- Upload `Clawdis-0.1.0.zip` (and `Clawdis-0.1.0.dSYM.zip`) to the GitHub release for tag `v0.1.0`.
|
||||
- Ensure the raw appcast URL matches the baked feed: `https://raw.githubusercontent.com/steipete/clawdis/main/appcast.xml`.
|
||||
- Upload `Clawdbot-0.1.0.zip` (and `Clawdbot-0.1.0.dSYM.zip`) to the GitHub release for tag `v0.1.0`.
|
||||
- Ensure the raw appcast URL matches the baked feed: `https://raw.githubusercontent.com/clawdbot/clawdbot/main/appcast.xml`.
|
||||
- Sanity checks:
|
||||
- `curl -I https://raw.githubusercontent.com/steipete/clawdis/main/appcast.xml` returns 200.
|
||||
- `curl -I https://raw.githubusercontent.com/clawdbot/clawdbot/main/appcast.xml` returns 200.
|
||||
- `curl -I <enclosure url>` returns 200 after assets upload.
|
||||
- On a previous public build, run “Check for Updates…” from the About tab and verify Sparkle installs the new build cleanly.
|
||||
|
||||
|
||||
@@ -1,32 +1,32 @@
|
||||
---
|
||||
summary: "macOS app flow for controlling a remote Clawdis gateway over SSH"
|
||||
summary: "macOS app flow for controlling a remote Clawdbot gateway over SSH"
|
||||
read_when:
|
||||
- Setting up or debugging remote mac control
|
||||
---
|
||||
# Remote Clawdis (macOS ⇄ remote host)
|
||||
# Remote Clawdbot (macOS ⇄ remote host)
|
||||
|
||||
Updated: 2025-12-08
|
||||
|
||||
This flow lets the macOS app act as a full remote control for a Clawdis gateway running on another host (e.g. a Mac Studio). All features—health checks, Voice Wake forwarding, and Web Chat—reuse the same remote SSH configuration from *Settings → General*.
|
||||
This flow lets the macOS app act as a full remote control for a Clawdbot gateway running on another host (e.g. a Mac Studio). All features—health checks, Voice Wake forwarding, and Web Chat—reuse the same remote SSH configuration from *Settings → General*.
|
||||
|
||||
## Modes
|
||||
- **Local (this Mac)**: Everything runs on the laptop. No SSH involved.
|
||||
- **Remote over SSH**: Clawdis commands are executed on the remote host. The mac app opens an SSH connection with `-o BatchMode` plus your chosen identity/key.
|
||||
- **Remote over SSH**: Clawdbot commands are executed on the remote host. The mac app opens an SSH connection with `-o BatchMode` plus your chosen identity/key.
|
||||
|
||||
## Prereqs on the remote host
|
||||
1) Install Node + pnpm and build/install the Clawdis CLI (`pnpm install && pnpm build && pnpm link --global`).
|
||||
2) Ensure `clawdis` is on PATH for non-interactive shells (symlink into `/usr/local/bin` or `/opt/homebrew/bin` if needed).
|
||||
1) Install Node + pnpm and build/install the Clawdbot CLI (`pnpm install && pnpm build && pnpm link --global`).
|
||||
2) Ensure `clawdbot` is on PATH for non-interactive shells (symlink into `/usr/local/bin` or `/opt/homebrew/bin` if needed).
|
||||
3) Open SSH with key auth. We recommend **Tailscale** IPs for stable reachability off-LAN.
|
||||
|
||||
## macOS app setup
|
||||
1) Open *Settings → General*.
|
||||
2) Under **Clawdis runs**, pick **Remote over SSH** and set:
|
||||
2) Under **Clawdbot runs**, pick **Remote over SSH** and set:
|
||||
- **SSH target**: `user@host` (optional `:port`).
|
||||
- If the gateway is on the same LAN and advertises Bonjour, pick it from the discovered list to auto-fill this field.
|
||||
- **Identity file** (advanced): path to your key.
|
||||
- **Project root** (advanced): remote checkout path used for commands.
|
||||
- **CLI path** (advanced): optional path to a runnable `clawdis` entrypoint/binary (auto-filled when advertised).
|
||||
3) Hit **Test remote**. Success indicates the remote `clawdis status --json` runs correctly. Failures usually mean PATH/CLI issues; exit 127 means the CLI isn’t found remotely.
|
||||
- **CLI path** (advanced): optional path to a runnable `clawdbot` entrypoint/binary (auto-filled when advertised).
|
||||
3) Hit **Test remote**. Success indicates the remote `clawdbot status --json` runs correctly. Failures usually mean PATH/CLI issues; exit 127 means the CLI isn’t found remotely.
|
||||
4) Health checks and Web Chat will now run through this SSH tunnel automatically.
|
||||
|
||||
## Web Chat over SSH
|
||||
@@ -38,20 +38,20 @@ This flow lets the macOS app act as a full remote control for a Clawdis gateway
|
||||
- Nodes advertise their permission state via `node.list` / `node.describe` so agents know what’s available.
|
||||
|
||||
## WhatsApp login flow (remote)
|
||||
- Run `clawdis login --verbose` **on the remote host**. Scan the QR with WhatsApp on your phone.
|
||||
- Run `clawdbot login --verbose` **on the remote host**. Scan the QR with WhatsApp on your phone.
|
||||
- Re-run login on that host if auth expires. Health check will surface link problems.
|
||||
|
||||
## Troubleshooting
|
||||
- **exit 127 / not found**: `clawdis` isn’t on PATH for non-login shells. Add it to `/etc/paths`, your shell rc, or symlink into `/usr/local/bin`/`/opt/homebrew/bin`.
|
||||
- **Health probe failed**: check SSH reachability, PATH, and that Baileys is logged in (`clawdis status --json`).
|
||||
- **exit 127 / not found**: `clawdbot` isn’t on PATH for non-login shells. Add it to `/etc/paths`, your shell rc, or symlink into `/usr/local/bin`/`/opt/homebrew/bin`.
|
||||
- **Health probe failed**: check SSH reachability, PATH, and that Baileys is logged in (`clawdbot status --json`).
|
||||
- **Web Chat stuck**: confirm the gateway is running on the remote host and the forwarded port matches the gateway WS port; the UI requires a healthy WS connection.
|
||||
- **Voice Wake**: trigger phrases are forwarded automatically in remote mode; no separate forwarder is needed.
|
||||
|
||||
## Notification sounds
|
||||
Pick sounds per notification from scripts with `clawdis` and `node.invoke`, e.g.:
|
||||
Pick sounds per notification from scripts with `clawdbot` and `node.invoke`, e.g.:
|
||||
|
||||
```bash
|
||||
clawdis nodes notify --node <id> --title "Ping" --body "Remote gateway ready" --sound Glass
|
||||
clawdbot nodes notify --node <id> --title "Ping" --body "Remote gateway ready" --sound Glass
|
||||
```
|
||||
|
||||
There is no global “default sound” toggle in the app anymore; callers choose a sound (or none) per request.
|
||||
|
||||
@@ -7,11 +7,11 @@ read_when:
|
||||
|
||||
This app is usually built from `scripts/package-mac-app.sh`, which now:
|
||||
|
||||
- sets a stable debug bundle identifier: `com.clawdis.mac.debug`
|
||||
- sets a stable debug bundle identifier: `com.clawdbot.mac.debug`
|
||||
- writes the Info.plist with that bundle id (override via `BUNDLE_ID=...`)
|
||||
- calls `scripts/codesign-mac-app.sh` to sign the main binary, bundled CLI, and app bundle so macOS treats each rebuild as the same signed bundle and keeps TCC permissions (notifications, accessibility, screen recording, mic, speech). For stable permissions, use a real signing identity; ad-hoc is opt-in and fragile (see `docs/mac/permissions.md`).
|
||||
- uses `CODESIGN_TIMESTAMP=auto` by default; it enables trusted timestamps for Developer ID signatures. Set `CODESIGN_TIMESTAMP=off` to skip timestamping (offline debug builds).
|
||||
- inject build metadata into Info.plist: `ClawdisBuildTimestamp` (UTC) and `ClawdisGitCommit` (short hash) so the About pane can show build, git, and debug/release channel.
|
||||
- inject build metadata into Info.plist: `ClawdbotBuildTimestamp` (UTC) and `ClawdbotGitCommit` (short hash) so the About pane can show build, git, and debug/release channel.
|
||||
- **Packaging requires Bun**: The embedded gateway relay is compiled using `bun`. Ensure it is installed (`curl -fsSL https://bun.sh/install | bash`).
|
||||
- reads `SIGN_IDENTITY` from the environment. Add `export SIGN_IDENTITY="Apple Development: Your Name (TEAMID)"` (or your Developer ID Application cert) to your shell rc to always sign with your cert. Ad-hoc signing requires explicit opt-in via `ALLOW_ADHOC_SIGNING=1` or `SIGN_IDENTITY="-"` (not recommended for permission testing).
|
||||
|
||||
@@ -31,11 +31,11 @@ When signing with `SIGN_IDENTITY="-"` (ad-hoc), the script automatically disable
|
||||
## Build metadata for About
|
||||
|
||||
`package-mac-app.sh` stamps the bundle with:
|
||||
- `ClawdisBuildTimestamp`: ISO8601 UTC at package time
|
||||
- `ClawdisGitCommit`: short git hash (or `unknown` if unavailable)
|
||||
- `ClawdbotBuildTimestamp`: ISO8601 UTC at package time
|
||||
- `ClawdbotGitCommit`: short git hash (or `unknown` if unavailable)
|
||||
|
||||
The About tab reads these keys to show version, build date, git commit, and whether it’s a debug build (via `#if DEBUG`). Run the packager to refresh these values after code changes.
|
||||
|
||||
## Why
|
||||
|
||||
TCC permissions are tied to the bundle identifier *and* code signature. Unsigned debug builds with changing UUIDs were causing macOS to forget grants after each rebuild. Signing the binaries (ad‑hoc by default) and keeping a fixed bundle id/path (`dist/Clawdis.app`) preserves the grants between builds, matching the VibeTunnel approach.
|
||||
TCC permissions are tied to the bundle identifier *and* code signature. Unsigned debug builds with changing UUIDs were causing macOS to forget grants after each rebuild. Signing the binaries (ad‑hoc by default) and keeping a fixed bundle id/path (`dist/Clawdbot.app`) preserves the grants between builds, matching the VibeTunnel approach.
|
||||
|
||||
@@ -6,21 +6,21 @@ read_when:
|
||||
---
|
||||
# Skills (macOS)
|
||||
|
||||
The macOS app surfaces Clawdis skills via the gateway; it does not parse skills locally.
|
||||
The macOS app surfaces Clawdbot skills via the gateway; it does not parse skills locally.
|
||||
|
||||
## Data source
|
||||
- `skills.status` (gateway) returns all skills plus eligibility and missing requirements
|
||||
(including allowlist blocks for bundled skills).
|
||||
- Requirements are derived from `metadata.clawdis.requires` in each `SKILL.md`.
|
||||
- Requirements are derived from `metadata.clawdbot.requires` in each `SKILL.md`.
|
||||
|
||||
## Install actions
|
||||
- `metadata.clawdis.install` defines install options (brew/node/go/uv).
|
||||
- `metadata.clawdbot.install` defines install options (brew/node/go/uv).
|
||||
- The app calls `skills.install` to run installers on the gateway host.
|
||||
- The gateway surfaces only one preferred installer when multiple are provided
|
||||
(brew when available, otherwise node manager from `skills.install`, default npm).
|
||||
|
||||
## Env/API keys
|
||||
- The app stores keys in `~/.clawdis/clawdis.json` under `skills.entries.<skillKey>`.
|
||||
- The app stores keys in `~/.clawdbot/clawdbot.json` under `skills.entries.<skillKey>`.
|
||||
- `skills.update` patches `enabled`, `apiKey`, and `env`.
|
||||
|
||||
## Remote mode
|
||||
|
||||
@@ -32,14 +32,14 @@ Audience: macOS app contributors. Goal: keep the voice overlay predictable when
|
||||
- Push-to-talk: no delay; wake-word: optional delay for auto-send.
|
||||
- Apply a short cooldown to the wake runtime after push-to-talk finishes so wake-word doesn’t immediately retrigger.
|
||||
5. **Logging**
|
||||
- Coordinator emits `.info` logs in subsystem `com.clawdis`, categories `voicewake.overlay` and `voicewake.chime`.
|
||||
- Coordinator emits `.info` logs in subsystem `com.clawdbot`, categories `voicewake.overlay` and `voicewake.chime`.
|
||||
- Key events: `session_started`, `adopted_by_push_to_talk`, `partial`, `finalized`, `send`, `dismiss`, `cancel`, `cooldown`.
|
||||
|
||||
### Debugging checklist
|
||||
- Stream logs while reproducing a sticky overlay:
|
||||
|
||||
```bash
|
||||
sudo log stream --predicate 'subsystem == "com.clawdis" AND category CONTAINS "voicewake"' --level info --style compact
|
||||
sudo log stream --predicate 'subsystem == "com.clawdbot" AND category CONTAINS "voicewake"' --level info --style compact
|
||||
```
|
||||
- Verify only one active session token; stale callbacks should be dropped by the coordinator.
|
||||
- Ensure push-to-talk release always calls `endCapture` with the active token; if text is empty, expect `dismiss` without chime or send.
|
||||
|
||||
@@ -12,11 +12,11 @@ The macOS menu bar app shows the WebChat UI as a native SwiftUI view and reuses
|
||||
|
||||
## Launch & debugging
|
||||
- Manual: Lobster menu → “Open Chat”.
|
||||
- Auto-open for testing: run `dist/Clawdis.app/Contents/MacOS/Clawdis --webchat` (or pass `--webchat` to the binary launched by launchd). The window opens on startup.
|
||||
- Logs: see `./scripts/clawlog.sh` (subsystem `com.clawdis`, category `WebChatSwiftUI`).
|
||||
- Auto-open for testing: run `dist/Clawdbot.app/Contents/MacOS/Clawdbot --webchat` (or pass `--webchat` to the binary launched by launchd). The window opens on startup.
|
||||
- Logs: see `./scripts/clawlog.sh` (subsystem `com.clawdbot`, category `WebChatSwiftUI`).
|
||||
|
||||
## How it’s wired
|
||||
- Implementation: `apps/macos/Sources/Clawdis/WebChatSwiftUI.swift` hosts `ClawdisChatUI` and speaks to the Gateway over `GatewayConnection`.
|
||||
- Implementation: `apps/macos/Sources/Clawdbot/WebChatSwiftUI.swift` hosts `ClawdbotChatUI` and speaks to the Gateway over `GatewayConnection`.
|
||||
- Data plane: Gateway WebSocket methods `chat.history`, `chat.send`, `chat.abort`; events `chat`, `agent`, `presence`, `tick`, `health`.
|
||||
- Session: usually primary (`main`); multiple transports (WhatsApp/Telegram/Discord/Desktop) share the same key. The onboarding flow uses a dedicated `onboarding` session to keep first-run setup separate.
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
---
|
||||
summary: "macOS IPC architecture for Clawdis app, gateway node bridge, and PeekabooBridge"
|
||||
summary: "macOS IPC architecture for Clawdbot app, gateway node bridge, and PeekabooBridge"
|
||||
read_when:
|
||||
- Editing IPC contracts or menu bar app IPC
|
||||
---
|
||||
# Clawdis macOS IPC architecture (Dec 2025)
|
||||
# Clawdbot macOS IPC architecture (Dec 2025)
|
||||
|
||||
**Current model:** there is **no local control socket** and no `clawdis-mac` CLI. All agent actions go through the Gateway WebSocket and `node.invoke`. UI automation still uses PeekabooBridge.
|
||||
**Current model:** there is **no local control socket** and no `clawdbot-mac` CLI. All agent actions go through the Gateway WebSocket and `node.invoke`. UI automation still uses PeekabooBridge.
|
||||
|
||||
## Goals
|
||||
- Single GUI app instance that owns all TCC-facing work (notifications, screen recording, mic, speech, AppleScript).
|
||||
@@ -19,9 +19,9 @@ read_when:
|
||||
|
||||
### PeekabooBridge (UI automation)
|
||||
- UI automation uses a separate UNIX socket named `bridge.sock` and the PeekabooBridge JSON protocol.
|
||||
- Host preference order (client-side): Peekaboo.app → Claude.app → Clawdis.app → local execution.
|
||||
- Host preference order (client-side): Peekaboo.app → Claude.app → Clawdbot.app → local execution.
|
||||
- Security: bridge hosts require TeamID `Y5PE65HELJ`; DEBUG-only same-UID escape hatch is guarded by `PEEKABOO_ALLOW_UNSIGNED_SOCKET_CLIENTS=1` (Peekaboo convention).
|
||||
- See: `docs/mac/peekaboo.md` for the Clawdis plan and naming.
|
||||
- See: `docs/mac/peekaboo.md` for the Clawdbot plan and naming.
|
||||
|
||||
### Mach/XPC (future direction)
|
||||
- Still optional for internal app services, but **not required** for automation now that node.invoke is the surface.
|
||||
|
||||
Reference in New Issue
Block a user