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

Release npm CI AllMCPs Verified

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)

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.
LeasesReivindicações exclusivas com TTL, labels, filas FIFO, auto-reset, pause/resume para handoff humano
Pool aquecidopool park/thaw (SIGSTOP): ~0,28 s de lease-para-vivo, ~0 CPU ociosa
Açõestoques/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çãopó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çõesexecuções YAML em uma chamada: lease → boot → app → passos → evidência → release (docs/runs.md)
Auditoriaverificações de UI determinísticas (alvos de toque, clipping, alinhamento, espaçamento, safe area, labels ausentes) → achados + screenshot anotado no diário
Streamingfan-out MJPEG, página /view no navegador, frames WS
Vídeogravações simctl por lease que vão para o diário
Estadosnapshots, fixtures, auto-reset por lease, imagens douradas
Diárioevidência append-only por execução, artefatos, export.md, exportação de spec reproduzível
Dashboardweb dashboard somente leitura em /dash: frota, leases, multiview, navegador do diário
Doctormanzanas doctor: diagnóstico de host em uma chamada, cada verificação com falha traz sua correção
DispositivosiPhones físicos via devicectl + WebDriverAgent, ou iPhone Mirroring para apps hostis ao XCTest
Frotamanzanas-broker federa N Macs atrás de um único endpoint
ClientesCLI manzanas, ferramentas MCP via stdio, wrapper npm, GitHub Action
Live MJPEG view of a leased simulator at /viewBuilt-in fleet dashboard at /dash
a página MJPEG ao vivo /view no navegadoro 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 doctor primeiro, 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.