Maestro has 1,319 open issues on GitHub. Some of them have been open for years. The most-upvoted feature request – real iOS device support – has been sitting there since 2022. Configurable timeouts? Requested in 2022. Parallel execution? Still not in the open-source CLI.
We got tired of waiting. So we built maestro-runner.
What It Is
maestro-runner is an open-source, drop-in replacement for the Maestro CLI. It reads the same YAML flow files, supports the same commands, and produces the same test results. If you have existing Maestro flows, you don’t change anything. You just swap the binary.
# Install
curl -fsSL https://open.devicelab.dev/install/maestro-runner | bash
# Run your existing flows -- no changes needed
maestro-runner flows/
Under the hood, it’s a single Go binary. No JVM, no Gradle, no dependency tree, no 400 MB of RAM just to tap a button.
The engine uses a three-driver architecture. Each driver speaks the protocol its platform already understands – no translation layers, no middleware:
- UIAutomator2 for Android. Direct HTTP to the on-device server. No gRPC, no protobuf serialization, no six-hop round trip per command. One HTTP call, one response.
- WebDriverAgent for iOS. Works on both real devices and simulators. Handles XCTest lifecycle internally with health checks and retry logic so you never see
IOSDriverTimeoutException. - Appium for cloud providers. BrowserStack, Sauce Labs, LambdaTest – any WebDriver-compatible endpoint. Same flows, different infrastructure.
┌─────────────────┐
│ core.Driver │ (interface)
└────────┬────────┘
┌─────────────────┼─────────────────┐
▼ ▼ ▼
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ UIAutomator2 │ │ Appium │ │ WDA │
│ (Android) │ │ (cloud) │ │ (iOS) │
└──────────────┘ └──────────────┘ └──────────────┘
All three implement the same core.Driver interface. Your YAML flows don’t know or care which driver runs underneath. The architecture details are in our technical deep-dive, and the performance numbers are in our benchmark post.
Today we’re releasing it under the Apache 2.0 license. Every feature is free. There is no paid tier.
Early Numbers
The architectural choices show up in benchmarks. Here’s a preview against Maestro v1.39.4 running the same 12-flow test suite on a Pixel 7 emulator (API 34):
| Metric | maestro-runner | Maestro | Delta |
|---|---|---|---|
| Avg test time | 14.2s | 34.1s | 2.4x faster |
| Peak memory | 27 MB | 358 MB | 13x less |
| Startup | 0.02s | 4.8s | 240x faster |
| Binary size | 21 MB | ~289 MB | 14x smaller |
Full methodology and raw data in the benchmarks post.
Why We Built It
We love Maestro’s YAML syntax. It’s the best thing to happen to mobile test automation. Simple, readable, version-control friendly.
But the execution engine has real problems. We analyzed the top 100 most-discussed open issues on Maestro’s GitHub (filtered to mobile-only – no macOS, browser, AI, or cloud items). These are the bugs that real teams hit repeatedly in CI pipelines and local development.
maestro-runner addresses 78% of them. 47 through specific code fixes, 31 through architectural decisions that prevent the problems from occurring in the first place. The remaining 22% are mostly feature requests (visual regression, biometrics, video recording) and things that don’t apply to our architecture.
Six Things That Actually Change
Real iOS device support. Issue #686 – 24 comments, open since 2022. maestro-runner supports physical iPhones and iPads out of the box through its WebDriverAgent driver. Pass --team-id and go. See our complete iOS real device guide for setup details.
maestro-runner --platform ios --team-id ABCDE12345 flows/
Parallel execution that works. Not static sharding where one slow device holds up the entire run. maestro-runner uses a shared work queue – faster devices pick up more tests automatically. No device sits idle.
maestro-runner --parallel 3 --auto-start-emulator flows/
Configurable timeouts. The number one category of frustration in Maestro’s issue tracker. maestro-runner lets you set timeouts per-command, per-flow, and globally. Set --wait-for-idle-timeout 0 for apps with continuous animations. Set commandTimeout: 30000 for flows that hit slow APIs.
Error messages you can actually read. Instead of io.grpc.StatusRuntimeException: UNKNOWN, you get element not found: text="Login". Instead of a Java stack trace, you get the flow file, the line number, and what went wrong. The Maestro source code generates errors that tell you about internal gRPC state – maestro-runner generates errors that tell you what to fix.
Cloud provider support. BrowserStack, Sauce Labs, LambdaTest – switch to the Appium driver and point at any provider:
maestro-runner --driver appium \
--appium-url "https://your-cloud/wd/hub" \
--caps caps.json flows/
Smart element finding. React Native apps render text inside non-clickable <View> nodes. Maestro’s element finder often taps the wrong item or misses it entirely – see issues #2480 (regex taps wrong element) and #1275 (ghost elements in hierarchy). maestro-runner uses a three-tier strategy: first, a clickable UiAutomator selector for exact or regex matches. If that misses, a text-exists check confirms the element is in the hierarchy. If the text lives in a non-clickable node, it falls back to page source parsing and walks up the parent chain until it finds a clickable ancestor. The result: taps land on the right element, even in deeply nested React Native or Flutter layouts.
What We Skipped (On Purpose)
maestro-runner does not do biometrics simulation. It does not record video. It does not do visual regression testing. There is no shake simulation, no broadcastReceiver support, no Google Maps marker interaction.
These are the 22% of top-100 issues we deliberately did not address. They are real feature requests from real teams, but they are additive capabilities on top of a working test runner – not the foundation. We focused on the foundation first: reliable element finding, correct input handling, stable device communication, and honest error messages. The extras can come later. The core has to be right from day one.
Getting Started
# Install (macOS, Linux)
curl -fsSL https://open.devicelab.dev/install/maestro-runner | bash
# Android -- just run
maestro-runner flows/
# iOS simulator
maestro-runner --platform ios flows/
# iOS real device
maestro-runner --platform ios --team-id ABCDE12345 flows/
Full documentation: open.devicelab.dev/maestro-runner