# Coming from Maestro

Squiggle flows are close to Maestro's, but a Maestro file doesn't run as it is. Most commands have a direct equivalent with a different name, and a few don't run at all.

## The same flow, both ways

```yaml
appId: com.acme.shop
---
- launchApp
- tapOn:
    id: "email"
- inputText: "dana@example.com"
- tapOn: "Sign in"
- assertVisible: "Welcome back"
```

```yaml
flow: sign in
appId: com.acme.shop
steps:
  - launchApp
  - type: { into: { testID: email }, value: dana@example.com }
  - tap: { text: Sign in }
  - assert: { visible: { text: Welcome back } }
```

A Squiggle flow is one YAML document: a `flow` name, the header keys, then `steps`. There’s no `---` separator.

## Commands

| Maestro | Squiggle |
| --- | --- |
| `tapOn` | tap, with a selector: { text: … } or { testID: … } |
| `tapOn: { id: … }` | tap: { testID: … } |
| `doubleTapOn · longPressOn` | doubleTap · longPress |
| `inputText` | type: { into: <selector>, value: … } |
| `assertVisible · assertNotVisible` | Accepted with a selector mapping, or assert: { visible: … } |
| `extendedWaitUntil` | waitFor, or scrollUntilVisible for a control |
| `waitForAnimationToEnd` | waitFor: { animationIdle: true } |
| `swipe · scroll · scrollUntilVisible` | The same names |
| `launchApp (clearState)` | launchApp: { clearState: true } |
| `stopApp · back · pressKey · openLink` | The same names |
| `runFlow · repeat · retry · when · optional · label` | The same names |
| `appId · env · tags` | The same keys, in the flow header |
| `index` | index (from 0), or nth (from 1) |

> **Directions are lowercase**
>
> Write `direction: left`, not `LEFT`. And check which way each step moves: `scroll: down` moves the content down. See [Gestures and scrolling](https://squiggle.sh/docs/flows/gestures).

## What Squiggle doesn’t run

These are read without an error and reported as `unsupported` in the run. They never count as passed, so a moved suite shows exactly which parts aren’t tested:

- `eraseText`, `copyTextFrom`, `pasteText` and `hideKeyboard`
- `setLocation`, `travel`, `setOrientation`, `setAirplaneMode`, `toggleAirplaneMode`, `addMedia`, `setPermissions` and `clearKeychain`
- `takeScreenshot`, `startRecording` and `stopRecording`
- `runScript` and `evalScript`: Squiggle has no JavaScript engine
- `assertWithAI`, `assertNoDefectsWithAI`, `extractTextWithAI` and `assertScreenshot`

These stop the flow from loading, with an error that names them:

- Position selectors (`below`, `above`, `leftOf`, `rightOf`). Use `within` to look inside another control.
- `containsChild` and state matchers such as `enabled` and `checked`.
- `assertTrue`. Use one of Squiggle’s asserts instead.
- `onFlowStart` and `onFlowComplete`. Use `prerequisite` for setup (see [Repeatable flows](https://squiggle.sh/docs/flows/repeatable)).

## What you get on top

A moved control heals instead of failing (see [Healing](https://squiggle.sh/docs/flows/healing)), and asserts can check what the app did, not only what it shows: renders, dropped frames, store and query state, and logged events (see [Assertions](https://squiggle.sh/docs/flows/assertions)).
