3.6 KiB
3.6 KiB
summary, read_when
| summary | read_when | |
|---|---|---|
| macOS IPC architecture for Clawdis app, CLI helper, and gateway bridge (control socket + XPC + PeekabooBridge) |
|
Clawdis macOS IPC architecture (Dec 2025)
Note: the current implementation primarily uses a local UNIX-domain control socket (controlSocketPath) between clawdis-mac and the app. This doc captures the intended long-term Mach/XPC direction and the security constraints, and also documents the separate PeekabooBridge socket used for UI automation.
Goals
- Single GUI app instance that owns all TCC-facing work (notifications, screen recording, mic, speech, AppleScript).
- A small surface for automation: the
clawdis-macCLI and the Node gateway talk to the app via local IPC. - Predictable permissions: always the same signed bundle ID, launched by launchd, so TCC grants stick.
- Limit who can connect: only signed clients from our team (with an explicit DEBUG-only escape hatch for development).
How it works
Control socket (current)
clawdis-mactalks to the app via a local UNIX socket (controlSocketPath) for app-specific requests (notify, status, ensure-permissions, run, etc.).
PeekabooBridge (UI automation)
- UI automation uses a separate UNIX socket named
bridge.sockand the PeekabooBridge JSON protocol. - Host preference order (client-side): Peekaboo.app → Clawdis.app → local execution.
- Security: bridge hosts require TeamID
Y5PE65HELJ; DEBUG-only same-UID escape hatch is guarded byPEEKABOO_ALLOW_UNSIGNED_SOCKET_CLIENTS=1(Peekaboo convention). - See:
docs/mac/peekaboo.mdfor the Clawdis plan and naming.
Mach/XPC (future direction)
- The app registers a Mach service named
com.steipete.clawdis.xpcvia a user LaunchAgent at~/Library/LaunchAgents/com.steipete.clawdis.plist. - The launch agent runs
dist/Clawdis.app/Contents/MacOS/ClawdiswithRunAtLoad=true,KeepAlive=false, and aMachServicesentry for the XPC name. - The app hosts the XPC listener (
NSXPCListener(machServiceName:)) and exportsClawdisXPCService. - The CLI (
clawdis-mac) connects withNSXPCConnection(machServiceName:); the Node gateway shells out to the CLI. - Security: on incoming connections we read the audit token (or PID) and allow only:
- Code-signed clients with team ID
Y5PE65HELJ. - In
DEBUGbuilds only, you can opt into allowing same-UID clients by settingCLAWDIS_ALLOW_UNSIGNED_SOCKET_CLIENTS=1.
- Code-signed clients with team ID
Operational flows
- Restart/rebuild:
SIGN_IDENTITY="Apple Development: Peter Steinberger (2ZAC4GM7GD)" scripts/restart-mac.sh- Kills existing instances
- Swift build + package
- Writes/bootstraps/kickstarts the LaunchAgent
- CLI version:
clawdis-mac --version(pulled frompackage.jsonduring packaging) - Single instance: app exits early if another instance with the same bundle ID is running.
Why launchd (not anonymous endpoints)
- A Mach service avoids brittle endpoint handoffs and lets the CLI/Node connect even if the app was started by launchd.
- RunAtLoad without KeepAlive means the app starts once; if it crashes it stays down (no unwanted respawn), but CLI calls will re-spawn via launchd.
Hardening notes
- Prefer requiring a TeamID match for all privileged surfaces.
- Clawdis control socket:
CLAWDIS_ALLOW_UNSIGNED_SOCKET_CLIENTS=1(DEBUG-only) may allow same-UID callers for local development. - PeekabooBridge:
PEEKABOO_ALLOW_UNSIGNED_SOCKET_CLIENTS=1(DEBUG-only) may allow same-UID callers for local development.
- Clawdis control socket:
- All communication remains local-only; no network sockets are exposed.
- TCC prompts originate only from the GUI app bundle; run scripts/package-mac-app.sh so the signed bundle ID stays stable.