# Run flows

Run a flow from the terminal or Studio, run a whole folder of flows across simulators, and re-run a flow every time you save it.

## Run one flow

```shell
squiggle flow checkout                   # by name, from .squiggle/flows/
squiggle flow ./e2e/checkout.yaml        # by path
squiggle flow - < generated.yaml         # from standard input
squiggle flow checkout --fresh           # relaunch the app first
```

Each step prints as it runs, then the result. When a run fails, it names the failing step and saves a screenshot of the simulator under it. Before running again after a failure, use `--fresh`: the failed run left the app wherever it stopped.

```shell
squiggle flow login
```

Output:

```text
flow login 19 steps · direct · in-process taps

  ✔  0 tap                 tap text=Sign in                         259ms
  ✔  1 type                enter email — type testID=email-input    1.3s
  …
  ✔ 18 assert              Welcome back — 1 assertion(s)               1ms

  ✔ PASS  19 of 19 steps  11.6s
```

In Studio, open the Flows screen and press **Replay** on a flow. Each step’s result appears next to the simulator.

## Re-run on every save

```shell
squiggle watch checkout
```

`watch` keeps the connection to the app open, so each re-run starts at once. If you save during a run, it finishes that run and then runs again, so the app is never left mid-step.

## Run a folder of flows

```shell
squiggle flows ./.squiggle/flows/smoke --shards 4
```

`squiggle flows` runs every flow in a folder and splits them across the booted simulators, so the suite gets faster with each one you add. `--clone-from <udid>` clones a simulator to make more. `--agentic` or `--scripted` runs one kind of flow.

## Why runs are fast

Most test runners sleep after every step, long enough for the slowest screen. Squiggle watches the app, and moves on as soon as it stops moving:

This needs the app launched with Squiggle attached (Studio and `squiggle up` do it). Without it, flows still run, but nothing in the app answers when Squiggle asks whether it has stopped moving: each wait moves on after three unanswered checks, so a step can act while a screen is still animating. The [Run settings](https://squiggle.sh/docs/run/settings) page lists the flags that change how steps are delivered and how long they wait.

> **Release builds**
>
> The SDK does nothing in a Release build unless you set `EXPO_PUBLIC_SQUIGGLE_ALLOW_RELEASE=1` when you build. It is read at build time, so a store build without it stays inert. A Release build then connects only to the same Mac; `EXPO_PUBLIC_SQUIGGLE_ALLOW_REMOTE=1` allows other addresses.

## More

- [Run in CI](https://squiggle.sh/docs/run/ci): Licence token, JUnit results, exit codes and agentic flows.
- [The report card](https://squiggle.sh/docs/run/card): Check a change: its flows, budgets, renders and requests.
- [Start a screen from a template](https://squiggle.sh/docs/run/templates): A new screen with its flow, controls and budget.
- [Benchmark a flow](https://squiggle.sh/docs/run/bench): See where a run spends its time, and catch it getting slower.
- [Run settings](https://squiggle.sh/docs/run/settings): Flags that change how steps run, and per-flow config.
