Flow syntax reference

For AI agents: this page is Markdown at https://squiggle.sh/docs/reference/flow.md. Every docs page is listed at https://squiggle.sh/llms.txt, and all of them are one file at https://squiggle.sh/llms-full.txt.

Every key a flow file can hold. For how to use them, start with Writing flows; this page is for looking things up.

Check flows in your editor

Put this line at the top of a flow file, and editors with YAML support complete keys and flag mistakes as you type. squiggle init adds it to the first flow it writes.

YAML
# yaml-language-server: $schema=https://squiggle.sh/schemas/flow-1.0.0.schema.jsonflow: checkout

Top-level keys

KeyWhat it holds
flowThe name you run the flow by. Required, with steps.
stepsThe list of steps.
appIdThe app’s bundle id. Flows called with runFlow inherit it.
envVariables, used as ${NAME} in any string.
secretsVariables like env, whose values are never written to recordings or run logs.
tagsLabels for the flow. A flow tagged probe measures your tools rather than a screen, and the report card never runs it to cover one.
prerequisiteThe screen the flow starts on: route, reset (auto, scroll, back or relaunch), app, and an optional goal. See Repeatable flows.
healingadaptive (default), strict or lossy-fallback. See Healing.
goalChecks, in the same form as assert, that must hold after the last step.
configRun settings the flow needs: autoScroll, scrollMode, fastSettle, strictAssert, stepDelayFloorMs, transitionSettleMs, and chaos (a bad-network profile, for a flow that tests the error state). See Run settings.
expectFor a flow that exists to catch a known bug: { verdict: fail, failure: <text> }. It passes only by failing with that text.
intent · plan · onStuck · runWithThe form agents write: intent and plan instead of flow and steps. onStuck is escalate or fail. runWith names the command that runs the program, such as squiggle agent branch; squiggle flow refuses one that names another command (E_RUNS_WITH) and squiggle flows lists it with that command instead of running it.

Any other key stops the flow from loading, as does a file that isn’t valid YAML (E_FLOW_PARSE). Quote a value that contains #, such as text: "Order #20": unquoted, YAML reads the rest as a comment.

Options on any step

These go inside the step’s body, for example - tap: { testID: promo-close, optional: true }:

OptionWhat it does
labelNames the step in the report.
optionalThe step may fail without failing the flow.
whenRuns the step only if this condition holds, in the same form as assert.

Steps

Act on a control

StepOptions
tap · doubleTap · longPressA selector. expectRoute names the screen the tap opens.
typeinto (a selector), value, and submit (a key to press after). Replaces whatever the field held.
swipedirection (up, down, left or right) and amount in points, or to: a percentage of the control. Optional selector. duration (50–5000 ms, default about 300) makes the drag slower; hold (1–3000 ms) keeps the finger still first, a long press that becomes a drag, such as reordering a list.
scrolldirection (where the content goes) and amount. Optional selector.
scrollUntilVisibleelement (a selector), direction, maxScrolls (default 15), mode (gesture or direct).

Selector fields are listed on Selectors.

Wait and check

StepOptions
waitForAt least one of route, commitQuiet (React stopped rendering), animationIdle, networkIdle, appRunIdle (a run started elsewhere finished), plus timeout in ms, or auto to use past runs. An app whose JS thread is blocked renders nothing, so commitQuiet and animationIdle read it as settled.
assertOne or more checks. See the table below.
assertVisible · assertNotVisibleA selector. The same as assert: { visible } and { notVisible }.

App and device

StepOptions
launchAppapp, relaunch (ifNeeded by default, or always), clearState (wipes app data and relaunches).
stopAppapp.
backGoes back.
pressKeyA key name, such as Enter or Home.
navigateroute: goes to a screen through your app’s navigator.
openLinkA URL or deep link.
network.stuburlMatch, and the response: status, body, headers, method, delayMs. network.stub: clear removes all stubs. Needs --capture-net.
hideKeyboardReported as unsupported.

Reuse and control

StepOptions
runFlowfile, and env to override its variables.
repeatcommands, and times or while (a condition).
retrycommands and maxRetries.
branchif (a condition), then, and else.
agentA goal, or goal with rounds, timeout and hints. Must be followed by an assert. See Agentic flows.
escalatereason: stops and asks the agent running the flow. Without one, it reports pending.

Assertions

assert, goal, when and branch take these. Numbers compare with lt, lte, gt, gte or eq.

CheckForm
visible · notVisible · exists{ visible: <selector> }
route{ route: OrderConfirmation }
rerenders{ rerenders: { CartRow: { lt: 3 } } }
droppedFrames{ droppedFrames: { lt: 2 } }
store{ store: { useCart.mutationCount: { gte: 1 } } }: a Zustand store by the variable it is declared as, and how many times it changed. { store: { useCart: {} } } checks that it exists.
queryA TanStack Query, its status or fetch count.
log{ log: { contains: … } }, { log: { regex: … } } or { log: { field: …, equals: … } }
action{ action: { checkout.submit: { eq: 1 } } }
visualnoOverlap, noClipping, onScreen, noBlankFrame or legibleContrast, as a name or a list.
memoryDelta{ memoryDelta: { lt: 20MB } }, across the step before. Bytes, or a size in KB, MB or GB.
scroll{ scroll: { fps, droppedFrames, blank, churn, list } }, after a scroll step. Every part is optional: fps and droppedFrames default to the screen’s budget, so scroll: {} is valid.
smooth{ smooth: { region: <selector>, gapFrames, droppedFrames, jsDriven } }, after the step that starts the motion. region is required; droppedFrames defaults to the screen’s budget.
memory · network · gestureAccepted, and reported as pending.

Steps Squiggle reads but doesn’t run

These Maestro commands load without an error and are reported as unsupported: eraseText, copyTextFrom, pasteText, setLocation, travel, setOrientation, setAirplaneMode, toggleAirplaneMode, addMedia, setPermissions, clearKeychain, takeScreenshot, startRecording, stopRecording, runScript, evalScript, assertWithAI, assertNoDefectsWithAI, extractTextWithAI and assertScreenshot. See Coming from Maestro.