
A watchOS app installs through a paired iPhone simulator, so the Apple Watch simulator only becomes a valid destination once a phone pair is booted alongside it. That pairing step has to happen on the Mac that runs the simulator, which is where a remote Mac makes the whole loop reproducible. This guide covers the exact xcrun simctl sequence, an xcodebuild destination that targets the paired phone, and the Figment plan to run it on.
For routine WatchKit layout, complication, and HealthKit work using an Intel-compatible Xcode toolchain, request the i3 Mac at $49/month. Intel Macs run Xcode 26 or earlier per Apple's Porting your macOS apps to Apple silicon guidance, and that line of Xcode ships watchOS and iOS simulator runtimes that cross-compile and deploy to simulators.
For visionOS targets, Xcode 27, parallel simulator sessions, or anything that must execute arm64-only binaries natively, step up to the M-series Mac from $95/month. The exact chip, RAM, and disk at the $95 entry are confirmed on the quote — physical Intel and M-series plans collect requests until supply is confirmed, so ask for availability when you request a configuration.
The $29 virtual Intel macOS plan runs macOS and a compatible Intel Xcode, but it has no GPU acceleration. The iOS and watchOS simulators render through Metal, so simulator-heavy work is not a good fit there; use it for build, test-logic, and command-line tooling rather than interactive simulator sessions. Start a configuration at /mac-hosting/start.
Xcode's watchOS simulator differs from iOS in one way that matters for scripting: an Apple Watch simulator must be paired to a specific booted iPhone simulator before an app can be installed on it, mirroring how a physical watch is bound to one phone. When a WatchKit scheme builds, Xcode routes the watch payload through the paired phone, which is why the correct -destination is the phone's UDID, not the watch's. Apple's Running your app in Simulator or on a device is the reference for the simulator destination model.
xcrun simctl creates, pairs, and boots devices from the command line, which is exactly what you want on a remote Mac you reach through a browser console.
Confirm that the watchOS runtime is installed on the remote Mac before creating anything:
# Runtimes — look for watchOS and iOS rows
xcrun simctl list runtimes
# Device types
xcrun simctl list devicetypes | grep -i watch
xcrun simctl list devicetypes | grep iPhone
If the watchOS runtime is missing, install it via Xcode → Settings → Platforms in the remote desktop, or:
xcodebuild -downloadPlatform watchOS
Copy the exact identifiers you see — for example com.apple.CoreSimulator.SimRuntime.watchOS-11-0 and a device-type string that ends with the model/size — rather than hard-coding values from a guide. Identifier strings change between Xcode versions.
This script resolves identifiers from your installed Xcode, creates both simulators, pairs them, and boots them. Run it in the remote Mac's terminal:
set -euo pipefail
# Resolve the first matching identifier; override by pasting the explicit
# string from `xcrun simctl list` output if you want a specific model/runtime.
WATCH_TYPE="$(xcrun simctl list devicetypes | awk '/Apple Watch/ {print $NF; exit}' | tr -d '()')"
WATCH_RUNTIME="$(xcrun simctl list runtimes | awk '/watchOS/ {print $NF; exit}' | tr -d '()')"
PHONE_TYPE="$(xcrun simctl list devicetypes | awk '/iPhone/ {print $NF; exit}' | tr -d '()')"
PHONE_RUNTIME="$(xcrun simctl list runtimes | awk '/iOS/ {print $NF; exit}' | tr -d '()')"
for v in "$WATCH_TYPE" "$WATCH_RUNTIME" "$PHONE_TYPE" "$PHONE_RUNTIME"; do
[[ -n "$v" ]] || { echo "Missing identifier — run 'xcrun simctl list' and paste the exact string." >&2; exit 1; }
done
PHONE_UDID=$(xcrun simctl create "Paired iPhone" "$PHONE_TYPE" "$PHONE_RUNTIME")
WATCH_UDID=$(xcrun simctl create "Paired Watch" "$WATCH_TYPE" "$WATCH_RUNTIME")
# Pair order is watch first, then phone
xcrun simctl pair "$WATCH_UDID" "$PHONE_UDID"
xcrun simctl boot "$PHONE_UDID"
xcrun simctl boot "$WATCH_UDID"
open -a Simulator
echo "Phone: $PHONE_UDID"
echo "Watch: $WATCH_UDID"
Verify the pair with xcrun simctl list pairs; the entry should read (active). This is an unexecuted example — run it against your own Xcode install and check its exit status before wiring it into CI.
For a WatchKit scheme, pass the iPhone's UDID as the destination. Xcode installs the watch payload through the paired phone automatically:
set -euo pipefail
PHONE_UDID="<paste from previous step>"
WORKSPACE="YourApp.xcworkspace" # or -project YourApp.xcodeproj
SCHEME="YourApp WatchKit App" # your actual scheme name
xcodebuild build \
-workspace "$WORKSPACE" \
-scheme "$SCHEME" \
-destination "platform=iOS Simulator,id=$PHONE_UDID" \
-derivedDataPath ./DerivedData \
CODE_SIGN_IDENTITY="" \
CODE_SIGNING_REQUIRED=NO
Replace build with test and add -only-testing:YourWatchTests to run a test bundle. To launch the watch app interactively after a build, install it onto the watch simulator and launch by bundle identifier:
xcrun simctl install "$WATCH_UDID" path/to/YourWatchApp.app
xcrun simctl launch "$WATCH_UDID" com.example.YourWatchApp
Use your real scheme name and bundle identifier — the strings above are placeholders, not a benchmark or a verified run.
Complication preview. With the watch simulator booted, use Simulator.app's Features menu to change the watch face, then long-press the face to enter edit mode and add your complication. Timeline entries render immediately from your CLKComplicationDataSource, which lets you iterate on layout without touching a physical device.
HealthKit mock data. The watch simulator accepts HKQuantitySample and HKWorkout writes through HKHealthStore.save(...). Seed a store from a debug-only code path in your test target so the same data loads on every boot. Live sensor streams (heart rate, accelerometer, gyroscope) are not available in the simulator.
Background refresh. Simulator.app exposes test hooks under Features or Debug in current versions; menu paths change between releases, so check the installed build. If the hook is missing, trigger your refresh handler from a debug entry point that posts the same notification.
| Capability | Simulator | Physical device |
|---|---|---|
| Complication timelines | Yes | Yes |
| HealthKit reads/writes | Yes (mocked data) | Yes (live sensors) |
| Heart rate / motion sensors | Not available | Yes |
| Digital Crown | Scroll gesture | Tactile + software |
| Taptic Engine haptics | Not available | Yes |
WatchConnectivity (WCSession) | Yes, via paired iPhone sim | Yes |
| Always-on display | Not available | Series 5+ |
| GPS in workout sessions | Not available | Yes |
Simulator coverage handles layout, navigation, complication data sources, HealthKit writes, and WCSession message passing end-to-end. Sensor-driven features and haptics still need a real watch.
Request a configured Mac for this workflow at /mac-hosting/start.
Related guides: