Bundled bun Gateway (macOS)
Goal: ship Clawdbot.app with a self-contained relay binary that can run both the CLI and the Gateway daemon. No globalnpm install -g clawdbot, no system Node requirement.
What gets bundled
App bundle layout:Clawdbot.app/Contents/Resources/Relay/clawdbot- bun
--compilerelay executable built fromdist/macos/relay.js - Supports:
clawdbot …(CLI)clawdbot gateway …(LaunchAgent daemon)
- bun
Clawdbot.app/Contents/Resources/Relay/package.json- tiny “p runtime compatibility” file (see below)
Clawdbot.app/Contents/Resources/Relay/theme/- p TUI theme payload (optional, but strongly recommended)
- The embedded p runtime detects “bun binary mode” and then looks for
package.json+theme/next toprocess.execPath(i.e. next toclawdbot). - So even if bun can embed assets, the runtime expects filesystem paths. Keep the sidecar files.
Build pipeline
Packaging script: It builds:- TS:
pnpm exec tsc - Swift app + helper:
swift build … - bun relay:
bun build dist/macos/relay.js --compile --bytecode …
--compile: produces a standalone executable--bytecode: reduces startup time / parsing overhead (works here)- externals:
-e electron- Reason: avoid bundling Electron stubs in the relay binary
--define "__CLAWDBOT_VERSION__=\"<pkg version>\""- The relay honors
__CLAWDBOT_VERSION__/CLAWDBOT_BUNDLED_VERSIONso--versiondoesn’t depend on readingpackage.jsonat runtime.
Launchd (Gateway as LaunchAgent)
Label:com.clawdbot.gateway
~/Library/LaunchAgents/com.clawdbot.gateway.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;clawdbot daemon install --forcerewrites it. clawdbot doctoraudits the LaunchAgent config and can update it to current defaults.
- launchd stdout/err:
/tmp/clawdbot/clawdbot-gateway.log
CLAWDBOT_IMAGE_BACKEND=sips(avoid sharp native addon under bun)
Codesigning (hardened runtime + bun)
Symptom (when mis-signed):Ran out of executable memory …on launch
- The bun executable needs JIT-ish permissions under hardened runtime.
scripts/codesign-mac-app.shsignsRelay/clawdbotwith:com.apple.security.cs.allow-jitcom.apple.security.cs.allow-unsigned-executable-memory
Image processing under bun
Problem:- bun can’t load some native Node addons like
sharp(and we don’t want to ship native addon trees for the gateway).
- Image operations prefer
/usr/bin/sipson macOS (especially under bun). - When running in Node/dev,
sharpis used when available. - This affects inbound/outbound media, screenshots, and tool image sanitization.
Browser control server
The Gateway starts the browser control server (loopback only) from the relay daemon process, so the relay binary includes Playwright deps.Tests / smoke checks
From a packaged app (local build):Repo hygiene
Bun may leave dotfiles like*.bun-build in the repo root or subfolders.
- These are ignored via
.gitignore(*.bun-build).
DMG styling (human installer)
scripts/create-dmg.sh styles the DMG via Finder AppleScript.
Rules of thumb:
- Use a 72dpi background image that matches the Finder window size in points.
- Preferred asset:
assets/dmg-background-small.png(500×320). - Default icon positions: app
{125,160}, Applications{375,160}.