Maestro is a mobile UI testing framework built by mobile.dev that simplifies end-to-end testing. But its documentation is spread across multiple pages. Commands aren’t fully documented. Flags are mentioned in examples but never explained.

This is the complete reference. Every command, every flag, every config option.

Installation

macOS / Linux

bash
curl -Ls "https://get.maestro.mobile.dev" | bash

Add to your PATH:

bash
export PATH="$PATH":"$HOME/.maestro/bin"

Windows (WSL Required)

Maestro doesn’t run natively on Windows. You need Windows Subsystem for Linux:

  1. Install WSL2:
powershell
wsl --install
  1. Open Ubuntu terminal and install Maestro:
bash
curl -Ls "https://get.maestro.mobile.dev" | bash
  1. Connect ADB to Windows:
bash
export ADB_SERVER_SOCKET=tcp:host.docker.internal:5037

Verify Installation

bash
maestro --version

Core Commands

maestro test

Run one or more flows.

bash
# Run a single flow
maestro test flow.yaml

# Run all flows in a directory
maestro test flows/

# Run specific flows
maestro test flow1.yaml flow2.yaml flow3.yaml

Essential Flags

Flag Description Example
--app-path Path to app binary --app-path ./app.apk
--format Output format (junit) --format junit
--output Report output directory --output ./reports
--env Set environment variable --env USERNAME=test
--device Target specific device --device emulator-5554
--debug-output Save debug artifacts --debug-output ./debug
--continuous Watch mode, re-run on changes --continuous
--include-tags Run flows with specific tags --include-tags smoke
--exclude-tags Skip flows with specific tags --exclude-tags slow

App Path Flag

The --app-path flag tells Maestro where to find your app binary:

bash
# Android APK
maestro test --app-path ./app/build/outputs/apk/debug/app-debug.apk flow.yaml

# iOS Simulator App
maestro test --app-path ./build/MyApp.app flow.yaml

# iOS IPA (for real devices - limited support)
maestro test --app-path ./build/MyApp.ipa flow.yaml

If --app-path is not specified, Maestro assumes the app is already installed on the device.

Report Generation

Generate JUnit-compatible reports for CI integration:

bash
maestro test --format junit --output ./test-results flows/

This creates report.xml in JUnit format, compatible with:

  • GitHub Actions
  • Jenkins
  • GitLab CI
  • CircleCI
  • Azure DevOps

For detailed report options, see Maestro Test Reports: JUnit, HTML, Allure.

Environment Variables

Pass variables to your flows:

bash
maestro test --env USERNAME=testuser --env PASSWORD=secret flow.yaml

Access in your flow:

yaml
- inputText: ${USERNAME}
- inputText: ${PASSWORD}

Continuous Mode

Watch for file changes and re-run tests:

bash
maestro test --continuous flow.yaml

Useful during flow development. Press Ctrl+C to stop.

maestro studio

Launch the visual element inspector.

bash
maestro studio

Opens in your browser at http://localhost:9999. Features:

  • Live device screen view
  • Element hierarchy inspector
  • Accessibility ID viewer
  • Click-to-generate commands
  • Real-time flow execution

Studio Flags

Flag Description Example
--device Target specific device --device emulator-5554
--port Custom port --port 8080

maestro cloud

Run tests on Maestro Cloud infrastructure.

bash
maestro cloud --app-file ./app.apk flows/

Cloud Flags

Flag Description Example
--app-file App binary to upload --app-file ./app.apk
--app-binary-id Use previously uploaded app --app-binary-id abc123
--android-api-level Android API version --android-api-level 33
--ios-version iOS version --ios-version 17
--device-locale Device locale --device-locale ja_JP
--include-tags Run specific tags --include-tags regression
--name Upload name --name "Nightly Run"
--async Don’t wait for results --async

Cloud Pricing

Maestro Cloud costs $250/device/month for unlimited test runs. The 3-minute execution limit on free tier makes it unsuitable for comprehensive test suites.

maestro record

Record interactions and generate flow YAML.

bash
maestro record output.yaml

Captures:

  • Taps
  • Swipes
  • Text input
  • Back button presses

Limitation: Recording doesn’t capture assertions. You’ll need to add assertVisible commands manually.

maestro download-samples

Download example flows:

bash
maestro download-samples

Creates a samples/ directory with flows for:

  • Android Contacts app
  • iOS Contacts app
  • Wikipedia Android app

Useful for learning Maestro syntax.

maestro hierarchy

Print the current view hierarchy:

bash
maestro hierarchy

Outputs the element tree in text format. Useful for debugging when Studio isn’t available.

maestro start-device

Launch an emulator/simulator:

bash
# Android
maestro start-device --platform android --api-level 33

# iOS
maestro start-device --platform ios --ios-version 17

maestro login

Authenticate with Maestro Cloud:

bash
maestro login

Opens browser for authentication. Credentials saved to ~/.maestro/.

Required before using --analyze or cloud features.

AI Analysis (Beta)

Maestro’s AI analysis feature reviews your test results and provides insights.

bash
maestro test --analyze flows/

Generates an HTML report with:

  • Spelling and grammar issues in your app
  • Internationalization problems
  • UI consistency issues
  • Potential bugs detected from screenshots

Requirements:

  • Must be logged in (maestro login)
  • Beta feature — results should be validated

Disable Analysis Notification

bash
export MAESTRO_CLI_ANALYSIS_NOTIFICATION_DISABLED=true
maestro test flows/

Configuration File: config.yaml

Create config.yaml in your workspace root to configure test execution.

Basic Structure

yaml
# config.yaml
flows:
  - "*"              # Include all flows in root
  - "smoke/*"        # Include smoke directory
  - "!regression/*"  # Exclude regression directory

executionOrder:
  continueOnFailure: true  # Continue if a flow fails (default: true)
  flowsOrder:
    - login
    - dashboard
    - checkout
    - logout

Flow Inclusion Patterns

yaml
flows:
  - "*"                    # All flows in root directory
  - "subFolder/*"          # All flows in subFolder
  - "**/*"                 # All flows recursively
  - "!slow/*"              # Exclude slow directory
  - "smoke/login.yaml"     # Specific flow

Execution Order

By default, Maestro runs flows in arbitrary order. To specify order:

yaml
executionOrder:
  continueOnFailure: false  # Stop on first failure
  flowsOrder:
    - setup              # Runs first
    - test_feature_a
    - test_feature_b
    - teardown           # Runs last

Flow names can be:

  • Filename without extension: login (for login.yaml)
  • Flow name from YAML: name: Login Flow

Environment Variables

yaml
env:
  BASE_URL: https://staging.example.com
  API_KEY: ${API_KEY}  # Read from system environment

Tags

Define tags in your flows:

yaml
# login.yaml
tags:
  - smoke
  - auth
appId: com.example.app
---
- launchApp
- tapOn: "Login"

Run specific tags:

bash
maestro test --include-tags smoke flows/
maestro test --exclude-tags slow flows/

Flow YAML Reference

Minimal Flow

yaml
appId: com.example.app
---
- launchApp
- tapOn: "Get Started"
- assertVisible: "Welcome"

Flow with Metadata

yaml
appId: com.example.app
name: Login Flow
tags:
  - smoke
  - critical
env:
  TIMEOUT: 5000
---
- launchApp
- tapOn: "Login"

Common Commands

Command Description Example
launchApp Start the app - launchApp
tapOn Tap element - tapOn: "Button"
inputText Type text - inputText: "hello"
assertVisible Check element visible - assertVisible: "Welcome"
assertNotVisible Check element hidden - assertNotVisible: "Error"
swipe Swipe gesture - swipe: { direction: "up" }
scroll Scroll to element - scroll
back Press back button - back
hideKeyboard Dismiss keyboard - hideKeyboard
waitForAnimationToEnd Wait for animations - waitForAnimationToEnd
takeScreenshot Capture screenshot - takeScreenshot: "checkout"
runFlow Run another flow - runFlow: login.yaml

Selectors

yaml
# By text (default)
- tapOn: "Submit"

# By ID
- tapOn:
    id: "submit_button"

# By accessibility ID
- tapOn:
    accessibilityId: "Submit Button"

# By index (multiple matches)
- tapOn:
    text: "Item"
    index: 0

# With timeout
- tapOn:
    text: "Loading Complete"
    timeout: 10000  # 10 seconds

Conditional Logic

yaml
- runFlow:
    when:
      visible: "Skip Tutorial"
    file: skip_tutorial.yaml

JavaScript Injection

yaml
- evalScript: |
    const timestamp = Date.now();
    output.timestamp = timestamp;
- inputText: ${output.timestamp}

Common Errors and Fixes

“No devices found”

Error: No devices found

Fix: Start an emulator/simulator or connect a device:

bash
# Android
emulator -avd Pixel_6_API_33

# iOS
open -a Simulator

Verify connection:

bash
adb devices        # Android
xcrun simctl list  # iOS

“App not installed”

Error: App com.example.app is not installed

Fix: Either install the app first or use --app-path:

bash
# Install manually
adb install app.apk

# Or use --app-path
maestro test --app-path ./app.apk flow.yaml

“Element not found”

Error: Unable to find element with text "Button"

Fixes:

  1. Use maestro studio to verify the element text/ID
  2. Add timeout: - tapOn: { text: "Button", timeout: 10000 }
  3. Wait for animations: - waitForAnimationToEnd
  4. Check if element is in a scrollable container

For more on flaky tests, see Maestro Flakiness: A Code Deep-Dive.

“Flow timeout”

Error: Flow execution timed out

Fix: Increase the flow timeout in config or environment:

bash
export MAESTRO_FLOW_TIMEOUT=600000  # 10 minutes

“Could not launch app”

Error: Could not launch app com.example.app

Fixes:

  1. Verify appId matches your app’s package name
  2. Check app is installed: adb shell pm list packages | grep example
  3. Clear app data: adb shell pm clear com.example.app

CI/CD Integration

GitHub Actions

yaml
name: Maestro Tests

on: [push, pull_request]

jobs:
  test:
    runs-on: macos-latest
    steps:
      - uses: actions/checkout@v4

      - name: Install Maestro
        run: curl -Ls "https://get.maestro.mobile.dev" | bash

      - name: Start Simulator
        run: |
          xcrun simctl boot "iPhone 15"

      - name: Run Tests
        run: |
          export PATH="$PATH":"$HOME/.maestro/bin"
          maestro test --format junit --output ./results flows/

      - name: Upload Results
        uses: actions/upload-artifact@v4
        with:
          name: test-results
          path: ./results/

For full CI/CD setup, see Maestro CI/CD: GitHub Actions & Jenkins.

Jenkins

groovy
pipeline {
    agent any
    stages {
        stage('Install Maestro') {
            steps {
                sh 'curl -Ls "https://get.maestro.mobile.dev" | bash'
            }
        }
        stage('Run Tests') {
            steps {
                sh '$HOME/.maestro/bin/maestro test --format junit flows/'
            }
        }
    }
    post {
        always {
            junit 'report.xml'
        }
    }
}

Running Maestro on Your Own Devices

Maestro Cloud costs $250/device/month. For a 10-device setup, that’s $30,000/year.

Alternative: Run Maestro on devices you own.

Direct Device Connection

Maestro works with any connected device:

bash
# List connected devices
adb devices

# Run on specific device
maestro test --device emulator-5554 flow.yaml

Parallel Execution

Run on multiple devices simultaneously:

bash
# Terminal 1
maestro test --device emulator-5554 flows/

# Terminal 2
maestro test --device emulator-5556 flows/

Scaling Beyond Local

For distributed device labs without cloud costs, tools like DeviceLab connect your own devices into a managed grid. Run Maestro flows across your entire device fleet at $99/device/month — or free if you’re running everything locally.

For real iOS testing setup, see Maestro on Real iOS Devices: The Complete Guide.

Quick Reference Card

bash
# Run tests
maestro test flow.yaml
maestro test --app-path ./app.apk flows/
maestro test --format junit --output ./results flows/
maestro test --include-tags smoke flows/
maestro test --continuous flow.yaml

# Development
maestro studio
maestro record output.yaml
maestro hierarchy

# Cloud
maestro login
maestro cloud --app-file ./app.apk flows/
maestro test --analyze flows/

# Device management
maestro start-device --platform android --api-level 33

Missing a command or flag? Check out the Maestro vs Appium comparison if you’re evaluating options.