Apus macOS IPC architecture

A local Unix socket connects the node host service to the macOS app for exec approvals and system.run. The bundled apus-mac CLI uses a separate local control socket to inspect and configure primary and saved Gateway connections. Agent actions still flow through the Gateway WebSocket and node.invoke. The node-backed computer.act path runs embedded Peekaboo automation in-process. Standalone Peekaboo clients use PeekabooBridge.

Goals

How it works

Gateway + node transport

Node service + app IPC

The exec response deadline includes the requested command timeoutMs, the companion's 15-second approval window, and 5 seconds for transport overhead. An omitted timeout keeps the 20-second default; timeoutMs: 0 disables the response deadline while preserving cancellation. After submission, a response deadline reports TIMEOUT and a lost or oversized reply reports UNKNOWN. Both mean the execution outcome is unknown; the command is never replayed locally. COMPANION_APP_UNAVAILABLE is reserved for requests that could not be submitted to the companion.

Diagram (SCI):

Agent -> Gateway -> Node Service (WS)
                      |  IPC (UDS + token + HMAC + TTL)
                      v
                  Mac App (UI + TCC + system.run)

App control socket

apus-mac sends one JSONL request and receives one JSONL response per Unix-domain connection. The running app starts and stops this listener with its exec-approvals lifecycle owner. The shared listener owns the socket path lease, guarded filesystem cleanup, connection framing, and shutdown drainage. It exposes only these operations:

Operation Result and effect
status Primary connection, saved Gateways, and app version/build/profile.
primary.set Set local mode, SSH transport, or direct transport through the app's native connection owners; return the resulting primary status.
primary.clear Return the primary connection to its unconfigured state; return primary status.
gateway.list List saved Gateways and their connection status.
gateway.add Validate and connect through the Gateways tab's sign-in coordinator; return the saved Gateway and identity when present.
gateway.remove Resolve an ID/name and use the profile store's Remove path, including credential and dashboard-data cleanup.
gateway.reconnect Repeat browser sign-in for browser profiles or reconnect the saved token/password connection.

Requests identify the operation with an operation string. Primary SSH settings include sshTarget, optional ports, identityPath, and hostKeyPolicy (strict or openssh). Direct settings include url and an optional tlsFingerprint. Credential-bearing operations accept token or password inside the authenticated request. The CLI reads these from files or stdin. Saved-Gateway requests use name, url, and browser, or idOrName for removal/reconnection. Matching tries an exact ID first, then a unique case-insensitive name. Ambiguity is an error with candidate names/IDs.

The default profile uses ~/.apus/mac-control.sock and ~/.apus/mac-control.token. Named profiles use the corresponding ~/.apus-<name>/ directory. These paths follow AppProfile.stateDirectoryURL, independently of config/state environment overrides. The app owns token creation. The token must be a regular, user-owned file with mode 0600. Missing or unsafe credentials reject requests. Clients must have the app's peer UID (getpeereid). The JSON envelope carries a nonce, millisecond timestamp, encoded request, and HMAC-SHA256 over the nonce, timestamp, and exact request bytes. Requests have a 15-second authentication TTL. A successfully authenticated browser sign-in may remain open for the coordinator's bounded 300-second operation.

Socket responses use {ok:true,result:...} or {ok:false,error:{code,message}}. The CLI's --json success output unwraps result. status contains:

Responses never include tokens, passwords, browser-session credentials, or Keychain contents. Saved-Gateway mutations execute inside the signed app, where the profile store owns Keychain access, connection retirement, dashboard cookies, and device-token cleanup. The CLI never writes the saved-Gateway registry.

See remote control for shell examples, profile selection, safe credential input, and background app launch.

PeekabooBridge (UI automation)

Operational flows

Hardening notes

Related