Maestro CLI 2.0.0 Release Notes, Java 17, GraalJS

Why is it called 2.0?

“Isn’t this just another release?”
Not exactly.
But to understand why Maestro 2.0 is such a major thing, we need to go back to the beginning.


The Journey So Far: Why Maestro Exists

When Maestro first launched, the mobile testing landscape was broken. Teams were trapped between two bad options: clunky UI automation tools that required endless maintenance, or writing brittle code-based tests that broke with every UI change.
The problem was clear: Mobile teams needed a testing solution that was both powerful enough for complex scenarios and simple enough that anyone could write and maintain their tests. They needed something that could adapt to fast-moving projects instead of slowing them down.
Maestro’s mission was born from this frustration: Create a testing framework that feels natural to write, runs reliably across devices, and actually helps teams ship better apps faster.

And it worked. Maestro was adopted by thousands of teams because it solved real problems:


Maestro 2.0: A New Era Begins

Consider this release as Maestro getting ready for the next step.

⚠️ Action required

Before you upgrade:


Java 17: A Modern Foundation

“Why is updating Java such a big deal? Up until now, I’ve been managing Maestro well!”
Java 17 removes the technical barriers that were holding Maestro back. This modern foundation unlocks features that older Java versions simply can’t support.

⚠️ Heads-up: Before using Maestro 2.0.0, update to Java 17+ if you're using Java 16 or below.


Default JavaScript Engine is now GraalJS

“Wait… JavaScript engine? I didn’t even know Maestro had one!”
Sure, it does. Up until now, Rhino, a JavaScript engine that stopped evolving years ago, was in charge of it. Teams constantly hit walls: modern JavaScript syntax didn’t work and debugging was a nightmare.
The adoption of GraalJS was made possible by Java 17, and it is now the default engine in Maestro 2.0.0.

The problems Rhino created:

GraalJS changes everything:

Here’s what’s now possible:

# Modern JavaScript that actually works
- inputText: ${user?.name ?? 'Anonymous'}
- assertVisible: ${items.filter(item => item.active).length > 0 ? 'Active Items' : 'No Items'}

If you need the old engine for legacy scripts, you can still switch back:

appId: com.example.app
jsEngine: rhino

Meet Maestro Studio Desktop 🖥️

“Why is it so difficult to create tests? Why do I have to keep switching between the emulator, studio web and code editor?”
This highlighted a bigger issue: Writing Maestro tests had an unnecessary learning curve, and the constant context switching between tools made building, maintaining, and debugging tests frustrating and inefficient.
Write, maintain, and debug your tests at a single using Maestro Studio Desktop, where test development becomes intuitive. Test generation is no longer a technical challenge. Maestro Studio Desktop makes it a simple, visually appealing & intuitive process that team members with and without technical expertise can use efficiently.

The Desktop app is currently in beta. If you are looking to simplify your testing workflow, do give it a try! We’ll love to get your feedbacks and improve Studio Desktop. Download Maestro Studio Desktop - Beta →


First step into WEB TESTING 🎉

Web testing support has been our most requested feature, with users asking: “When will Maestro support web testing?”
The wait is over. We’re excited to introduce web testing capabilities as our first step into expanding beyond mobile.
What’s new:
1. Run Multiple Web Flows with one command
“Mobile flows could always run together… but web?”
Now, yes. With Maestro 2.0, you can run your entire web workspace in a single command:

# You can now run entire web workspaces
maestro test workspace_containing_multiple_web_flows

2. Clearer Web Flow Configuration:
“Why is Maestro thinking my web test belongs to some random app?”
That’s what can happen when you define a web flow using appId, sometimes it guesses wrong.Web flows now explicitly require to use url instead of the confusing appId field.

url: https://maestro.mobile.dev
---
- launchApp
- assertVisible: "Welcome to Maestro"

⚠️ Still using appId in your web flows? Time to switch to url
Web testing in Maestro is currently at its early stages. While the core functionality works, we’re still optimizing and expanding capabilities. We will be learning from early adopters and continuously improving the experience.


New Command: setOrientation

“Ever had to rotate your device mid-test just to see if the UI breaks?”
This seemingly simple problem highlighted a bigger issue: Maestro couldn’t adapt to how real users actually interact with apps. Users rotate their devices constantly, but tests were locked to a single orientation.
You now get complete orientation control within your tests

appId: com.example.maestro.orientation
---
- launchApp
- setOrientation: LANDSCAPE_LEFT
- assertVisible: "Landscape Layout"
- setOrientation: PORTRAIT
- assertVisible: "Portrait Layout"

Supports:

appId: com.example.maestro.orientation
---
- launchApp
- setOrientation: LANDSCAPE_LEFT

MCP: AI That Actually Helps

MCP brings AI-powered testing that could understand your app, understand your test scenarios, look at the screens and accordingly generate meaningful test.
The change in 2.0:


Own your Artifacts

“Where did that screenshot go? Wait… where are the logs?!”
When tests failed in CI, teams often spent extra minutes searching for the right screenshot or log file after a failed test. While not a critical blocker, it was still a distraction.
The solution: Complete control over your test output. Pick where screenshots, logs and AI reports go with testOutputDir or --test-output-dir.

# In config.yaml
testOutputDir: your_maestro_output_directory

# Or via CLI
maestro test workspace --test-output-dir=your_maestro_output_directory

Other Notables

A couple of smaller changes that still make a big difference:


🚀 Quick upgrade checklist

  1. Check Java version
java -version
  1. Install or switch to Java 17
  2. Update Maestro to 2.0.0
  3. If you used Rhino-specific JS, either update scripts or set jsEngine: rhino temporarily

Why Maestro 2.0 Matters

Recently, a Maestro team informed us of their “JavaScript incident.” After months of successfully running tests, they made the decision to update their test logic using some ES2020 features. Suddenly, half their flows were failing with cryptic Rhino errors. After hours of debugging, they discovered that the engine was the problem, not their reasoning.
Sometimes the most important releases are the ones that simply remove the friction you didn’t realize was there.