Bundled Gateway (macOS)
Goal: ship Clawdbot.app with a self-contained relay that can run the CLI and Gateway daemon. No globalnpm 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
- Compiled CLI/gateway payload from
Clawdbot.app/Contents/Resources/Relay/node_modules/- Production dependencies staged via
pnpm deploy --prod --legacy(includes optional native addons)
- Production dependencies staged via
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")
- tiny “Pi runtime compatibility” file (see below, includes
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)
- The embedded Pi runtime detects “bundled relay mode” and then looks for
package.json+theme/next toprocess.execPath(i.e. next tonode). Keep the sidecar files.
Build pipeline
Packaging script: It builds:- TS:
pnpm exec tsc - Swift app + helper:
swift build … - Relay payload:
pnpm deploy --prod --legacy+ copydist/ - Node runtime: downloads the latest Node release (override via
NODE_VERSION)
NODE_VERSION=22.12.0→ pin a specific Node versionNODE_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)
- The relay wrapper exports
CLAWDBOT_BUNDLED_VERSIONso--versionworks without readingpackage.jsonat runtime.
Launchd (Gateway as LaunchAgent)
Label:com.clawdbot.gateway(orcom.clawdbot.<profile>)
~/Library/LaunchAgents/com.clawdbot.gateway.plist(or.../com.clawdbot.<profile>.plist)
- The macOS app owns LaunchAgent install/update for the bundled gateway.
- “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;--forcerewrites it.
- launchd stdout/err:
/tmp/clawdbot/clawdbot-gateway.log
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-jitcom.apple.security.cs.allow-unsigned-executable-memory
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 nativesharp addons inside the bundle, the gateway defaults
to /usr/bin/sips for image ops when run from the app (via launchd env + wrapper).