Before you start
This guide assumes:
FlowDeck is installed and your license or trial is active. If not, follow the getting-started guide first.
A physical iPhone, iPad, or Apple Watch you can connect by USB (or wirelessly after the initial USB pairing).
A working Apple Developer account. A free Personal Team is fine for installing on devices you own.
Your project's signing tab in Xcode is configured at least once (FlowDeck reads the signing configuration from your project; it doesn't generate it).
By the end you'll have built, installed, and launched your app on a real device, streamed its logs from the terminal, and have the workflow you'd use day to day instead of the Xcode Run button.
Pair the device (one-time setup)
The first time you connect a device, it has to be paired and trusted. This still happens through Xcode, FlowDeck doesn't bypass Apple's pairing flow.
Plug the device into your Mac via USB.
Open Xcode at least once.
Go to Window → Devices and Simulators. Your device should appear in the sidebar.
Trust the device when prompted on the iOS side ("Trust This Computer?").
For wireless development, check "Connect via network" in the Devices pane while the device is still on USB. After that you can unplug.
After this one-time setup, FlowDeck can see the device for the rest of its life. You don't have to open Xcode again unless you re-pair.
Prefer the keyboard? Everything below works from FlowDeck's interactive TUI too, run flowdeck -i in your project and use single-letter shortcuts (D to pick the paired device, R to build + install + launch, L to stream logs, T for tests). The CLI snippets in the steps below are what the TUI runs under the hood; copy them when you want to script, hand them to an agent, or run one-off commands outside the TUI. See the TUI guide for the full keyboard reference.
Verify the device is reachable
List all paired devices:
You should see your device with its name, UDID, platform, and connection type (USB or network). Add --json for structured output if you're scripting against this.
If a device you paired in Xcode doesn't appear in flowdeck device list, the pairing didn't take. Re-trust it from the device's settings (Settings → General → VPN & Device Management → your computer name) and try again.
Build for the device
Build, sign, and produce an installable .app in one command. The destination is the device by name:
FlowDeck calls xcodebuild under the hood with the right destination string and signing configuration. If your scheme has multiple signing identities (debug vs release), pass --configuration Debug or --configuration Release explicitly. Save it to the project config so it sticks across commands:
If you have multiple devices on your account, you can use the partial name ("iPhone" matches the first paired iPhone) or pass the UDID directly. Be specific when you have multiple devices; partial matches lean toward the first paired device, which is rarely what you want.
Install and launch on the device
Single command, same as the simulator path:
This builds (if needed), signs, installs, and launches. The first launch on a personal development account may prompt you to trust the developer profile on the device, go to Settings → General → VPN & Device Management on the device and approve. After that first approval, subsequent launches don't prompt.
The output ends with the app's short ID, which you'll use to address the running app for logs and stops.
For install-without-launch (useful when you're handing off a build for someone else to test on their device):
And uninstall when you want a clean slate:
Both device install and device uninstall take the device UDID positionally, not the device name. Grab the UDID from flowdeck device list. The higher-level flowdeck run -D "Daniel's iPhone" resolves names for you; the lower-level device install / uninstall commands don't.
Stream logs from the device
The same flowdeck logs command that streams simulator app logs also streams from physical devices. The launch type is recorded in the app registry, so FlowDeck routes through the device console pathway automatically, no separate command, no syntax change.
Output is your app's print() calls and OSLog messages, same as on the simulator. Wireless device connections work the same way; the underlying transport is handled by Apple's devicectl.
Or, to launch and stream in one step:
Stop or relaunch
Same surface as the simulator. When you're done with the app, stop it cleanly:
For a fresh run, stop then run. FlowDeck deliberately refuses to silently replace a running app, devices in particular can leave background activity that confuses the next launch if you don't terminate cleanly first.
Patterns that come up most often
Switching between simulator and device on the same project.
The saved config holds one default target. To switch occasionally without losing the saved value, just pass the override: flowdeck run -S "iPhone 16" for the simulator, flowdeck run -D "Daniel's iPhone" for the device. To change the default permanently, flowdeck config set -D "..." (which clears the simulator default and vice versa).
Multiple devices on one account.
Pass distinct names: -D "Daniel's iPhone" vs -D "Daniel's iPad". If two devices share a name, target by UDID instead. Use flowdeck device list --json to script against device inventory in CI.
Apple Watch development.
For watchOS app development, pair the watch with its companion iPhone first (in Xcode's Devices pane). Then target the watch directly: flowdeck run -D "Daniel's Apple Watch". The watch must be unlocked and on the wrist for launches to complete.
Network-only devices.
After the initial USB pairing with "Connect via network" checked, the device shows up in flowdeck device list even when unplugged. The connection type column reads network. The Mac and the device must be on the same Wi-Fi network (or at least the same subnet) for the transport to work. Network builds and launches are slower than USB (binary transfer is the bottleneck) but work otherwise identically.
UI automation on physical devices.
Not supported. Apple does not expose the out-of-process accessibility hooks on physical devices that the iOS Simulator exposes. flowdeck ui simulator works only on the simulator. For device-based UI automation, XCUITest is the available option (it runs in-target on the device).
How the device workflow differs from the simulator workflow
For reference, what changes when you swap a simulator target for a physical device.
Aspect | Simulator | Physical device |
|---|---|---|
Setup | None; simulators ship with Xcode | One-time pair + trust in Xcode, plus a developer profile |
Targeting flag |
|
|
Build time | Fast (no signing step) | Slower (signing + binary transfer) |
Install time | Instant | 10-60s first install, near-instant after |
Logs |
|
|
UI automation |
| Not supported. XCUITest is the option for device UI testing. |
Reset state |
|
|
Multiple targets | Cheap; spawn as many as you have RAM for | Cheap; pair as many as your team has, address by name or UDID |
The CLI surface is intentionally identical where it can be. The unavoidable differences (signing, UI automation, install times) come from Apple's platform constraints, not FlowDeck.
When things go wrong
Device doesn’t appear in flowdeck device list
“Untrusted Developer” on first launch
“Could not launch” or signing errors
Wireless device disconnects mid-build
Logs are empty
App takes a long time to install on the device
“Provisioning profile doesn’t include this device”
