flowdeck ui simulator.
Common Flags
Most UI automation commands support:-S, --simulatorto target a specific simulator by name or UDID. Recommended when multiple simulators are booted. Examples:-S "iPhone 16"or-S "A1B2C3D4-...".- For AI agent workflows, always pass
-Sexplicitly on everyflowdeck ui simulator ...command. - If
-Sis omitted, FlowDeck falls back to session/default simulator selection. This is usually fine when only one simulator is booted (common in CI). --json,-jfor machine-readable output.--verbose,-vand--examples,-eon commands that support extra output.
Capture
Query
Interaction
Wait and Assert
Input and Keyboard
App Control
Simulator Hardware Aliases
Simulator hardware and device-state controls are canonical underflowdeck simulator.
Advanced
Batch Flows
ui simulator batch runs a whole UI flow in a single invocation. It spans screens (label/id targets are re-found on the current screen), auto-scrolls to off-screen targets, and verifies values inline with assert — so navigation, input, and verification become one call with no per-action round-trips and no intermediate screenshots. It returns the final accessibility tree (or only the interactive elements with --interactive-elements).
--file path/to/steps.json.
Batch Options
Step Actions
The batch stops at the first failing step. The JSON response includes a
steps[] array with per-step success/error and a final snapshot of the screen after the last step.
batch is the most efficient way to drive a multi-step flow from an agent: one call replaces many tap/type/screen round-trips, and inline assert steps verify state without screenshots.Key Options Explained
Screen and Record
--outputuses a file path. Screenshots default to a.png, recordings to a.mov. If omitted, FlowDeck writes to a temp file and prints the path.screenreturns the accessibility tree by default and captures no image. The tree is the source of truth for what is on screen.--screenshotadds an image to that response. Use it when a value is drawn without accessibility data — custom graphics, charts — or when you need pixel-level layout.--interactive-elementsreturns only the actionable elements instead of the full tree, which is what you want when you are just looking for a tap target.--since-hash <hash>returnsunchangedinstead of the full tree when the screen still matches that hash, so a polling loop costs almost nothing while nothing moves.--optimizeshrinks the screenshot output for AI workflows.--treeis deprecated and accepted only for compatibility. The tree already comes back without it.screenreports size in points; JSON includespoint_width/point_heightandpixel_width/pixel_heightwhen available.--durationis in seconds (supports decimals like2.5).--codecacceptsh264orhevc.--forceoverwrites an existing output file.
Sessions
- Always pass
-S <name-or-udid>onsession startandsession stopto target a specific simulator. Accepts a simulator name (e.g.,"iPhone 16") or raw UDID. This is required when multiple simulators are booted and recommended in all automation workflows. session startcaptures the accessibility tree and checks a persistent simulator framebuffer every 500ms by default. It writes to~/.flowdeck/automation/sessions/<session-short-id>/(the short ID is the first 8 characters of the session UUID).- Starting a session stops and replaces only an existing session for the same simulator. Sessions for other simulators keep running concurrently.
--interval-msand--retention-secondstune capture frequency and retention (default 60s). Retention always keeps at least one capture.- The framebuffer backend skips pixel copying, JPEG encoding, and image writes while its version is unchanged. Entries are written only when the tree or screenshot body changes, and screenshots are stored at 50% JPEG quality. Screenshot change detection ignores the volatile top system/status strip, so Dynamic Island/status-bar churn does not keep rewriting idle frames; saved screenshots are not cropped or masked.
- FlowDeck automatically falls back to the legacy screenshot backend if the private framebuffer interface cannot attach or fails during the session. It prints one warning and keeps that backend for the rest of the session; no manual flag is required.
latest.jsonpoints to the most recent capture,latest.jpgsymlinks to the latest screenshot, andlatest-tree.jsonsymlinks to the latest accessibility tree (no directory listing required).- JSON output from
session startincludes full paths for the session directory, screens, trees, latest pointers, the UDID, and the current screen size in points (screen). Key fields you can parse:session_id— full UUID of the sessionsession_short_id— first 8 characters of the UUID (matches the directory name)session_dir— absolute path to the session’s data directorylatest_screenshot— absolute path to the rollinglatest.jpgfilelatest_tree— absolute path to the rollinglatest-tree.jsonfilecapture_backend—framebuffernormally, orlegacy_screenshotafter automatic fallbackcapture_warning— present only during fallback, withreason,message, andtimestamp_msscreens_dir,trees_dir,root,udid,interval_ms,retention_seconds,pid,owner_pid,screen
session list --jsonreports every active session, includingudid, recorderpid,owner_pid,age_seconds, and the livecapture_backend/capture_warningstate.- Session commands skip malformed active pointer files and reconcile stale pointers for dead recorders, abandoned pending starts, and sessions from a previous system boot, so
list,stop, andstop --allremain usable for recovery. session stopwithout-Sstops the sole active session. If multiple sessions are active, pass-S <name-or-udid>to stop one or--allto stop every active session. JSON output includes the stopped session UDID(s).- Sessions also end automatically if the simulator disappears or if the owner process that started the session exits. Set
FLOWDECK_OWNER_PIDto bind a session to a specific owner process.
Find, Tap, and Double-Tap
- Default (no flag): exact label match.
--by-id: matches accessibility identifiers instead of labels.--by-role: matches element roles (e.g.button,textField).--contains: substring match against labels (only valid alone or with default label mode; do not combine with--by-idor--by-role).--pointexpects a single comma-separated valuex,yin points (matches normalized screenshots and tree output).- Valid:
--point 100,200or--point "100,200". - Invalid:
--point 100 200(space-separated; two arguments will be rejected).
- Valid:
- Do not scale by @2x/@3x or device resolution; use the image coordinates directly.
- Coordinate taps use the provided point exactly; use label/ID taps to target element centers.
--geometryacceptspointsonly.- Session screenshots are normalized to point size so image coordinates map 1:1 to points.
--durationontapis a long-press hold time in seconds.
Swipe and Scroll
swipesupports directionsup,down,left,rightor explicit--from x,y+--to x,y.--durationforswipeis in seconds (default0.3).--distancesets swipe/scroll distance as a fraction of the screen (0.05–0.95), not pixels or points. Defaults: swipe0.4, scroll0.85(≈ one viewport, so each scroll advances a full screen with a small overlap — no duplicated or skipped content).- Example:
--distance 0.5scrolls half the screen height. - Invalid:
--distance 300(FlowDeck will reject values outside 0.05–0.95).
- Example:
scrollreturnsmovedandreached_endin its JSON. Whenreached_endistruethe content didn’t move — you are at the top/bottom; stop scrolling.--directionforscrollusesUP,DOWN,LEFT, orRIGHT(defaultDOWN).--speedis a 0-100 value (higher is faster).--untilscrolls until an element is visible, then returns the settled screen. Useid:myElementto match by accessibility identifier. It early-exits when the content stops moving, so it won’t scroll uselessly to the timeout at the end of a list.--timeoutforscroll --untilis in milliseconds (default20000).tap,type,scroll,swipe,double-tap, andwaitreturn the settled post-action screen (full tree + element refs +screen_hash) under ascreenkey by default — so you don’t need a separate snapshot after each action. Pass--no-screenfor a terse result when you don’t need the tree.
Pinch and Wait
pinchuses a direction argument:in(zoom out) orout(zoom in).--scaleoverrides the zoom factor (defaults to2.0forout,0.5forin).--pointexpectsx,ycoordinates in points for the pinch center.--geometryacceptspointsonly.--durationforpinchis in seconds.--timeoutforwaitis in seconds;--pollis in milliseconds.--gone,--enabled, and--stablechange the wait condition (default is “exists”).
Text, Key, and App Control
type --clearclears the focused field before typing.type --maskhides typed text in terminal output and JSON.erase --characters 5deletes a specific number of characters; omit to clear all.key 40sends a single HID keycode (for example,40= Enter).key --sequence 11,8,15sends comma-separated HID keycodes.key --hold 1.0holds a single key for the given seconds.- Pass either a positional keycode (e.g.
key 40) or--sequence, not both. open-urlacceptshttps://...or custom schemes likemyapp://path.clear-staterequires a bundle identifier (for examplecom.example.app) and resets the simulator container for that app.rotate <angle>performs a two-finger rotation gesture.<angle>is in degrees; positive values rotate clockwise, negative values rotate counterclockwise. Optional--point(center) and--radius.
Buttons, Appearance, and Touch
- Use
flowdeck simulator button --hold 1.5to hold a hardware button for the given seconds. - Use
flowdeck simulator appearance lightordarkto switch appearance mode. - Use
flowdeck simulator orientation getororientation set <value>for physical orientation. touch downandtouch upexpectx,ycoordinates in points.- Do not scale by @2x/@3x or device resolution; use the image coordinates directly.
--geometryacceptspointsonly.
Performance and Reliability Tips
- Start a session before any UI work. Run
flowdeck ui simulator session start -S <name-or-udid> --json, parse the JSON output to getlatest_screenshotandlatest_treefile paths, then use Read tool on those paths to see the screen and inspect elements. - Verify after every action. After each tap/type/swipe, wait ~1 second, then re-read
latest_screenshotto confirm the UI changed. Never chain actions without checking. - Use accessibility identifiers and
--by-idwhenever possible; label matching is slower and more ambiguous. - Before tapping an element, read
latest_treeto confirm it exists and is visible. - For automation loops, re-read
latest-tree.json/latest.jpgfrom disk instead of issuingscreenfor every step. The session updates these files automatically. - For one-off checks, use
ui simulator screen --json -S <name-or-udid>— the tree comes back and no screenshot is taken. Add--screenshot(with--optimize) only when you actually need the image. - Use
scroll --until "id:yourElement"to bring off-screen targets into view before tapping. - Increase
--pollfor slow UIs to reduce load; decrease when you need faster detection. - Tune input timing with environment variables:
FLOWDECK_HID_STABILIZATION_MS(default 25) for tap/gesture stabilityFLOWDECK_TYPE_DELAY_MS(default 20) for typing speed
flowdeck ui simulator --help.