Guide · CLI commands

Drive FlowDeck from any shell.

The interactive TUI is great for daily iteration. The CLI is what you reach for when you're scripting, automating, or wiring FlowDeck into a CI job. Everything the TUI does, the CLI does too, and it speaks structured JSON when you need it.

Before you start

This guide assumes:

  • FlowDeck is installed and your license or trial is active. If not, follow the getting-started guide first.
  • You have an Xcode project to drive. Anything with an .xcodeproj or .xcworkspace works.
  • A terminal you're comfortable with. The CLI is also happy inside tmux, CI runners, or whatever shell you script in.

By the end you'll know how to configure a project, build, run, stream logs, run tests, manage simulators and devices, clean caches, and emit structured JSON from every command.

Step 01

Discover and configure your project

Switch into your Xcode project's directory. FlowDeck reads the project from disk; no installation step inside Xcode, no fastlane init-style setup.

cd /path/to/your/project
flowdeck context

The context command parses the workspace and prints what it found: workspaces, schemes, build configurations, available simulators, and connected devices. It's the equivalent of xcodebuild -list, but it parses the project natively instead of compiling anything, so it returns instantly.

If you'd rather consume the result as data, ask for JSON:

flowdeck context --json

Pick a scheme to work with and save it so you don't have to repeat it on every command:

flowdeck config set -w MyApp.xcworkspace -s MyApp -S "iPhone 16"

To inspect the saved config, or to read individual values:

flowdeck config get
flowdeck config get --json

The config lives in .flowdeck/config.json alongside your project. Safe to check into version control (no secrets) or to .gitignore, whichever your team prefers. If you ever want to start fresh, flowdeck config reset wipes it.

Step 02

Build, run, and stop

With the config saved, every subsequent command picks up the workspace, scheme, and simulator automatically. Run a build:

flowdeck build

FlowDeck shells out to xcodebuild under the hood; the build itself is identical to what Xcode runs, but the output is summarized into the lines that matter: compile errors, warnings, and the success/failure status. Pass --verbose for the raw xcodebuild output, or --json for a structured stream of build events.

To build, install, and launch in one command:

flowdeck run

FlowDeck boots the simulator named in your config (override with -S "iPhone 16 Pro" for a one-off, or -D "Daniel's iPhone" for a physical device). The output ends with the app's short ID, which addresses the running app from other commands:

# Example output (yours will differ):
✓ App launched
   ID: a1b2c3d4 | MyApp | iPhone 16

List every app FlowDeck has running, and stop one (or all) cleanly:

flowdeck apps
flowdeck stop a1b2c3d4
flowdeck stop --all

FlowDeck refuses to silently replace a running app, so if flowdeck run blocks on "already running," flowdeck stop first.

Step 03

Stream the app's logs

In a second terminal (so the first one stays free), find your running app and stream its output:

flowdeck apps
flowdeck logs <app-id>

You'll see your print() calls, your OSLog messages, and any runtime errors the app emits, and only those. No SpringBoard, no nsurlsessiond, no other process bleeding into the stream.

Pass --json if you want each log line as a structured event (useful for CI artifacts or piping into jq):

flowdeck logs <app-id> --json | jq 'select(.level == "error")'

A shorthand for launching and streaming in one command:

flowdeck run --log

Step 04

Discover and run tests

FlowDeck discovers tests by parsing your Swift source files directly. No build required. List what's available:

flowdeck test discover

Want it as data? Same flag pattern:

flowdeck test discover --json

Run a specific test, class, or whole target:

# A single test method
flowdeck test --only LoginTests/testValidLogin

# A whole test class
flowdeck test --only LoginTests

# A whole test target
flowdeck test --only MyAppTests

Skip slow tests instead of selecting fast ones:

flowdeck test --skip SlowIntegrationTests

Output is the same shape every time: a stream of pass/fail/skip events, plus a final summary. Add --json for a structured stream you can pipe into jq or a CI reporter.

Step 05

Manage simulators and devices

List every simulator on the machine, in any state, with their runtime:

flowdeck simulator list
flowdeck simulator list --json

Boot a specific simulator by name (FlowDeck handles UDID lookup for you):

flowdeck simulator boot "iPhone 16 Pro"
flowdeck simulator shutdown "iPhone 16 Pro"
flowdeck simulator erase "iPhone 16 Pro"

Create a new simulator from a device type and runtime:

flowdeck simulator create --name "TestSim" --device-type "iPhone 16" --runtime "iOS 18.4"

Install a missing iOS runtime from Apple's catalog (handy in CI when a fresh image is missing a runtime your project needs):

flowdeck simulator runtime list
flowdeck simulator runtime install iOS 18.4

For physical devices, list what FlowDeck can see:

flowdeck device list
flowdeck device list --json

Pairing a device for the first time still happens through Xcode (plug in over USB, trust the prompt on the device). After that, FlowDeck sees the device for the rest of its life. The physical devices guide covers the one-time setup.

To target a device for a single build or run, swap the saved simulator for a device with the -D flag:

flowdeck run -D "Daniel's iPhone"
flowdeck run -D "My Mac"   # macOS apps

Step 06

Clean, reset, and recover

Two levels of clean, depending on how stuck things are:

# Just this project's derived data
flowdeck clean

# Global DerivedData + Xcode caches + FlowDeck's own caches
flowdeck clean --all

When Swift Package Manager state is corrupt, force a re-resolve:

flowdeck project packages resolve

When code-signing fails (expired provisioning profile, new device, fresh CI runner), sync provisioning profiles from your Apple Developer account:

flowdeck project sync-profiles

To start a brand-new project from the CLI (the same wizard the TUI uses, but scriptable, so it works in CI or a non-interactive shell):

flowdeck project create --name MyApp --bundle-id com.example.MyApp \
  --platforms ios,macos --deployment-target 17.0

If you'd rather drive the same flow interactively, run flowdeck -i from an empty folder and the TUI's new-project wizard runs automatically. See the getting-started guide for the wizard walkthrough.

Step 07

Speak JSON to scripts, CI, and agents

Every command accepts --json and emits versioned NDJSON: one event per line, schema documented and stable across minor releases. The same shape applies to build events, test events, log lines, simulator state, and UI automation results.

For a quick taste, watch a build's events as they happen:

flowdeck build --json | jq -r 'select(.type == "error") | "\(.file):\(.line)  \(.message)"'

The output is one event per line: build_started, compile, warning, error, build_completed. Filter, reformat, or hand it to an agent.

The same flag works on every command that produces output, useful when you want one consistent contract across your CI scripts:

flowdeck context --json
flowdeck test --only LoginTests --json
flowdeck logs <app-id> --json
flowdeck simulator list --json
flowdeck config get --json

Common patterns from here

Once the basic build-run-test loop feels natural, the patterns that come up most often:

Switch simulators or devices on the fly.
Any command accepts -S "iPhone 16 Pro" (simulator) or -D "Daniel's iPhone" (device) to override the saved config for a single call. To change the default, use flowdeck config set -S "iPhone 16 Pro".
Run on a physical device.
Pair and trust once in Xcode, then flowdeck run -D "Daniel's iPhone". After that, every command works the same as on a simulator. Logs, tests, UI automation, all of it.
Mix CLI and TUI in the same project.
The TUI (flowdeck -i) and the CLI share .flowdeck/config.json. Drive a build in the TUI, run a one-off scripted test from the CLI, then go back to the TUI. State stays consistent.
Wire FlowDeck into CI.
The same commands work in GitHub Actions, Bitrise, or any runner with macOS and Xcode. The CI automation guide walks through a working pipeline.
Use it from your editor.
The VS Code / Cursor extension surfaces the same commands as menu items and status-bar buttons. Install free from the marketplace.

When things go wrong

flowdeck context says "No workspace found"
You're not in a directory that contains an .xcodeproj or .xcworkspace. cd into your project root and try again. FlowDeck doesn't search upward by design; it always operates on the current directory.
"Simulator not found" when running
The name in your config doesn't match any installed simulator. Run flowdeck simulator list to see what's available, and update the config with flowdeck config set -S "<exact name>". If the runtime is missing entirely, install it: flowdeck simulator runtime install iOS 18.4.
Build succeeds but launch is blocked
An older instance is still registered. flowdeck apps shows what's running; flowdeck stop <app-id> (or flowdeck stop --all) clears it. FlowDeck refuses to silently replace a running app to avoid stealing focus.
No logs streaming
Three usual causes. The build configuration is Release, which suppresses the default logging filter (rebuild as Debug). The app already crashed (check flowdeck apps). Or the only output is debug-level, hidden by default (try flowdeck logs <id> --json to see everything).
Code signing fails on a fresh machine or runner
Provisioning profiles aren't synced. Run flowdeck project sync-profiles to pull them from your Apple Developer account. If signing identity is the blocker, the error message names the missing certificate so you can import it.
Swift Package state is wedged
Force a re-resolve with flowdeck project packages resolve. If that doesn't unstick it, flowdeck clean --all wipes the global DerivedData and Swift package cache too.

Annex

How this compares to Apple's tools

For reference, the same five operations done with Apple's CLIs and with FlowDeck side by side.

What you're doing Apple's tools FlowDeck
Discover schemes xcodebuild -list (2-5 seconds) flowdeck context (native parse, instant)
Build and run on a simulator xcodebuild + simctl install + simctl launch flowdeck run -S "iPhone 16"
Stream this app's logs simctl spawn booted log stream --predicate '...' flowdeck logs <app-id>
Run one test -only-testing:Target/Class/method --only Class/method
Parse output Regex over hundreds of lines of stdout --json on any command

Full side-by-side at FlowDeck vs xcodebuild.

Read next

Further reading

  1. Advanced interactive mode, the interactive view of the same commands.
  2. Automate iOS builds for CI and local dev, a working GitHub Actions pipeline.
  3. iOS simulator management, the deep dive on what makes simulator boot reliable.
  4. iOS log streaming, the deep dive on per-app logging.
  5. iOS UI automation, when you are ready to tap, type, and screenshot from the CLI.
  6. Full CLI reference, in the FlowDeck docs.