manzanas
Controle simuladores iOS a partir do Claude Code, Cursor ou Codex por rótulo de acessibilidade em vez de captura de tela e coordenadas de toque, com leases e um pool aquecido para que vários agentes possam compartilhar um único Mac.
Documentação
manzanas
Um daemon para Mac que orquestra frotas de simuladores iOS para múltiplos agentes: leases, ações, streaming, estado determinístico e um diário de execução exportável para agentes de IA (e humanos) que compartilham simuladores.
A história dos 90%: faça lease de um simulador, execute uma spec YAML, obtenha evidências. Todo o resto — frotas, iPhones físicos, espelhamento — é um capítulo opcional que você pode ignorar até precisar.
https://github.com/user-attachments/assets/983b0548-df1a-41a3-812c-f0f39cfaa01c
1 orquestrador, 7 agentes Codex, 7 simuladores em 3 Macs; leases garantem que ninguém atrapalhe ninguém. Tempo real, sem edições.
manzanasd roda em cada host Mac e é dono de tudo que é stateful: o registro de
simuladores, a tabela de leases, o pool aquecido, os backends de ações, os
streamers, as imagens douradas e o diário de execução. Os clientes (CLI manzanas, fachada MCP,
SDKs) são leves e multiplataforma, falando um protocolo JSON versionado
sobre HTTP + WebSocket.
Site: manzanas.dapsdev.dev (código-fonte em
site/).
Início rápido em cinco minutos
Sem flags para ler, sem config para escrever. Quatro camadas, comece na que combina com sua máquina:
0. Uma linha (macOS/Linux): npx
npx manzanasd-client@latest doctor # downloads the release binary and runs the setup diagnosis
O wrapper npm baixa o binário manzanasd/manzanas correto para sua
plataforma na instalação e depois faz proxy de todos os comandos para ele. Use como CLI,
ou aponte a config MCP do seu agente para manzanas mcp.
1. Em qualquer lugar (sem Mac): modo mock
make build # writes bin/manzanasd, bin/manzanas, bin/manzanas-broker
./bin/manzanasd --mock # full daemon + fake fleet + mock action backend
Em outro terminal, execute o loop completo lease → boot → ação → evidência como uma execução YAML declarativa:
# hello.yaml, drives the mock login screen (docs/mock.md)
name: hello
target:
labels: [ios26]
steps:
- action: type_into_element
with: {id: username, text: agent}
- action: type_into_element
with: {id: password, text: pw}
- action: tap_element
with: {label: "Sign In"}
- action: wait_for_element
with: {label: "Welcome, agent!", timeout_ms: 5000}
./bin/manzanas run hello.yaml -o evidence.md
cat evidence.md # PR-ready markdown evidence of every step
Esse é o produto: uma spec, um comando, um rastro de evidências registrado. A mesma spec roda sem alterações contra simuladores reais e contra iPhones físicos, porque cada alvo fala a mesma API de ações.
2. Em um Mac com Xcode: simuladores reais
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
manzanas doctor # one-shot setup diagnosis; every failure names its fix
manzanasd precisa de zero flags para um daemon de Mac único funcionando:
padrões sensatos para o diário, biblioteca de templates e mapa de elementos,
simuladores enumerados a partir de simctl, dispositivos físicos e espelhamento desligados
até você optar por ativá-los. O mesmo manzanas run spec.yaml agora dirige simuladores
reais. Passo a passo completo (lease, toque, screenshot, release manual):
docs/quickstart.md.
manzanas targets # list simulators
manzanas lease acquire --labels ios26 --agent me --wait # claim one
manzanas tap 200 400 --lease lse_... # drive it
manzanas mcp # or hand the tools to an agent
3. Capítulos opcionais (provavelmente você ainda não precisa deles)
- iPhones físicos (WebDriverAgent): docs/devices.md
- Apps hostis ao XCTest via iPhone Mirroring: docs/mirror-onboarding.md
- Vários Macs atrás de um único endpoint: docs/broker.md
Por quê
Agentes dirigindo simuladores via SSH bruto + ferramentas de CLI atrapalham uns aos outros
e pagam custos fixos enormes. O manzanasd remove ambos, com números medidos
(M3 Pro, macOS 26.5, Xcode 26.5; reproduza com make bench):
- Leases, não locks: reivindicações exclusivas com TTL e filas FIFO; dois agentes nunca dirigem o mesmo simulador.
- Pool aquecido park/thaw: simuladores ociosos recebem SIGSTOP (uma árvore parada não é escalonável, ~0 CPU de host ociosa não importa o que os daemons do simulador estejam fazendo) e são descongelados na concessão do lease: ~0,28 s de lease-para-vivo vs ~7 s para um boot frio (~29 s no primeiro boot). O descongelamento em si é um SIGCONT com PID em cache e leva menos de um milissegundo.
- Ações aquecidas: um helper residente por simulador faz um toque ponta a ponta em ~36 ms vs ~950 ms a frio (spawn de AXe por ação), ~3 s a frio em Intel.
- Estado determinístico: snapshots, fixtures, auto-reset por lease e imagens douradas que geram simuladores enxutos em segundos (~0,75 GB vs ~5 GB padrão, via simslim), é assim que um Mac roda uma dúzia de simuladores.
- Evidências: toda operação mutável sob um lease é registrada, com artefatos endereçados por conteúdo e exportação markdown pronta para PR.
| Leases | Reivindicações exclusivas com TTL, labels, filas FIFO, auto-reset, pause/resume para handoff humano |
| Pool aquecido | pool park/thaw (SIGSTOP): ~0,28 s de lease-para-vivo, ~0 CPU ociosa |
| Ações | toques/deslizes/digitação a frio (AXe) + aquecidos (helper residente), tap_element composto com DSL de predicados estruturados, compostos de rolagem de lista (scroll_until/scroll_collect), templates de pixel (save_template/tap_template), lotes |
| Verificação | pós-condições assert_text/assert_template, toques verificados por pixel (opt-in), settle de pixel wait_for_stable, veredictos de execução + detecção de drift em replay |
| Execuções | execuções YAML em uma chamada: lease → boot → app → passos → evidência → release (docs/runs.md) |
| Auditoria | verificações de UI determinísticas (alvos de toque, clipping, alinhamento, espaçamento, safe area, labels ausentes) → achados + screenshot anotado no diário |
| Streaming | fan-out MJPEG, página /view no navegador, frames WS |
| Vídeo | gravações simctl por lease que vão para o diário |
| Estado | snapshots, fixtures, auto-reset por lease, imagens douradas |
| Diário | evidência append-only por execução, artefatos, export.md, exportação de spec reproduzível |
| Dashboard | web dashboard somente leitura em /dash: frota, leases, multiview, navegador do diário |
| Doctor | manzanas doctor: diagnóstico de host em uma chamada, cada verificação com falha traz sua correção |
| Dispositivos | iPhones físicos via devicectl + WebDriverAgent, ou iPhone Mirroring para apps hostis ao XCTest |
| Frota | manzanas-broker federa N Macs atrás de um único endpoint |
| Clientes | CLI manzanas, ferramentas MCP via stdio, wrapper npm, GitHub Action |
![]() | ![]() |
|---|---|
a página MJPEG ao vivo /view no navegador | o dashboard de frota /dash embutido |
MCP (Claude Code, Cursor, Codex)
manzanas mcp serve todo o conjunto de ferramentas via Model Context Protocol
(stdio), então qualquer agente compatível com MCP pode fazer lease e dirigir simuladores, com
auto-release de leases por sessão e erros de ferramenta autodescritivos.
Configs de cliente prontas para colar e troubleshooting:
docs/mcp.md.
claude mcp add manzanas -e MANZANASD_ADDR=mac-host:7433 -- /path/to/manzanas mcp
Arquitetura
┌ 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) │
└───────────────────────────────────┘
Um núcleo de orquestração, transports como backends finos: a mesma spec YAML, leases, diário e pipeline de evidências rodam contra simuladores (AXe/simctl), iPhones físicos (WebDriverAgent) e apps hostis ao XCTest (iPhone Mirroring). O que manzanas não é — um framework genérico de automação OCR, uma ferramenta de bot para apps — está documentado em docs/non-goals.md, junto com o porquê de o repositório continuar um repositório único.
Documentação
Comece aqui (o caminho dos 90%):
- docs/quickstart.md, do zero a uma execução que passa em um Mac: install → doctor → lease → toque → screenshot → execução YAML.
- docs/runs.md, a execução YAML em uma chamada: schema, veredictos, detecção de drift, record → replay.
- docs/mock.md, o daemon completo em qualquer lugar (Linux/CI), sem precisar de Mac.
- docs/journal.md, o rastro de evidências: formato do diário de execução, artefatos, exportação markdown, exportação de spec reproduzível.
- docs/mcp.md, entregando as ferramentas a um agente (Claude Code, Cursor, Codex).
- docs/troubleshooting.md,
manzanas doctorprimeiro, depois sintomas → causas → correções.
Aprofundando (leia quando chegar no subsistema):
- proto/PROTOCOL.md, o protocolo de rede v0: alvos, leases, ações, streams, estado, diário, execuções, superfície WS. As tabelas na §5 são a lista autoritativa de tipos de ação e payloads.
- docs/architecture.md, componentes, contratos de interface e a fronteira do produto.
- docs/agent-qa.md, uma sessão completa de QA de agente ponta a ponta, além de dirigir apps animados (React Native).
- docs/resolver-ladder.md, como a resolução de elementos funciona: degraus map/ax/ocr/template, proveniência, escalonamento.
- docs/elementmap.md, o mapa de elementos aprendido (resolução de caminho rápido entre execuções).
- docs/templates.md, a biblioteca de templates de pixel
(
save_template/tap_template/assert_template). - docs/warm-pool.md, pool aquecido park/thaw, watchdog de footprint, portões de segurança do host.
- docs/actions-warm.md, caminhos de ação aquecidos vs
frios; o helper residente
simbridge. - docs/state.md, snapshots, fixtures, auto-reset por lease, quarentena.
- docs/images.md, imagens douradas: enxugue uma vez, gere N simuladores em segundos.
- docs/streaming.md, streaming MJPEG e a página de visualização no navegador.
- docs/dashboard.md, o web dashboard embutido somente leitura
em
/dash. - docs/recording.md, captura de vídeo por lease no diário.
- docs/eval.md, o harness de benchmark de determinismo dirigido por cenários.
- clients/README.md, inícios rápidos da CLI
manzanas+ MCP; clients/npm/; GitHub Action em action/.
Provavelmente você ainda não precisa destes (superfícies opt-in; cada página abre com para quem é):
- docs/non-goals.md, a fronteira do produto: o que manzanas é, o que deliberadamente não é e o único candidato futuro a split.
- docs/devices.md, iPhones físicos como alvos leasáveis (devicectl + WebDriverAgent) e a referência do backend de espelhamento.
- docs/mirror-onboarding.md, o caminho de setup guiado para dirigir apps hostis ao XCTest via iPhone Mirroring.
- docs/broker.md, federação multi-Mac.
- docs/fleet.md, operando uma frota multi-Mac (topologia, Tailscale, operações do dia 2).
- docs/install.md, instalação via launchd, releases, fórmula Homebrew.
A frota física onde isso roda (máquinas, locks, cache de build) é específica do site; docs/fleet.md cobre a parte do daemon.
Status
Tudo acima está implementado e rodando na frota: leases +
filas (incl. pause/resume), pool aquecido com portões de segurança, backends de ação a frio (AXe) +
aquecidos (simbridge), ações compostas/lote/assert, a
escada de resolução com mapa de elementos e templates de pixel, execuções YAML em uma chamada
com veredictos e detecção de drift, streaming MJPEG, captura de vídeo,
snapshots/fixtures/auto-reset, imagens douradas, diário, dashboard, doctor,
suporte a dispositivos físicos (WDA + mirror), broker, harness de eval, CLI + MCP.
Verifique com go build ./... && go vet ./... && go test ./...
(seguro para Linux; caminhos de simctl são mockados).
Licença
Apache-2.0, veja LICENSE. Releases até e incluindo v0.6.0 (e suas tags existentes) foram publicados sob MIT e permanecem MIT; releases posteriores são Apache-2.0.

