Apus can host PeekabooBridge as a local, permission-aware UI automation broker (PeekabooBridgeHostCoordinator, backed by the apus/Peekaboo Swift package). This lets the peekaboo CLI drive UI automation while reusing the macOS app's TCC permissions.

What this is (and is not)

Relationship to other desktop-control paths

Apus has four desktop-control paths that intentionally stay separate:

Use Peekaboo for the broad macOS automation surface via Apus.app's permission-aware bridge host. Use agent-driven computer use when the gateway agent should see and control the desktop. It does this through a uniform computer.act node command that any vision model can drive. Use Codex Computer Use when a Codex-mode agent should rely on Codex's native plugin. Use direct cua-driver mcp to expose the CUA driver to any Apus-managed runtime as a normal MCP server.

Enable the bridge

In the macOS app, open Dashboard → Settings → This Mac → Capabilities and enable Peekaboo Bridge. The bridge requires Computer Control to be on, since both grant local UI automation. With Computer Control off, the host does not run. To drive Peekaboo without Computer Control, run Peekaboo's own Mac app as the host instead.

When enabled (and Computer Control is on), Apus starts a local UNIX socket server at ~/Library/Application Support/Apus/<socket-name>. If disabled, the host stops and peekaboo falls back to other available hosts. The coordinator also maintains legacy socket symlinks (clawdbot, clawdis, moltbot under Application Support) pointing at the current socket for older peekaboo installs.

For a one-off unattended run, --attach-only --background-only suppresses automatic windows and GUI-owned Keychain loading. The persistent elevation host is a managed-deployment path for OpenClaw Foundation release operators. Its package command requires the Foundation signing identity and notarization credentials. Apus does not publish a general-download elevation archive. Install only a certified, source-addressed archive supplied by an authorized release operator:

cd /path/to/elevation-artifact-set
export PREFIX="Apus-<full-apus-sha>-Peekaboo-<full-peekaboo-sha>-stable"
export INSTALLER_SHA256="<authenticated-installer-sha256>"
export RECEIPT_SHA256="<authenticated-receipt-sha256>"
[[ "$(shasum -a 256 "$PREFIX-installer.sh" | awk '{print $1}')" == "$INSTALLER_SHA256" ]] || exit 1
shasum -a 256 -c "$PREFIX.zip.sha256"
shasum -a 256 -c "$PREFIX-installer.sh.sha256"
./"$PREFIX-installer.sh" verify \
  --archive "$PREFIX.zip" \
  --receipt "$PREFIX.json" \
  --receipt-sha256 "$RECEIPT_SHA256"
./"$PREFIX-installer.sh" migration-plan \
  --migrate-launch-agent "$HOME/Library/LaunchAgents/ai.apus.node.plist"
./"$PREFIX-installer.sh" install \
  --archive "$PREFIX.zip" \
  --receipt "$PREFIX.json" \
  --receipt-sha256 "$RECEIPT_SHA256" \
  --migrate-launch-agent "$HOME/Library/LaunchAgents/ai.apus.node.plist"
./"$PREFIX-installer.sh" status --state-dir "<existing-state-dir>"

Transfer the complete artifact set: archive, receipt, portable installer, and both checksum files. The target Mac does not need an Apus source checkout. The authorized operator handoff must independently provide the installer and receipt SHA-256 digests. Run verify with the authenticated receipt digest before planning a cutover. The receipt then selects the approved archive. verify revalidates the Foundation-signed app, notarization, staple, Gatekeeper result, architectures, entitlements, and both source revisions. The portable installer is not covered by the app's code signature, so this explicit two-digest release-operator handoff remains part of the internal trust boundary.

Elevation artifacts require universal shared app code and one private runtime under Contents/Resources/runtime/. Its bin/bun and lib/libsqlite3.dylib must contain both arm64 and x86_64 Mach-O slices. verify checks both regardless of the target Mac's architecture. The runtime shares the full Apus package between architectures, including the CLI, worker, browser setup, and Control UI entrypoints. Package build metadata must match the app's version, source commit, build timestamp, and ApusRuntimeBuildID. Native dependencies, including addons, static archives, and libraries without executable permission bits, must support arm64 or x86_64; architecture-specific Darwin packages coexist in the shared tree. Foreign-platform native code and any Node executable in the app are rejected. Signable Mach-O images must also expose native signature metadata for every slice. A generic resource signature, even when strict whole-app verification succeeds, is not native-signature evidence. Compatible thin, fat32, and fat64 static archives remain resources protected by the app seal and architecture checks. They need no standalone Mach-O signature. Mixed archive/native containers fail verification. Inspection never thins or rewrites the supplied payload. Missing runtime entrypoints or required Bun/SQLite slices, escaping or cyclic runtime symlinks, and thin shared app executables or executable libraries outside the runtime fail verification. Dependencies that violate this closure must be repaired in packaging, not excluded from validation. The portable installer needs neither a checkout nor a separate inventory helper.

Both standard and elevation packaging construct a fresh runtime from the complete published package with production dependencies. Staging removes packages whose declared OS or CPU support excludes the requested architectures, and removes Node-based command shims. Materialization then preserves JavaScript, WASM, other resources, modes, and contained relative symlinks while omitting native images that cannot run on any selected Darwin architecture. Matching universal binaries remain intact. Within retained packages, Windows-named source, scripts, and README files remain; directory names alone do not select files for omission. Unclassifiable native images and links that would escape, cycle, or become dangling stop packaging. Both paths use the same runtime verification and publication flow. Build metadata remains unchanged by materialization. The elevation app retains library validation and rejects DISABLE_LIBRARY_VALIDATION=1. Its private Bun executable has the plugin native-addon exception; other helpers retain library validation.

The managed elevation workflow upgrades an already paired Mac. Its selected state and config must define an app-readable direct remote Gateway route with string token or password auth, and the selected macOS node identity must already be paired. migration-plan performs those checks without changing the app, process, LaunchAgent, state, or Gateway. It recognizes the canonical CLI-managed ai.apus.node job and app-backed background LaunchAgents. If the old app is running in background mode without a LaunchAgent, use --adopt-running-app instead of --migrate-launch-agent and pass its state/config paths explicitly when they are not the defaults.

--elevation-host is implied by the installed job. It keeps the Bridge, control channel, Mac node, Gateway connectivity, and termination handling active while disabling automatic windows, updater startup, Dock promotion, pairing and exec-approval presenters, Quick Chat hotkeys, voice and cookie services, and GUI-owned Keychain reads. status reports missing Screen Recording, Accessibility, or Event Synthesizing. The host never opens System Settings to grant it. Installation succeeds once the launchd-owned process is Bridge-ready even if those grants are still incomplete, but it commits only after the exact paired node identity reconnects as apus-macos/node with the new app version, computer capability, screen.snapshot, computer.act, and a computer-use descriptor. The installer copies no Gateway credentials or interactive PATH. It carries only the verified state/config ownership paths and uses the config's existing route and auth. status rechecks Bridge, Gateway node, and TCC readiness. The installer uses the separate ai.apus.mac.elevation-host job and refuses to race or rewrite ordinary Launch at login (ai.apus.mac).

Cutover is transactional: the installer snapshots the exact app and source plist, stops the prior owner, installs the replacement, and automatically restores the original bytes and loaded state if launchd, Bridge, or Gateway node attestation fails. The install receipt binds rollback plist digests, the prior app CDHash, and any previous managed install receipt. Generation-unique backups allow successive upgrades. recover preserves the replaced app in a unique evidence directory, restores the prior receipt, and refuses to overwrite a source LaunchAgent path recreated by another owner.

The elevation archive is Foundation-signed, notarized, stapled, named by the full Apus and Peekaboo source commits, and contains exactly Apus.app. Its receipt binds the archive and portable-installer names and digests, Apus and Peekaboo source revisions, signer, per-architecture CDHashes, architectures, entitlement digests, and Apple notarization submission ID. No AppleScript or Apple Events entitlement is part of this workflow.

Client discovery order

Peekaboo clients typically try hosts in this order:

  1. Peekaboo.app (full UX)
  2. Claude.app (if installed)
  3. Apus.app (thin broker)

Use peekaboo bridge status --verbose to see which host is active and which socket path is in use. Override with:

export PEEKABOO_BRIDGE_SOCKET=/path/to/bridge.sock

Security and permissions

Snapshot behavior (automation)

InMemorySnapshotManager stores snapshots in memory. It applies a 10-minute validity window and a cap of 50 snapshots. Cleanup does not delete artifacts. If you need longer retention, re-capture from the client.

Troubleshooting

Related