`xcrun simctl` Is the iOS Simulator Command Set You Should Learn Before Clicking Around Xcode for an Hour
A practical guide to using `xcrun simctl` to boot simulators, install apps, open deep links, clear state, and debug iOS simulator workflows without wasting time in Xcode menus.
Why this command matters: a lot of iOS debugging time gets wasted on UI clicking when the real problem is not Xcode itself. It is that developers are doing repeatable simulator tasks manually.
If you build for iPhone or iPad regularly, xcrun simctl is one of the fastest ways to stop treating the iOS Simulator like a black box. Apple documents it as the command-line control surface for Simulator devices, and that is exactly how you should think about it: boot, erase, install, uninstall, launch, open URLs, and manage app containers without poking through menus.
Start by listing devices
When you do not know which simulators are available, run:
xcrun simctl list devicesThat tells you:
- device names
- runtime versions
- whether they are booted
- whether they are shutdown or unavailable
If you only remember one first step, remember this one. A lot of “simulator is broken” problems are actually “you are targeting the wrong runtime or wrong device.”
Boot a simulator from the terminal
Instead of opening Simulator first and clicking around, boot directly:
xcrun simctl boot "iPhone 16 Pro"
open -a SimulatorIf the device is already booted, the boot command is harmless. This is especially useful in scripts and repeatable local setup.
You can also target by UDID instead of by name if you want something less ambiguous.
Install and launch your app without hunting for it
Once you have a built .app, install it directly:
xcrun simctl install booted /path/to/MyApp.appThen launch it by bundle id:
xcrun simctl launch booted com.example.myappThis matters because it separates build problems from simulator interaction problems. If Xcode looks confused, simctl install and simctl launch often tell you much faster whether the artifact itself is fine.
Test deep links and auth callbacks directly
If your app handles custom schemes or universal-link style flows, you do not need to manually type them in Safari every time. Use:
xcrun simctl openurl booted "myapp://login/callback?token=demo123"This is one of the best ways to debug:
- deep links
- OAuth callback handling
- app routing
- branch-specific test flows
The difference between a flaky manual test and a repeatable one is often just this command.
Wipe bad state when the app gets weird
Simulator state drifts. Caches persist. Broken auth sessions stick around. Developers often waste time debugging “code problems” that are really stale simulator state.
Erase the whole device if you need a clean start:
xcrun simctl erase bootedOr uninstall just your app:
xcrun simctl uninstall booted com.example.myappThis is a much cleaner debugging move than repeatedly deleting the app by hand and hoping that was enough.
Open the app’s sandbox when debugging files
If you need to inspect files your app wrote, get the container path:
xcrun simctl get_app_container booted com.example.myapp dataYou can then open that path in Finder or inspect it from the shell. This is extremely useful for:
- SQLite databases
- downloaded assets
- logs written by the app
- caches and preference files
When local storage is part of the bug, this command is usually faster than digging through Xcode’s UI.
A practical debug loop
Here is a clean repeatable simulator loop:
xcrun simctl boot "iPhone 16 Pro"
xcrun simctl uninstall booted com.example.myapp || true
xcrun simctl install booted /path/to/MyApp.app
xcrun simctl launch booted com.example.myapp
xcrun simctl openurl booted "myapp://debug"That flow turns simulator testing into something scriptable instead of something you perform by memory.
Final recommendation
If you touch iOS often, stop treating Simulator as a purely graphical tool. Learn xcrun simctl for device listing, booting, install, launch, deep-link testing, uninstall, erase, and app-container inspection. The payoff is not only speed. It is repeatability.