feat(macos): prompt for CLI install

This commit is contained in:
Peter Steinberger
2026-01-11 10:15:37 +00:00
parent 7551415db9
commit 6d2928888c
25 changed files with 204 additions and 602 deletions

View File

@@ -339,8 +339,12 @@ sleep 1
kill -9 <PID> # last resort
```
**Fix 3: Check embedded gateway**
Ensure the gateway relay was properly bundled. Run [`./scripts/package-mac-app.sh`](https://github.com/clawdbot/clawdbot/blob/main/scripts/package-mac-app.sh) and ensure Node is available (the script downloads a bundled runtime by default).
**Fix 3: Check the CLI install**
Ensure the global `clawdbot` CLI is installed and matches the app version:
```bash
clawdbot --version
npm install -g clawdbot@<version>
```
## Debug Mode

View File

@@ -1,118 +1,63 @@
---
summary: "Bundled gateway runtime: packaging, launchd, signing, and bundling"
summary: "Gateway runtime on macOS (external launchd service)"
read_when:
- Packaging Clawdbot.app
- Debugging the bundled gateway binary
- Changing relay bundling flags or codesigning
- Debugging the macOS gateway launchd service
- Installing the gateway CLI for macOS
---
# Bundled Gateway (macOS)
# Gateway on macOS (external launchd)
Goal: ship **Clawdbot.app** with a self-contained relay that can run the CLI and
Gateway daemon. No global `npm install -g clawdbot`, no system Node requirement.
Clawdbot.app no longer bundles Node/Bun or the Gateway runtime. The macOS app
expects an **external** `clawdbot` CLI install and manages a peruser launchd
service to keep the Gateway running.
## What gets bundled
## Install the CLI (required for local mode)
App bundle layout:
You need Node 22+ on the Mac, then install `clawdbot` globally:
- `Clawdbot.app/Contents/Resources/Relay/node`
- Node runtime binary (downloaded during packaging, stripped for size)
- `Clawdbot.app/Contents/Resources/Relay/dist/`
- Compiled CLI/gateway payload from `pnpm exec tsc`
- `Clawdbot.app/Contents/Resources/Relay/node_modules/`
- Production dependencies staged via `pnpm deploy --prod --legacy` (includes optional native addons)
- `Clawdbot.app/Contents/Resources/Relay/clawdbot`
- Wrapper script that execs the bundled Node + dist entrypoint
- `Clawdbot.app/Contents/Resources/Relay/package.json`
- tiny “Pi runtime compatibility” file (see below, includes `"type": "module"`)
- `Clawdbot.app/Contents/Resources/Relay/skills/`
- Bundled skills payload (required for Pi tools)
- `Clawdbot.app/Contents/Resources/Relay/theme/`
- Pi TUI theme payload (optional, but strongly recommended)
- `Clawdbot.app/Contents/Resources/Relay/a2ui/`
- A2UI host assets (served by the gateway)
- `Clawdbot.app/Contents/Resources/Relay/control-ui/`
- Control UI build output (served by the gateway)
```bash
npm install -g clawdbot@<version>
```
Why the sidecar files matter:
- The embedded Pi runtime detects “bundled relay mode” and then looks for
`package.json` + `theme/` **next to `process.execPath`** (i.e. next to
`node`). Keep the sidecar files.
## Build pipeline
Packaging script:
- [`scripts/package-mac-app.sh`](https://github.com/clawdbot/clawdbot/blob/main/scripts/package-mac-app.sh)
It builds:
- TS: `pnpm exec tsc`
- Swift app + helper: `swift build …`
- Relay payload: `pnpm deploy --prod --legacy` + copy `dist/`
- Node runtime: downloads the latest Node release (override via `NODE_VERSION`)
Important knobs:
- `NODE_VERSION=22.12.0` → pin a specific Node version
- `NODE_DIST_MIRROR=…` → mirror for downloads (default: nodejs.org)
- `STRIP_NODE=0` → keep symbols (default strips to reduce size)
- `BUNDLED_RUNTIME=bun` → switch the relay build back to Bun (`bun --compile`)
Version injection:
- The relay wrapper exports `CLAWDBOT_BUNDLED_VERSION` so `--version` works
without reading `package.json` at runtime.
The macOS apps **Install CLI** button runs the same flow via npm/pnpm/bun.
## Launchd (Gateway as LaunchAgent)
Label:
- `com.clawdbot.gateway` (or `com.clawdbot.<profile>`)
Plist location (per-user):
- `~/Library/LaunchAgents/com.clawdbot.gateway.plist` (or `.../com.clawdbot.<profile>.plist`)
Plist location (peruser):
- `~/Library/LaunchAgents/com.clawdbot.gateway.plist`
Manager:
- The macOS app owns LaunchAgent install/update for the bundled gateway.
- The macOS app owns LaunchAgent install/update in Local mode.
- The CLI can also install it: `clawdbot daemon install`.
Behavior:
- “Clawdbot Active” enables/disables the LaunchAgent.
- App quit does **not** stop the gateway (launchd keeps it alive).
- CLI install (`clawdbot daemon install`) writes the same LaunchAgent; `--force` rewrites it.
Logging:
- launchd stdout/err: `/tmp/clawdbot/clawdbot-gateway.log`
Default LaunchAgent env:
- `CLAWDBOT_IMAGE_BACKEND=sips` (avoid sharp native addon inside the bundle)
## Version compatibility
## Codesigning (hardened runtime + Node)
The macOS app checks the gateway version against its own version. If theyre
incompatible, update the global CLI to match the app version.
Node uses JIT. The bundled runtime is signed with:
- `com.apple.security.cs.allow-jit`
- `com.apple.security.cs.allow-unsigned-executable-memory`
This is applied by `scripts/codesign-mac-app.sh`.
Note: because the relay runs under hardened runtime, any bundled `*.node` native
addons must be signed with the same Team ID as the relay `node` binary.
`scripts/codesign-mac-app.sh` re-signs `Contents/Resources/Relay/**/*.node` for this.
## Image processing
To avoid shipping native `sharp` addons inside the bundle, the gateway defaults
to `/usr/bin/sips` for image ops when run from the app (via launchd env + wrapper).
## Tests / smoke checks
From a packaged app (local build):
## Smoke check
```bash
dist/Clawdbot.app/Contents/Resources/Relay/clawdbot --version
clawdbot --version
CLAWDBOT_SKIP_PROVIDERS=1 \
CLAWDBOT_SKIP_CANVAS_HOST=1 \
dist/Clawdbot.app/Contents/Resources/Relay/clawdbot gateway --port 18999 --bind loopback
clawdbot gateway --port 18999 --bind loopback
```
Then, in another shell:
Then:
```bash
pnpm -s clawdbot gateway call health --url ws://127.0.0.1:18999 --timeout 3000
clawdbot gateway call health --url ws://127.0.0.1:18999 --timeout 3000
```

View File

@@ -5,8 +5,9 @@ read_when:
---
# Gateway lifecycle on macOS
The macOS app **manages the Gateway via launchd** by default. This gives you
reliable autostart at login and restart on crashes.
The macOS app **manages the Gateway via launchd** by default. The launchd job
uses the external `clawdbot` CLI (no embedded runtime). This gives you reliable
autostart at login and restart on crashes.
Childprocess mode (Gateway spawned directly by the app) is **not in use** today.
If you need tighter coupling to the UI, use **Attachonly** and run the Gateway

View File

@@ -12,8 +12,7 @@ This guide covers the necessary steps to build and run the Clawdbot macOS applic
Before building the app, ensure you have the following installed:
1. **Xcode 26.2+**: Required for Swift development.
2. **Node.js & pnpm**: Required for the gateway and CLI components.
3. **Node**: Required to package the embedded gateway relay (the script can download a bundled runtime).
2. **Node.js 22+ & pnpm**: Required for the gateway, CLI, and packaging scripts.
## 1. Initialize Submodules
@@ -39,24 +38,22 @@ To build the macOS app and package it into `dist/Clawdbot.app`, run:
./scripts/package-mac-app.sh
```
Use `BUNDLED_RUNTIME=node|bun` to switch the embedded gateway runtime (default: node).
If you don't have an Apple Developer ID certificate, the script will automatically use **ad-hoc signing** (`-`).
> **Note**: Ad-hoc signed apps may trigger security prompts. If the app crashes immediately with "Abort trap 6", see the [Troubleshooting](#troubleshooting) section.
## 4. Install the CLI Helper
## 4. Install the CLI
The macOS app requires a symlink named `clawdbot` in `/usr/local/bin` or `/opt/homebrew/bin` to manage background tasks.
The macOS app expects a global `clawdbot` CLI install to manage background tasks.
**To install it:**
**To install it (recommended):**
1. Open the Clawdbot app.
2. Go to the **General** settings tab.
3. Click **"Install CLI helper"** (requires administrator privileges).
3. Click **"Install CLI"**.
Alternatively, you can manually link it from your Admin account:
Alternatively, install it manually:
```bash
sudo ln -sf "/Users/$(whoami)/Projects/clawdbot/dist/Clawdbot.app/Contents/Resources/Relay/clawdbot" /usr/local/bin/clawdbot
npm install -g clawdbot@<version>
```
## Troubleshooting

View File

@@ -9,10 +9,10 @@ This app is usually built from [`scripts/package-mac-app.sh`](https://github.com
- 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`](https://github.com/clawdbot/clawdbot/blob/main/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 [macOS permissions](/platforms/mac/permissions)).
- calls [`scripts/codesign-mac-app.sh`](https://github.com/clawdbot/clawdbot/blob/main/scripts/codesign-mac-app.sh) to sign the main binary 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 [macOS permissions](/platforms/mac/permissions)).
- 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: `ClawdbotBuildTimestamp` (UTC) and `ClawdbotGitCommit` (short hash) so the About pane can show build, git, and debug/release channel.
- **Packaging requires Node**: The embedded gateway relay is bundled with Node. Ensure Node is available for the packaging script (or set `NODE_VERSION` to pin the download).
- **Packaging requires Node 22+**: the script runs TS builds and the Control UI build.
- 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).
## Usage

View File

@@ -18,8 +18,7 @@ node.
- Runs or connects to the Gateway (local or remote).
- Exposes macOSonly tools (Canvas, Camera, Screen Recording, `system.run`).
- Optionally hosts **PeekabooBridge** for UI automation.
- Installs a helper CLI (`clawdbot`) into `/usr/local/bin` and
`/opt/homebrew/bin` on request.
- Installs the global CLI (`clawdbot`) via npm/pnpm/bun on request.
## Local vs remote mode
@@ -84,14 +83,13 @@ Safety:
1) Install and launch **Clawdbot.app**.
2) Complete the permissions checklist (TCC prompts).
3) Ensure **Local** mode is active and the Gateway is running.
4) Install the CLI helper if you want terminal access.
4) Install the CLI if you want terminal access.
## Build & dev workflow (native)
- `cd apps/macos && swift build`
- `swift run Clawdbot` (or Xcode)
- Package app + CLI: `scripts/package-mac-app.sh`
- Switch bundled gateway runtime with `BUNDLED_RUNTIME=node|bun` (default: node).
- Package app: `scripts/package-mac-app.sh`
## Debug gateway discovery (macOS CLI)
@@ -115,6 +113,6 @@ the Node CLIs `dns-sd` based discovery.
## Related docs
- [Gateway runbook](/gateway)
- [Bundled Node Gateway](/platforms/mac/bundled-gateway)
- [Gateway (macOS)](/platforms/mac/bundled-gateway)
- [macOS permissions](/platforms/mac/permissions)
- [Canvas](/platforms/mac/canvas)

View File

@@ -143,7 +143,7 @@ Use these hubs to discover every page, including deep dives and reference docs t
- [macOS remote](/platforms/mac/remote)
- [macOS signing](/platforms/mac/signing)
- [macOS release](/platforms/mac/release)
- [macOS bundled gateway (Node)](/platforms/mac/bundled-gateway)
- [macOS gateway (launchd)](/platforms/mac/bundled-gateway)
- [macOS XPC](/platforms/mac/xpc)
- [macOS skills](/platforms/mac/skills)
- [macOS Peekaboo](/platforms/mac/peekaboo)

View File

@@ -17,7 +17,7 @@ wizard, and let the agent bootstrap itself.
3) **Auth (Anthropic OAuth)** — local only
4) **Setup Wizard** (Gatewaydriven)
5) **Permissions** (TCC prompts)
6) **CLI helper** (optional)
6) **CLI** (optional)
7) **Onboarding chat** (dedicated session)
8) Ready
@@ -62,10 +62,10 @@ Onboarding requests TCC permissions needed for:
- Microphone / Speech Recognition
- Automation (AppleScript)
## 5) CLI helper (optional)
## 5) CLI (optional)
The app can symlink the bundled `clawdbot` CLI into `/usr/local/bin` and
`/opt/homebrew/bin` so terminal workflows work out of the box.
The app can install the global `clawdbot` CLI via npm/pnpm/bun so terminal
workflows and launchd tasks work out of the box.
## 6) Onboarding chat (dedicated session)

View File

@@ -157,8 +157,8 @@ All endpoints accept `?profile=<name>`.
### Playwright requirement
Some features (navigate/act/ai snapshot, element screenshots, PDF) require
Playwright. In embedded gateway builds, Playwright may be unavailable; those
endpoints return a clear 501 error. ARIA snapshots and basic screenshots still work.
Playwright. If Playwright isnt installed, those endpoints return a clear 501
error. ARIA snapshots and basic screenshots still work.
## How it works (internal)