manzanas
Kendalikan simulator iOS dari Claude Code, Cursor, atau Codex melalui label aksesibilitas, bukan dengan tangkapan layar dan koordinat ketukan, lengkap dengan sewa dan kumpulan hangat sehingga beberapa agen dapat berbagi satu Mac.
Dokumentasi
manzanas
A Mac daemon for multi-agent iOS simulator fleet orchestration: leases, actions, streaming, deterministic state, and an exportable run journal for AI agents (and humans) sharing simulators.
https://github.com/user-attachments/assets/deb577d0-1123-4a89-90d8-8d9c7684a3cf
The launch film — leases, actions, live streaming, warm pools, the broker, and the run journal in 52 seconds. Sound on.
manzanasd runs on each Mac host and owns everything stateful — the
simulator registry, the lease table, the warm pool, action backends,
streamers, golden images, and the run journal. Clients (manzanas CLI, MCP
facade, SDKs) are thin and cross-platform, speaking a versioned JSON
protocol over HTTP + WebSocket. manzanas-broker federates N daemons
behind one endpoint — start with one Mac, and when you outgrow it the same
clients lease across the whole fleet without changing a line.
https://github.com/user-attachments/assets/983b0548-df1a-41a3-812c-f0f39cfaa01c
1 orchestrator, 7 Codex agents, 7 simulators across 3 Macs — leases mean nobody trips over anybody. Real time, no edits.
Website: manzanas.dapsdev.dev (source in
site/).
Install
brew tap baribarigood/tap https://github.com/BariBariGood/homebrew-tap
brew trust baribarigood/tap # Homebrew >= 6 requires trusting third-party taps
brew install manzanasd # daemon (+ pulls in the manzanas CLI)
brew services start manzanasd # launchd service on port 7433
See docs/install.md for launchd tarball installs and alternatives, and docs/quickstart.md for a single-Mac walkthrough from install to first screenshot.
Why
Agents driving simulators over raw SSH + CLI tools trip over each other
and pay huge fixed costs. manzanasd removes both, with measured numbers
(M3 Pro, macOS 26.5, Xcode 26.5; reproduce with make bench):
- Leases, not locks: TTL-bounded exclusive claims with FIFO queues — no two agents ever drive the same sim.
- Park/thaw warm pool: idle sims are SIGSTOPped (a parked tree is unschedulable — ~0 idle host CPU no matter what the sim's daemons are doing) and thawed on lease grant: ~0.28 s lease-to-live vs ~7 s for a cold boot (~29 s first boot). The thaw itself is a cached-PID SIGCONT and takes under a millisecond.
- Warm actions: a resident per-sim helper makes an end-to-end tap ~36 ms vs ~950 ms cold (per-action AXe spawn) — ~3 s cold on Intel.
- Deterministic state: snapshots, fixtures, per-lease auto-reset, and golden images that stamp out slimmed sims in seconds (~0.75 GB vs ~5 GB stock, via simslim) — how one Mac runs a dozen sims.
- Evidence: every mutating op under a lease is journaled, with content-addressed artifacts and a PR-ready markdown export.
| Leases | TTL-bounded exclusive claims, labels, FIFO queues, auto-reset |
| Warm pool | park/thaw (SIGSTOP) pool sims: ~0.28 s lease-to-live, ~0 idle CPU |
| Actions | cold (AXe) + warm (resident helper) taps/swipes/typing, composite tap_element with a structured predicate DSL, batches |
| Audit | deterministic UI checks (touch targets, clipping, alignment, spacing, safe area, missing labels) → findings + annotated screenshot in the journal |
| Streaming | MJPEG fan-out, browser /view page, WS frames |
| Video | per-lease simctl recordings that land in the journal |
| State | snapshots, fixtures, per-lease auto-reset, golden images |
| Journal | append-only evidence per run, artifacts, export.md |
| Dashboard | read-only web dashboard at /dash: fleet, leases, multiview, journal browser |
| Devices | physical iPhones via devicectl + WebDriverAgent (--devices) |
| Fleet | manzanas-broker federates N Macs behind one endpoint |
| Clients | manzanas CLI, MCP tools over stdio, npm wrapper, GitHub Action |
![]() | ![]() |
|---|---|
the browser /view MJPEG live page | the built-in /dash fleet dashboard |
Quickstart
New here? docs/quickstart.md walks through a full single-Mac session (install → lease → tap → screenshot). The short version:
make build # builds bin/manzanasd, bin/manzanas, bin/manzanas-broker
# on a Mac with Xcode:
./bin/manzanasd --addr :7433
# anywhere (Linux/dev/CI), with a mock fleet and a full mock action
# backend — the whole lease→observe→tap→audit loop, no Mac (docs/mock.md):
./bin/manzanasd --addr :7433 --mock
# list simulators
curl -s localhost:7433/v0/targets | jq
# lease one by label, boot it, release it
curl -s -X POST localhost:7433/v0/leases \
-d '{"labels":["ios26"],"agent_id":"me","ttl_seconds":300}' | jq
curl -s -X POST localhost:7433/v0/targets/<udid>/boot -d '{"lease_id":"<id>"}' | jq
curl -s -X DELETE localhost:7433/v0/leases/<id> | jq
Or the thin client (--json for machine output; see
clients/):
manzanas targets
manzanas lease acquire --labels ios26 --agent me --wait
manzanas tap 200 400 --lease lse_...
manzanas mcp # lease-scoped MCP tools over stdio for agents
Production installs (launchd, releases): docs/install.md.
MCP (Claude Code, Cursor, Codex)
manzanas mcp serves the whole toolset over the Model Context Protocol
(stdio), so any MCP-capable agent can lease and drive simulators — with
per-session auto-release of leases and self-describing tool errors.
Ready-to-paste client configs and troubleshooting:
docs/mcp.md.
claude mcp add manzanas -e MANZANASD_ADDR=mac-host:7433 -- /path/to/manzanas mcp
Architecture
┌ Linux / CI / anywhere ────────────┐ ┌ each Mac host ─────────────────────────────┐
│ manzanas (thin client, Go) │ WS │ manzanasd (Go daemon) :7433 │
│ - CLI: lease/tap/observe/... │◄──────►│ registry ── warm pool (park/thaw, gates) │
│ - MCP facade (stdio) │ HTTP │ leases (TTL, labels, FIFO, auto-reset) │
│ - eval harness (manzanas-eval) │ │ actions ── cold AXe / warm simbridge │
├───────────────────────────────────┤ │ streams (MJPEG fan-out, browser view) │
│ manzanas-broker :7440 │ │ state (snapshots, fixtures, golden images)│
│ fleet-wide placement: leases are │───────►│ journal (evidence, artifacts, export.md) │
│ scheduled across N daemons, then │ probe/ └────────────────────────────────────────────┘
│ clients talk to the owning │ lease × one daemon per Mac in the fleet
│ daemon directly (host_addr) │
└───────────────────────────────────┘
Documentation
Protocol:
- proto/PROTOCOL.md — the v0 wire protocol: targets,
leases, actions (incl. composite
tap_element/type_into_elementandactions:batch), streams, state, images, journal, WS surface.
Subsystems:
- docs/architecture.md — components and the interface contracts between slices.
- docs/agent-qa.md — a worked end-to-end agent QA session, plus driving animated (React Native) apps: screenshot/type races, waiting strategy, batch entry shape.
- docs/devices.md — physical iPhones as leasable targets (devicectl + WebDriverAgent).
- docs/recording.md — per-lease video capture into the journal.
- docs/warm-pool.md — park/thaw warm pool, footprint watchdog, host safety gates (503 overloaded).
- docs/actions-warm.md — warm vs cold action
paths; the resident
simbridgehelper. - docs/streaming.md — MJPEG streaming and the browser view page.
- docs/dashboard.md — the built-in read-only web
dashboard at
/dash(fleet, leases, pool, journal browser). - docs/state.md — snapshots, fixtures, per-lease auto-reset, quarantine.
- docs/images.md — golden images: slim once, stamp N sims in seconds.
- docs/journal.md — run journal format, artifacts, GC.
- docs/broker.md — multi-Mac federation.
- docs/eval.md — the scenario-driven determinism benchmark harness.
- docs/mcp.md — the MCP server: setup, Claude Code/Cursor/Codex configuration, troubleshooting.
- clients/README.md —
manzanasCLI + MCP quickstarts; clients/npm/; GitHub Action in action/.
Operations:
- docs/install.md — launchd install, releases, Homebrew formula.
- docs/fleet.md — running a multi-Mac fleet (topology, Tailscale, day-2 ops).
- docs/troubleshooting.md — 503 overloaded, boot failures, parked-sim semantics, quarantine, and friends.
The physical fleet this runs on (machines, locks, build caching) is site-specific; docs/fleet.md covers the daemon's part.
Status
Everything above is implemented and running on the fleet — leases +
queues, warm pool with safety gates, cold (AXe) + warm (simbridge) action
backends, composite/batch actions, MJPEG streaming, video capture,
snapshots/fixtures/auto-reset, golden images, journal, dashboard,
physical-device support, broker, eval harness, CLI + MCP. Verify with
go build ./... && go vet ./... && go test ./... (Linux-safe; simctl
paths are mocked).
License
Apache-2.0 — see LICENSE. Releases up to and including v0.6.0 (and their existing tags) were published under MIT and remain MIT; later releases are Apache-2.0.

