manzanas
Controla simuladores de iOS desde Claude Code, Cursor o Codex mediante la etiqueta de accesibilidad en lugar de coordenadas de captura de pantalla y toque, con concesiones y un grupo de instancias precalentadas para que múltiples agentes puedan compartir un Mac.
Documentación
manzanas
Un daemon de Mac para la orquestación de flotas de simuladores iOS multiagente: leases, acciones, streaming, estado determinista y un diario de ejecución exportable para agentes de IA (y humanos) que comparten simuladores.
https://github.com/user-attachments/assets/deb577d0-1123-4a89-90d8-8d9c7684a3cf
La película de lanzamiento: leases, acciones, streaming en vivo, warm pools, el broker y el diario de ejecución en 52 segundos. Con sonido.
manzanasd se ejecuta en cada host Mac y posee todo lo que tiene estado: el registro de simuladores, la tabla de leases, el warm pool, los backends de acciones, los streamers, las imágenes doradas y el diario de ejecución. Los clientes (CLI manzanas, fachada MCP, SDKs) son ligeros y multiplataforma, hablando un protocolo JSON versionado sobre HTTP + WebSocket. manzanas-broker federiza N daemons detrás de un único endpoint: comienza con un Mac y, cuando lo superes, los mismos clientes obtienen leases en toda la flota sin cambiar una línea.
https://github.com/user-attachments/assets/983b0548-df1a-41a3-812c-f0f39cfaa01c
1 orquestador, 7 agentes Codex, 7 simuladores en 3 Macs: los leases significan que nadie se tropieza con nadie. Tiempo real, sin ediciones.
Sitio web: manzanas.dapsdev.dev (fuente en site/).
Instalación
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
Consulta docs/install.md para instalaciones de tarball launchd y alternativas, y docs/quickstart.md para un recorrido de un solo Mac desde la instalación hasta la primera captura de pantalla.
Por qué
Los agentes que manejan simuladores a través de SSH y herramientas CLI se tropiezan entre sí y pagan enormes costos fijos. manzanasd elimina ambos, con números medidos (M3 Pro, macOS 26.5, Xcode 26.5; reproduce con make bench):
- Leases, no bloqueos: reclamos exclusivos con límite TTL y colas FIFO: nunca dos agentes manejan el mismo simulador.
- Warm pool de estacionamiento/descongelación: los simuladores inactivos se detienen con SIGSTOP (un árbol estacionado no es programable: ~0 CPU del host sin importar lo que hagan los daemons del simulador) y se descongelan al otorgar el lease: ~0.28 s de lease a activo vs ~7 s para un arranque en frío (~29 s en el primer arranque). La descongelación en sí es un SIGCONT con PID en caché y toma menos de un milisegundo.
- Acciones cálidas: un helper residente por simulador hace un toque de extremo a extremo en ~36 ms vs ~950 ms en frío (spawn de AXe por acción) — ~3 s en frío en Intel.
- Estado determinista: instantáneas, fixtures, auto-reset por lease e imágenes doradas que generan simuladores reducidos en segundos (~0.75 GB vs ~5 GB estándar, mediante simslim) — así es como un Mac ejecuta una docena de simuladores.
- Evidencia: cada operación mutante bajo un lease se registra en el diario, con artefactos direccionados por contenido y una exportación en markdown lista para PR.
| Leases | Reclamos exclusivos con límite TTL, etiquetas, colas FIFO, auto-reset |
| Warm pool | Simuladores en pool con estacionamiento/descongelación (SIGSTOP): ~0.28 s de lease a activo, ~0 CPU inactiva |
| Acciones | toques/deslizamientos/escritura en frío (AXe) y en caliente (helper residente), tap_element compuesto con un DSL de predicados estructurado, lotes |
| Auditoría | comprobaciones de UI deterministas (objetivos táctiles, recorte, alineación, espaciado, área segura, etiquetas faltantes) → hallazgos + captura de pantalla anotada en el diario |
| Streaming | fan-out MJPEG, página /view en el navegador, tramas WS |
| Vídeo | grabaciones simctl por lease que llegan al diario |
| Estado | instantáneas, fixtures, auto-reset por lease, imágenes doradas |
| Diario | evidencia de solo agregar por ejecución, artefactos, export.md |
| Panel | panel web de solo lectura en /dash: flota, leases, multivista, navegador de diario |
| Dispositivos | iPhones físicos mediante devicectl + WebDriverAgent (--devices) |
| Flota | manzanas-broker federiza N Macs detrás de un único endpoint |
| Clientes | CLI manzanas, herramientas MCP sobre stdio, envoltorio npm, GitHub Action |
![]() | ![]() |
|---|---|
la página en vivo MJPEG /view del navegador | el panel de flota /dash integrado |
Inicio rápido
¿Nuevo aquí? docs/quickstart.md recorre una sesión completa de un solo Mac (instalación → lease → toque → captura de pantalla). La versión corta:
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
O el cliente ligero (--json para salida de máquina; consulta 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
Instalaciones de producción (launchd, releases): docs/install.md.
MCP (Claude Code, Cursor, Codex)
manzanas mcp sirve todo el conjunto de herramientas a través del Model Context Protocol (stdio), de modo que cualquier agente compatible con MCP puede obtener leases y manejar simuladores, con liberación automática de leases por sesión y errores de herramienta autodescriptivos. Configuraciones de cliente listas para pegar y solución de problemas: docs/mcp.md.
claude mcp add manzanas -e MANZANASD_ADDR=mac-host:7433 -- /path/to/manzanas mcp
Arquitectura
┌ 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) │
└───────────────────────────────────┘
Documentación
Protocolo:
- proto/PROTOCOL.md — el protocolo de cable v0: objetivos, leases, acciones (incl.
tap_element/type_into_elementcompuestos yactions:batch), streams, estado, imágenes, diario, superficie WS.
Subsistemas:
- docs/architecture.md — componentes y los contratos de interfaz entre las partes.
- docs/agent-qa.md — una sesión de QA de agente de extremo a extremo, además de manejar aplicaciones animadas (React Native): carreras de captura/escritura, estrategia de espera, forma de entrada por lotes.
- docs/devices.md — iPhones físicos como objetivos arrendables (devicectl + WebDriverAgent).
- docs/recording.md — captura de video por lease en el diario.
- docs/warm-pool.md — warm pool de estacionamiento/descongelación, watchdog de huella, compuertas de seguridad del host (503 sobrecargado).
- docs/actions-warm.md — rutas de acción en caliente vs en frío; el helper residente
simbridge. - docs/streaming.md — streaming MJPEG y la página de vista en el navegador.
- docs/dashboard.md — el panel web de solo lectura integrado en
/dash(flota, leases, pool, navegador de diario). - docs/state.md — instantáneas, fixtures, auto-reset por lease, cuarentena.
- docs/images.md — imágenes doradas: reduce una vez, genera N simuladores en segundos.
- docs/journal.md — formato del diario de ejecución, artefactos, GC.
- docs/broker.md — federación multi-Mac.
- docs/eval.md — el arnés de benchmark de determinismo basado en escenarios.
- docs/mcp.md — el servidor MCP: configuración, configuración de Claude Code/Cursor/Codex, solución de problemas.
- clients/README.md — inicios rápidos de CLI
manzanas+ MCP; clients/npm/; GitHub Action en action/.
Operaciones:
- docs/install.md — instalación launchd, releases, fórmula Homebrew.
- docs/fleet.md — ejecutar una flota multi-Mac (topología, Tailscale, operaciones de día 2).
- docs/troubleshooting.md — 503 sobrecargado, fallos de arranque, semántica de simuladores estacionados, cuarentena y otros.
La flota física en la que se ejecuta (máquinas, bloqueos, caché de compilación) es específica del sitio; docs/fleet.md cubre la parte del daemon.
Estado
Todo lo anterior está implementado y en ejecución en la flota: leases + colas, warm pool con compuertas de seguridad, backends de acciones en frío (AXe) y en caliente (simbridge), acciones compuestas/lote, streaming MJPEG, captura de video, instantáneas/fixtures/auto-reset, imágenes doradas, diario, panel, soporte de dispositivos físicos, broker, arnés de evaluación, CLI + MCP. Verifica con go build ./... && go vet ./... && go test ./... (seguro para Linux; las rutas de simctl están simuladas).
Licencia
Apache-2.0 — consulta LICENSE. Las versiones hasta la v0.6.0 inclusive (y sus etiquetas existentes) se publicaron bajo MIT y siguen siendo MIT; las versiones posteriores son Apache-2.0.

