How to Bulk Delete Unavailable iOS Simulators via Terminal
If you work with Xcode long enough, your local development environment inevitably collects digital dust. Every major Xcode update, beta cycle, or iOS SDK transition leaves behind orphaned, “unavailable” simulator targets that clutter your disk space and muddy your tooling outputs.
Running xcrun simctl list might show dozens of ghost devices tied to older runtimes you no longer even have installed.
If you want to clear out the junk, doing it manually via the Xcode GUI or copying individual UUIDs is a tedious chore. Here is how to automate the cleanup instantly using the command line.
The One-Liner (The Quick Way)
Before writing custom shell scripts, Apple actually built a hidden native shorthand directly into simctl to handle basic housecleaning. If you just want to purge every single broken or unavailable simulator on your Mac right now, open your terminal and run:
Bash
xcrun simctl delete unavailable
This acts as a global sweep, instantly destroying any device container whose underlying runtime is missing.
The Targeted Way (Using JSON and jq)
Sometimes you need more granular control, or you are building an automated CI/CD build-agent cleanup script. Because simctl can export your entire simulator state as structured JSON using the -j flag, we can combine it with jq and xargs to pinpoint and destroy exactly what we want.
To find and destroy only the devices explicitly flagged with "isAvailable" : false, run this pipeline:
Bash
xcrun simctl list -j devices | jq -r '.devices[] | .[] | select(.isAvailable == false) | .udid' | xargs -I {} xcrun simctl delete {}
Breaking Down the Pipeline
If you are curious about how this script parses the nested data structure, here is what each segment is doing under the hood:
xcrun simctl list -j devicesOutputs your entire simulator directory structure as a clean JSON payload.jq -r '.devices[] | .[]'Digs past the top-level dictionary keys (which are organized by runtime strings likecom.apple.CoreSimulator.SimRuntime.iOS-18-0) and unpacks every single device object into a flat, scannable stream. The-rflag ensures the output prints as raw text instead of JSON-formatted strings wrapped in quotes.select(.isAvailable == false)Acts as a conditional filter. It ignores your functional, booted, or available simulators and only passes objects downstream if they are broken..udidIsolates the raw identifier string (e.g.,74A2B6DC-EB50-4666-844C-AD7B635400E2).xargs -I {} xcrun simctl delete {}Takes every unique UDID emitted byjqand sequentially drops it into a target-specificdeleteexecution loop.
Tip: If your Mac complains that
jqisn’t found, you can install it instantly via Homebrew usingbrew install jq. It is an essential Swiss Army knife for anyone doing framework engineering or managing build pipelines on macOS.