# How to Test Maestro YAML Configurations Locally: CLI and Validation Guide

> Easily test Maestro YAML configurations locally using the maestro test CLI or Studio server's dry-run endpoint. Validate syntax and run tests against emulators, simulators, or browsers with this essential guide.

- Repository: [Maestro/Maestro](https://github.com/mobile-dev-inc/Maestro)
- Tags: how-to-guide
- Published: 2026-03-20

---

**You can test Maestro YAML configurations locally using the `maestro test` CLI command against an emulator, simulator, or browser, or validate syntax without a device using the Studio server's dry-run endpoint.**

Maestro is an open-source mobile UI testing framework by mobile-dev-inc that lets you write test flows in human-readable YAML. Whether you are iterating on a single flow or running a full regression suite against a local device, the CLI provides multiple ways to test Maestro YAML configurations locally without requiring cloud infrastructure.

## Installing the Maestro CLI

Before testing flows locally, install the Maestro command-line tool. The installation script downloads the latest binary and adds it to your path.

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

```

Verify the installation by checking the version:

```bash
maestro --version

```

## Running Flows Against Local Devices

The primary way to test Maestro YAML configurations locally is through the `maestro test` command, implemented in [`TestCommand.kt`](https://github.com/mobile-dev-inc/Maestro/blob/main/TestCommand.kt). This entry point orchestrates the entire execution pipeline: parsing your YAML, planning the run, connecting to the device, and reporting results.

### Single Flow Execution

To run a single YAML file on a connected emulator, simulator, or browser:

```bash
maestro test path/to/your/flow.yaml

```

Under the hood, `TestCommand` invokes `TestRunner.runSingle`, which parses the file using `MaestroFlowParser` and executes each `MaestroCommand` against the device session created by `MaestroSessionManager`.

### Batch Execution with Folders

You can test multiple flows by pointing the CLI at a directory or using glob patterns:

```bash

# Run all YAML files in a directory

maestro test path/to/flows/

# Run with specific output format

maestro test path/to/flow.yaml --format HTML_DETAILED --output report.html

```

When targeting a folder, `WorkspaceExecutionPlanner.plan` (defined in [`WorkspaceExecutionPlanner.kt`](https://github.com/mobile-dev-inc/Maestro/blob/main/WorkspaceExecutionPlanner.kt)) resolves the file set, handles sub-flows, and applies tag filters to build an `ExecutionPlan` before execution begins.

### Capturing Debug Output

For troubleshooting failed tests, use the `--debug-output` flag to preserve device logs and screenshots:

```bash
maestro test path/to/flow.yaml --debug-output ./debug

```

The [`TestDebugReporter.kt`](https://github.com/mobile-dev-inc/Maestro/blob/main/TestDebugReporter.kt) file manages this directory, cleaning old files and organizing artifacts by test run.

## Validating YAML Syntax Without a Device

You do not need a running emulator to validate that your YAML is syntactically correct. Maestro's Studio server provides a **dry-run** mode that parses the flow without executing commands.

### Using the Studio Server API

The dry-run logic lives in [`DeviceService.kt`](https://github.com/mobile-dev-inc/Maestro/blob/main/DeviceService.kt). While the CLI does not expose a dedicated dry-run flag, you can validate YAML by starting the Studio server and hitting the `run-command` endpoint:

```bash
curl -X POST http://localhost:3000/api/run-command \
     -H "Content-Type: application/json" \
     -d '{"yaml":"- launchApp","dryRun":true}'

```

The server uses `MaestroFlowParser` to convert the YAML string into a list of `MaestroCommand` objects and returns the parsed structure, allowing you to catch syntax errors early without device interaction.

## Advanced Local Testing Options

The `maestro test` command supports several options for complex local testing scenarios, all parsed in [`TestCommand.kt`](https://github.com/mobile-dev-inc/Maestro/blob/main/TestCommand.kt):

- **`--config <file>`**: Supply a workspace-level [`config.yaml`](https://github.com/mobile-dev-inc/Maestro/blob/main/config.yaml) to set default values like `appId` or environment variables.
- **`--include-tags <list>` / `--exclude-tags <list>`**: Filter which flows to run based on custom tags defined in your YAML metadata.
- **`--shard-split N`**: Distribute flows across **N** connected devices, splitting the suite evenly.
- **`--shard-all N`**: Run the complete flow suite on each of **N** connected devices simultaneously.
- **`--continuous`**: Keep the session alive and automatically re-run flows when file changes are detected, enabling rapid iteration.
- **`--headless`**: For web flows, launch the browser without a visible window.
- **`--screen-size WxH`**: Specify dimensions for headless browser testing (e.g., `1920x1080`).

Example with tags and sharding:

```bash
maestro test flows/ --include-tags smoke --shard-split 2

```

## Understanding the Internal Execution Flow

Testing locally involves four distinct phases implemented across the Maestro codebase.

### 1. Parsing with MaestroFlowParser

First, your YAML is converted into executable commands. In [`MaestroFlowParser.kt`](https://github.com/mobile-dev-inc/Maestro/blob/main/MaestroFlowParser.kt), the `parseCommand` method handles this transformation:

```kotlin
// maestro-orchestra/src/main/kotlin/maestro/orchestra/yaml/MaestroFlowParser.kt
val commands = MaestroFlowParser.parseCommand(Paths.get(""), "", yamlString)

```

This produces a list of `MaestroCommand` objects that represent actions like `launchApp`, `tapOn`, or `assertVisible`.

### 2. Planning with WorkspaceExecutionPlanner

For multi-flow runs, [`WorkspaceExecutionPlanner.kt`](https://github.com/mobile-dev-inc/Maestro/blob/main/WorkspaceExecutionPlanner.kt) builds an execution plan that respects your directory structure and tag filters:

```kotlin
val executionPlan = WorkspaceExecutionPlanner.plan(
    input = setOf(Paths.get("flow1.yaml"), Paths.get("subfolder")),
    includeTags = listOf("smoke"),
    excludeTags = emptyList(),
    config = Paths.get("config.yaml")
)

```

### 3. Execution with TestRunner

Finally, [`TestRunner.kt`](https://github.com/mobile-dev-inc/Maestro/blob/main/TestRunner.kt) handles the actual device interaction. For single flows, `runSingle` manages the session, executes commands, and handles reporting:

```kotlin
TestRunner.runSingle(
    maestro = maestro,
    device = device,
    flowFile = File("login_flow.yaml"),
    env = mapOf("USERNAME" to "test"),
    resultView = AnsiResultView(),
    debugOutputPath = debugPath,
    analyze = false,
    apiKey = null,
    testOutputDir = null,
    deviceId = null
)

```

For suites, `runMultiple` iterates through the `ExecutionPlan`, executing each flow in sequence or parallel depending on sharding configuration.

## Summary

- **Install** the Maestro CLI using the official install script to get the `maestro test` command.
- **Run single flows** with `maestro test <file.yaml>` or batch test directories to validate complete suites locally.
- **Debug failures** using `--debug-output` to capture screenshots and logs, or generate HTML reports with `--format HTML_DETAILED`.
- **Validate syntax** without a device by using the Studio server's dry-run endpoint at `/api/run-command`.
- **Optimize execution** with sharding (`--shard-split`, `--shard-all`), tag filtering, and continuous mode for rapid local iteration.
- **Key source files**: [`TestCommand.kt`](https://github.com/mobile-dev-inc/Maestro/blob/main/TestCommand.kt) (CLI entry), [`MaestroFlowParser.kt`](https://github.com/mobile-dev-inc/Maestro/blob/main/MaestroFlowParser.kt) (YAML parsing), [`WorkspaceExecutionPlanner.kt`](https://github.com/mobile-dev-inc/Maestro/blob/main/WorkspaceExecutionPlanner.kt) (execution planning), and [`TestRunner.kt`](https://github.com/mobile-dev-inc/Maestro/blob/main/TestRunner.kt) (device execution).

## Frequently Asked Questions

### Can I test Maestro YAML without connecting a device?

Yes. Start the Maestro Studio server and POST to the `run-command` endpoint with `"dryRun": true` in the JSON body. This uses `MaestroFlowParser` to validate syntax without executing commands against a device, as implemented in [`DeviceService.kt`](https://github.com/mobile-dev-inc/Maestro/blob/main/DeviceService.kt).

### How do I run only specific tests from my local workspace?

Use the `--include-tags` and `--exclude-tags` flags with the `maestro test` command. Tags are defined in your YAML file metadata, and `WorkspaceExecutionPlanner` filters the execution plan accordingly before `TestRunner` begins execution.

### What is the difference between `--shard-split` and `--shard-all`?

`--shard-split N` divides your flow suite across **N** connected devices, giving each device a subset of flows to complete the suite faster. `--shard-all N` runs the entire suite on each of **N** devices simultaneously, useful for testing across different device configurations or OS versions.

### Where does Maestro store debug logs and screenshots when testing locally?

When you provide the `--debug-output <path>` flag, [`TestDebugReporter.kt`](https://github.com/mobile-dev-inc/Maestro/blob/main/TestDebugReporter.kt) creates a directory at the specified path containing subdirectories for each flow run with screenshots, device logs, and hierarchy dumps to help diagnose failures.