refactor: tidy mac bundled gateway packaging

This commit is contained in:
Peter Steinberger
2026-01-10 16:03:01 +01:00
parent 43b530ca1c
commit 001a19eb2c
6 changed files with 222 additions and 62 deletions

View File

@@ -239,7 +239,11 @@
},
{
"source": "/mac/bun",
"destination": "/platforms/mac/bun"
"destination": "/platforms/mac/bundled-gateway"
},
{
"source": "/platforms/mac/bun",
"destination": "/platforms/mac/bundled-gateway"
},
{
"source": "/mac/canvas",
@@ -709,7 +713,7 @@
"platforms/mac/remote",
"platforms/mac/signing",
"platforms/mac/release",
"platforms/mac/bun",
"platforms/mac/bundled-gateway",
"platforms/mac/xpc",
"platforms/mac/skills",
"platforms/mac/peekaboo"

View File

@@ -0,0 +1,114 @@
---
summary: "Bundled gateway runtime: packaging, launchd, signing, and bundling"
read_when:
- Packaging Clawdbot.app
- Debugging the bundled gateway binary
- Changing relay bundling flags or codesigning
---
# Bundled Gateway (macOS)
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.
## What gets bundled
App bundle layout:
- `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 --no-optional --legacy`
- `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)
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 --no-optional --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.
## Launchd (Gateway as LaunchAgent)
Label:
- `com.clawdbot.gateway`
Plist location (per-user):
- `~/Library/LaunchAgents/com.clawdbot.gateway.plist`
Manager:
- The macOS app owns LaunchAgent install/update for the bundled gateway.
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)
## Codesigning (hardened runtime + Node)
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`.
## 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):
```bash
dist/Clawdbot.app/Contents/Resources/Relay/clawdbot --version
CLAWDBOT_SKIP_PROVIDERS=1 \
CLAWDBOT_SKIP_CANVAS_HOST=1 \
dist/Clawdbot.app/Contents/Resources/Relay/clawdbot gateway --port 18999 --bind loopback
```
Then, in another shell:
```bash
pnpm -s clawdbot gateway call health --url ws://127.0.0.1:18999 --timeout 3000
```

View File

@@ -93,6 +93,6 @@ Safety:
## Related docs
- [Gateway runbook](/gateway)
- [Bundled Node Gateway](/platforms/mac/bun)
- [Bundled Node Gateway](/platforms/mac/bundled-gateway)
- [macOS permissions](/platforms/mac/permissions)
- [Canvas](/platforms/mac/canvas)

View File

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