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

Release CI License: Apache-2.0 AllMCPs Verified

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.
LeasesReclamos exclusivos con límite TTL, etiquetas, colas FIFO, auto-reset
Warm poolSimuladores en pool con estacionamiento/descongelación (SIGSTOP): ~0.28 s de lease a activo, ~0 CPU inactiva
Accionestoques/deslizamientos/escritura en frío (AXe) y en caliente (helper residente), tap_element compuesto con un DSL de predicados estructurado, lotes
Auditoríacomprobaciones de UI deterministas (objetivos táctiles, recorte, alineación, espaciado, área segura, etiquetas faltantes) → hallazgos + captura de pantalla anotada en el diario
Streamingfan-out MJPEG, página /view en el navegador, tramas WS
Vídeograbaciones simctl por lease que llegan al diario
Estadoinstantáneas, fixtures, auto-reset por lease, imágenes doradas
Diarioevidencia de solo agregar por ejecución, artefactos, export.md
Panelpanel web de solo lectura en /dash: flota, leases, multivista, navegador de diario
DispositivosiPhones físicos mediante devicectl + WebDriverAgent (--devices)
Flotamanzanas-broker federiza N Macs detrás de un único endpoint
ClientesCLI manzanas, herramientas MCP sobre stdio, envoltorio npm, GitHub Action
Live MJPEG view of a leased simulator at /viewBuilt-in fleet dashboard at /dash
la página en vivo MJPEG /view del navegadorel 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_element compuestos y actions: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.