Guide · Physical devices

Develop and deploy to physical iOS devices.

The terminal workflow for physical-device iOS development. Pair the device, build with the right signing, install and launch on a real iPhone or iPad, and stream its logs, all without opening Xcode.

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.

Step 01

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.

  1. Plug the device into your Mac via USB.
  2. Open Xcode at least once.
  3. Go to Window → Devices and Simulators. Your device should appear in the sidebar.
  4. Trust the device when prompted on the iOS side ("Trust This Computer?").
  5. 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.

Step 02

Verify the device is reachable

List all paired devices:

flowdeck device list

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.

Step 03

Build for the device

Build, sign, and produce an installable .app in one command. The destination is the device by name:

flowdeck build -D "Daniel's iPhone"

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:

flowdeck config set -D "Daniel's iPhone" -C Debug

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.

Step 04

Install and launch on the device

Single command, same as the simulator path:

flowdeck run -D "Daniel's iPhone"

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):

flowdeck device install <udid> /path/to/MyApp.app

And uninstall when you want a clean slate:

flowdeck device uninstall <udid> com.example.myapp

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.

Step 05

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.

flowdeck apps
flowdeck logs <app-id>

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:

flowdeck run --log -D "Daniel's iPhone"

Step 06

Stop or relaunch

Same surface as the simulator. When you're done with the app, stop it cleanly:

flowdeck stop <app-id>

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.

flowdeck stop <app-id>
flowdeck run -D "Daniel's iPhone"

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).

When things go wrong

Device doesn't appear in flowdeck device list
The pairing didn't take. Open Xcode's Devices pane, confirm the device shows there. If it's there but Xcode reports "Preparing device for development," wait for that to finish (it takes 5-15 minutes on a fresh device or major iOS update). If the device shows in Xcode but not FlowDeck, restart your terminal, the device-list connection is established when the FlowDeck CLI process starts.
"Untrusted Developer" on first launch
One-time. On the device, go to Settings → General → VPN & Device Management, find your developer name, tap "Trust." Subsequent launches don't re-prompt. If you're on a Personal Team free Apple ID, the trust expires every 7 days; you'll need to relaunch from Xcode or FlowDeck within that window to refresh it.
"Could not launch" or signing errors
Signing problems originate in your project, not in FlowDeck. Open Xcode's signing tab and check: is the bundle ID one that matches your team's provisioning profile? Is the team selected? Does the device's UDID appear in the developer portal for your provisioning profile? Resolve all three before retrying.
Wireless device disconnects mid-build
Wireless transfer is fragile on flaky Wi-Fi. Plug back in over USB for builds, unplug for run+logs once installed. Or pin the device's connection to USB-only via the "Connect via network" checkbox in Xcode's Devices pane.
Logs are empty
Same causes as simulator: Release build suppresses debug logs (rebuild as Debug), app already crashed during launch (check flowdeck apps), or all output is at debug level (try flowdeck logs <id> --json to see everything). On wireless devices, an extra cause: weak network can drop the log stream silently; reconnect via USB to diagnose.
App takes a long time to install on the device
Expected. Device installs are slower than simulator installs because the binary is transferred and signed against the device's identity. First install of a new build is the slowest (10-60 seconds depending on app size); subsequent installs of the same build are nearly instant. For wireless, expect 2-5x slower than USB.
"Provisioning profile doesn't include this device"
The device's UDID isn't registered with the provisioning profile your project uses. Open Xcode, let it auto-resolve (it usually offers to add the device to the profile and re-sign). If you're on a non-personal team, an admin may need to register the device through developer.apple.com first.

Annex

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 -S "iPhone 16" -D "Daniel's iPhone"
Build time Fast (no signing step) Slower (signing + binary transfer)
Install time Instant 10-60s first install, near-instant after
Logs flowdeck logs <app-id> flowdeck logs <app-id> (same; FlowDeck routes the transport)
UI automation flowdeck ui simulator fully supported Not supported. XCUITest is the option for device UI testing.
Reset state flowdeck simulator erase flowdeck device uninstall (per-app) or factory-reset the device (rare)
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.

Read next

Further reading

  1. Automate iOS builds for CI and local dev, a working GitHub Actions pipeline.
  2. iOS log streaming, per-app filtering for device builds.
  3. Things to ask your AI agent, AI workflows on real devices, not just simulators.
  4. Full CLI reference, in the FlowDeck docs.