You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Run an AI agent that can fully operate a fresh Mac mini at home (browser automation, GUI control, shell) from anywhere. The agent "brain" runs in a sandbox — home, cloud, k8s, anywhere. The Mac mini runs a thin executor daemon. All traffic goes over Tailscale. OpenAB Connect/Remote (Mac/iOS app) lets the human control the agent and view the remote desktop from anywhere.
Mental model — three cleanly separated roles
Role
Component
Runs
🧠 Brain
Agent (via openab broker) + openab-pty for human shell access
Sandbox — k8s / ECS / anywhere
🎮 Remote control
OpenAB Connect / Remote (Mac / iOS app)
Wherever the human is
🦾 Hands & feet
OpenAB Mac App (oab-mc-agent)
Mac mini fleet on isolated home VLAN
Perfect isolation between all three layers — every cross-boundary edge goes through the tailnet.
Ecosystem overview
flowchart TB
subgraph human["👤 Human — anywhere"]
CHAT["Chat client<br/>Discord / Slack / Telegram"]
CONNECT["🎮 OpenAB Connect / Remote<br/>(Mac / iOS app)"]
end
subgraph tailnet["🔐 Tailscale tailnet — WireGuard encrypted overlay + ACLs"]
NET(("tailnet"))
end
subgraph sandbox["🧠 Agent Sandbox — k8s / ECS / anywhere"]
OAB["openab<br/>Open Agent Broker<br/>chat ⇄ ACP JSON-RPC"]
AGENT["ACP Agent CLI<br/>(Kiro / Claude / …)<br/>the brain: LLM loop, planning"]
PTY["openab-pty runtime<br/>sandboxed PTY over WSS<br/>per-session tokens"]
WORK["shared workspace"]
OAB -->|"stdio"| AGENT
AGENT --- WORK
PTY --- WORK
end
subgraph home["🏠 Home — isolated VLAN / guest Wi-Fi (no LAN access)"]
subgraph mini["Mac mini (×N fleet)"]
MCA["🦾 OpenAB Mac App<br/>(oab-mc-agent)<br/>thin executor daemon"]
SCK["ScreenCaptureKit<br/>screenshot / stream"]
INJ["CGEvent + AX<br/>input injection"]
CDP["Chrome<br/>remote CDP"]
SH["shell /<br/>AppleScript"]
MCA --- SCK
MCA --- INJ
MCA --- SH
MCA -.manages.- CDP
end
end
CHAT -->|"natural-language tasks"| OAB
CONNECT -->|"attach terminal<br/>HTTPS + WSS"| NET
CONNECT -->|"live desktop view<br/>video stream"| NET
AGENT -->|"operate Mac:<br/>daemon API + Playwright over CDP"| NET
NET --> PTY
NET --> MCA
NET --> CDP
classDef brain fill:#e8f4fd,stroke:#3a87c8,color:#000
classDef hands fill:#e9f7ef,stroke:#2e9e5b,color:#000
classDef control fill:#fff4e6,stroke:#d9822b,color:#000
classDef net fill:#f3e8fd,stroke:#8e5bc8,color:#000
class AGENT,OAB,PTY,WORK brain
class MCA,SCK,INJ,CDP,SH hands
class CHAT,CONNECT control
class NET net
Loading
Design principle: brain/body separation
Mac mini side stays thin: a pure executor daemon that rarely changes. All intelligence (LLM loop, task orchestration, retry strategy) lives in the sandbox and can be rolled out independently.
Browser control is native to this split: Chrome runs on the Mac mini with --remote-debugging-port; the sandboxed agent drives it directly via playwright.connectOverCDP("http://<tailnet-ip>:9222"). No custom protocol needed for browser tasks.
Components
1. Network — Tailscale
Mac mini: system Tailscale app.
Sandbox: preferred options in order — (a) tsnet embedded in the agent binary (userspace, no privileged pod), (b) Tailscale Kubernetes Operator, (c) tailscaled sidecar.
Ephemeral + tagged auth keys so pods auto-join the tailnet on recreation.
ACLs are mandatory: CDP and the executor daemon have no built-in auth. Lock ports to the agent pod's tag. Add a shared-token check in the daemon as a second layer.
2. Mac mini — OpenAB Mac App / oab-mc-agent (Swift)
LaunchAgent (must run in the Aqua user session for GUI access — not a LaunchDaemon).
WebSocket (or gRPC) server bound to the tailnet IP.
Connects to the sandbox for task submission, status, and terminal attach (via openab-pty).
Connects directly to the Mac mini over the tailnet only when live desktop view is needed.
Swift chosen over Tauri: native VideoToolbox decode for streaming, shared Codable protocol models with the daemon, and a free path to an iOS client.
Isolation & hardening (defense in depth)
VLAN / guest Wi-Fi isolation — Mac minis live on a dedicated home network segment that cannot reach any other hosts on the home LAN. A compromised Mac mini can't pivot into the home network.
Tailscale ACLs — only tagged agent pods can reach the executor daemon / CDP ports.
Daemon shared token — last line of defense on the API itself.
This makes the Mac minis behave like disposable "compute appliances" — safe to let an autonomous agent drive them.
macOS setup (one-time, manual by design)
TCC permissions cannot be granted programmatically; a setup wizard should guide:
Accessibility, Screen Recording, Automation, (optionally) Full Disk Access.
Auto-login enabled, screen lock/saver disabled so the GUI session stays alive.
Known constraints / risks
Latency: screenshot → sandbox → LLM → action round trip; acceptable when the tailnet gets a direct (hole-punched) connection, worse via DERP relay.
CDP is unauthenticated: mitigated by Tailscale ACLs + daemon token.
OpenAB Mac Agent — Design Proposal
Goal
Run an AI agent that can fully operate a fresh Mac mini at home (browser automation, GUI control, shell) from anywhere. The agent "brain" runs in a sandbox — home, cloud, k8s, anywhere. The Mac mini runs a thin executor daemon. All traffic goes over Tailscale. OpenAB Connect/Remote (Mac/iOS app) lets the human control the agent and view the remote desktop from anywhere.
Mental model — three cleanly separated roles
openabbroker) +openab-ptyfor human shell accessoab-mc-agent)Perfect isolation between all three layers — every cross-boundary edge goes through the tailnet.
Ecosystem overview
flowchart TB subgraph human["👤 Human — anywhere"] CHAT["Chat client<br/>Discord / Slack / Telegram"] CONNECT["🎮 OpenAB Connect / Remote<br/>(Mac / iOS app)"] end subgraph tailnet["🔐 Tailscale tailnet — WireGuard encrypted overlay + ACLs"] NET(("tailnet")) end subgraph sandbox["🧠 Agent Sandbox — k8s / ECS / anywhere"] OAB["openab<br/>Open Agent Broker<br/>chat ⇄ ACP JSON-RPC"] AGENT["ACP Agent CLI<br/>(Kiro / Claude / …)<br/>the brain: LLM loop, planning"] PTY["openab-pty runtime<br/>sandboxed PTY over WSS<br/>per-session tokens"] WORK["shared workspace"] OAB -->|"stdio"| AGENT AGENT --- WORK PTY --- WORK end subgraph home["🏠 Home — isolated VLAN / guest Wi-Fi (no LAN access)"] subgraph mini["Mac mini (×N fleet)"] MCA["🦾 OpenAB Mac App<br/>(oab-mc-agent)<br/>thin executor daemon"] SCK["ScreenCaptureKit<br/>screenshot / stream"] INJ["CGEvent + AX<br/>input injection"] CDP["Chrome<br/>remote CDP"] SH["shell /<br/>AppleScript"] MCA --- SCK MCA --- INJ MCA --- SH MCA -.manages.- CDP end end CHAT -->|"natural-language tasks"| OAB CONNECT -->|"attach terminal<br/>HTTPS + WSS"| NET CONNECT -->|"live desktop view<br/>video stream"| NET AGENT -->|"operate Mac:<br/>daemon API + Playwright over CDP"| NET NET --> PTY NET --> MCA NET --> CDP classDef brain fill:#e8f4fd,stroke:#3a87c8,color:#000 classDef hands fill:#e9f7ef,stroke:#2e9e5b,color:#000 classDef control fill:#fff4e6,stroke:#d9822b,color:#000 classDef net fill:#f3e8fd,stroke:#8e5bc8,color:#000 class AGENT,OAB,PTY,WORK brain class MCA,SCK,INJ,CDP,SH hands class CHAT,CONNECT control class NET netDesign principle: brain/body separation
--remote-debugging-port; the sandboxed agent drives it directly viaplaywright.connectOverCDP("http://<tailnet-ip>:9222"). No custom protocol needed for browser tasks.Components
1. Network — Tailscale
tsnetembedded in the agent binary (userspace, no privileged pod), (b) Tailscale Kubernetes Operator, (c)tailscaledsidecar.2. Mac mini — OpenAB Mac App /
oab-mc-agent(Swift)SCStream) — on-demand screenshots + optional live stream.AVSampleBufferDisplayLayerrender.3. Sandbox — Agent Brain
openabbrokers chat-driven instructions;openab-ptygives the human a sandboxed shell beside the agent workspace.4. OpenAB Connect / Remote (Swift native, macOS/iOS)
openab-pty).Isolation & hardening (defense in depth)
This makes the Mac minis behave like disposable "compute appliances" — safe to let an autonomous agent drive them.
macOS setup (one-time, manual by design)
TCC permissions cannot be granted programmatically; a setup wizard should guide:
Known constraints / risks
Phased plan
Requested by Pahud (Discord thread, 2026-09-22).