Maestro
Use when running mobile E2E on React Native / iOS / Android, recording user flows, inspecting view hierarchy, or hunting flaky UI tests with Maestro. Multi-environment via MAESTRO_PROFILE.From its SKILL.md
npx -y skills add tuannv14/claude-team-toolkit --skill maestroAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
4 things to look at
- reads credentialsReads from 2 credential sources: `~/.maestro/profiles.ini` and 1 more.
- 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
- runs commandsInstructs the agent to run 8 commands, including `curl -Ls "https://get.maestro.mobile.dev" | bash` and 7 more.
- fetches URLsInstructs the agent to fetch 1 URL, including https://get.maestro.mobile.dev.
SKILL.md
6.2 KB, ~1.6k tokens by cl100k_base, as published. Nobody here has run it
/maestro — mobile E2E (YAML, multi-env)
Wraps maestro test. Profiles = device + app build per environment.
Profile resolution: --profile → MAESTRO_PROFILE → ~/.maestro/active_profile → [default].
Overview
Wraps maestro test for mobile E2E. Flows are declarative YAML — testers can read/write them without coding. Profiles bind a device + app build per environment. Includes flaky-test detection across multiple JUnit runs.
When to Use
- Mobile E2E flows on iOS / Android / React Native
- Recording new flows interactively (no coding required)
- Inspecting accessibility hierarchy to find selectors
- Detecting flaky tests across multiple runs (JUnit XML diff)
- Cloud-based device farm runs (Maestro Cloud)
When NOT to Use
- Pure unit / component tests → Jest / JUnit, not E2E
- Non-mobile (web, desktop) → wrong tool
- Performance / load tests → use k6 or Detox
- Personal phones (Maestro can hit any UI element including OS dialogs — dedicated test devices only)
Dependencies
curl -Ls "https://get.maestro.mobile.dev" | bash # macOS / Linux
# Windows: scoop install maestro (or use WSL)
maestro --version
iOS: Xcode + simulator. Android: Android Studio + emulator.
Profile config
~/.maestro/profiles.ini (mode 600 — may contain Cloud key):
[default]
platform = ios # ios | android
device = iPhone 15
app_id = com.example.app
flows_dir = .maestro
[android-emu]
platform = android
device = Pixel_7_API_34 # AVD name
app_id = com.example.app
flows_dir = .maestro
[staging-cloud]
platform = android
device = R5XY... # serial of physical device
app_id = com.example.app.staging
flows_dir = .maestro
cloud_api_key = xxxxxxxxxxxxxxxxxxxxxxxx # Maestro Cloud
Helpers
Shared profile/INI/
ctt_*pattern reference: profiles-and-credentials.
source "$HOME/.claude-team-toolkit/lib/credentials.sh"
ctt_load_creds maestro "$PROFILE"
# Verify device reachable
case "$CTT_PLATFORM" in
ios) xcrun simctl list devices "$CTT_DEVICE" | grep -q Booted || xcrun simctl boot "$CTT_DEVICE" ;;
android) adb devices | grep -q "$CTT_DEVICE" || { echo "Device not connected" >&2; return 1; } ;;
esac
Dispatch
run <flow.yaml> [--continuous]
ARGS=()
[ "$CONTINUOUS" = "true" ] && ARGS+=(--continuous)
maestro test "${ARGS[@]}" "$FLOW"
--continuous re-runs on file changes — great for authoring.
run-all [--tags smoke,critical]
maestro test "$CTT_FLOWS_DIR/" \
${TAGS:+--include-tags "$TAGS"} \
--format junit --output /tmp/maestro-results/
record <flow.yaml> — interactive flow recorder
maestro record "$FLOW"
Point/tap to record actions → save as YAML. Tester-friendly (no coding).
studio — visual flow editor (browser-based)
maestro studio
inspect [--app <bundle-id>] — view hierarchy
maestro hierarchy --app "${APP_ID:-$CTT_APP_ID}"
Find element selectors / accessibility IDs.
tags — list all tags used in flows
grep -h "^tags:" -A 20 "$CTT_FLOWS_DIR"/*.yaml | grep "^- " | sort -u
flaky-report [--last N] — detect flaky tests from JUnit results
LAST="${LAST:-10}"
ls -t /tmp/maestro-results/*.xml | head -n "$LAST" | xargs python3 -c '
import sys, xml.etree.ElementTree as ET
from collections import defaultdict
results = defaultdict(list)
for f in sys.argv[1:]:
for tc in ET.parse(f).iter("testcase"):
failed = tc.find("failure") is not None or tc.find("error") is not None
results[tc.get("name")].append(failed)
print("Flaky tests (passed AND failed across runs):")
for n, runs in results.items():
if any(runs) and not all(runs):
print(f" {n}: {sum(runs)}/{len(runs)} fail rate")
'
cloud upload <flow-or-folder> [--name <run-name>] — Maestro Cloud
[ -z "$CTT_CLOUD_API_KEY" ] && { echo "Set cloud_api_key in profile" >&2; return 1; }
maestro cloud --apiKey "$CTT_CLOUD_API_KEY" \
${NAME:+--name "$NAME"} \
"$APP" "$FLOW_OR_FOLDER"
<app> for cloud is the build artifact (.app/.ipa/.apk), not bundle ID.
from-xlsx <xlsx-path> — scaffold from xlsx test cases
Delegates to xlsx-testcases gen maestro — see that skill.
Flow patterns (cheat sheet)
# Common actions
- launchApp
- tapOn: "Submit" # by text
- tapOn:
id: "submit-btn" # by accessibility id
- inputText: "${EMAIL}"
- assertVisible: "Welcome"
- assertNotVisible: "Login"
- waitForAnimationToEnd
- extendedWaitUntil: { visible: "Loaded", timeout: 30000 }
- scrollUntilVisible: { element: "Footer", direction: DOWN }
- runFlow: { file: ../subflows/login.yaml }
Variables via env: [email protected] maestro test flow.yaml. Inside YAML: ${EMAIL}.
Common Mistakes
- Hard-coding credentials in YAML → leak on commit. Use
${ENV_VAR}placeholders. - Selectors by text only → fragile across translations. Prefer
id:(accessibility ID). - Running on real personal devices instead of simulators / test devices
- Writing one mega-flow instead of small subflows +
runFlow:composition - Cloud uploads need build artifact (
.app/.ipa/.apk), not bundle ID - "Flaky test" verdict on first run → need ≥5 runs to distinguish flake from broken
Safety
- Never commit credentials in flow YAML. Use
${ENV_VAR}+ document required vars in flow comment. - Cloud API key per-account — limited blast radius. Prefer CI-scoped key.
- Physical devices: Maestro can interact with anything on screen including OS dialogs. Run only on dedicated test devices, never personal phones.
- Recordings capture screen — don't record flows with real user data / prod accounts.
Layout
.maestro/
├── config.yaml # global config
├── subflows/{login,grant-perms}.yaml
├── smoke/{launch,home-tabs}.yaml
├── regression/...
└── iap/...
What ships with it
Read from the repository
Just SKILL.md. No reference files, no scripts.
Gives 0 of the 12 instructions most test skills give in ~1.6k tokens
Counted across 1,201 of the 2,096 authors here whose files we hold, read 2026-09-06
- Write a failing test before writing codein 43 of 1201, across 36 files
- Run the full test suitein 36 of 1201, across 35 files
- Test only one variable per experimentin 34 of 1201, across 17 files
- Read product marketing context before asking questionsin 34 of 1201, across 14 files
- Mock external dependenciesin 34 of 1201, across 30 files
- Define primary, secondary, and guardrail metricsin 33 of 1201, across 16 files
- Pre-determine sample size before startingin 31 of 1201, across 14 files
- Test behavior rather than implementationin 31 of 1201, across 29 files
- Formulate a hypothesis before designing a testin 30 of 1201, across 13 files
- Document every test hypothesis, variant, and resultin 29 of 1201, across 11 files
- Use descriptive test function namesin 25 of 1201, across 21 files
- Commit to the methodology without stopping earlyin 24 of 1201, across 8 files
Said here and by no other author read
- use dedicated test devices only
- use accessibility IDs instead of text selectors
- compose flows using small subflows
- verify device connectivity before running tests
- run tests on simulators or emulators
- use Maestro Cloud for device farm runs
Grouped from the skills themselves: near-identical wordings counted once, and counted by distinct author, so one author publishing three of these counts once. Length counted with cl100k_base; the agent that loads this file may tokenize it differently.