What does xcrun simctl delete unavailable actually do?

A complete xcrun simctl delete unavailable guide for iOS developers: what it removes, what it leaves behind, the rogue simulators it cannot touch, and the safe order.

8 min read · Published · Updated · Saad Belfqih

One thread on Apple Discussions opens with an iOS engineer staring at 18 GB of simulator devices that Xcode does not show in its Components window and that xcrun simctl delete unavailable flat-out refuses to remove. The thread is a question about simulators that were "not addressable from simctl". The replies are people swapping shell snippets. Apple never resolved it.

That is the context most posts about xcrun simctl delete unavailable skip. The command is real and you should run it. It also has a narrow scope that fools developers into thinking their disk is clean when it is not.

TL;DR
The command `xcrun simctl delete unavailable` removes simulator devices whose runtime is gone, and only those. It will not delete runtime DMGs, CoreSimulator caches, XCTestDevices, or rogue simulators that Xcode never tracked. CleanMyDev sizes all of them at once and moves them to Trash with one click, so you do not have to chain six commands and still miss the 9 GB orphan in `/System/Library/AssetsV2/`.

What does xcrun simctl delete unavailable actually do?

The simctl binary ships with the command-line tools and talks to the CoreSimulator service. When you run:

xcrun simctl delete unavailable

CoreSimulator walks every device record in ~/Library/Developer/CoreSimulator/Devices/, checks whether each device's runtime is still installed, and deletes the ones whose runtime is missing. An "unavailable" device is not a device you do not use. It is a device whose iOS runtime DMG has been removed, leaving the device folder pointing at nothing.

That happens often. You install Xcode 16.0, get simulators for iOS 18.0. You update to Xcode 16.2 and the iOS 18.0 runtime is replaced by iOS 18.2. The 18.0 device folders are now orphans, taking 1 to 3 GB each. Multiply by every old runtime you have rolled through in two years and the orphan pile is real.

The command is safe. It only removes devices you cannot boot anyway. It is also small, in the sense that it usually reclaims 2 to 8 GB on a typical dev Mac. That is not nothing, but it is not the whole story either.

Where does Xcode actually keep simulator data on Mac?

Before running cleanup commands, it helps to know what lives where. Apple has changed the layout three times since Xcode 14, and stale tutorials send people to paths that no longer exist.

Path What it holds Typical size
~/Library/Developer/CoreSimulator/Devices/ Per-device data: apps, NSUserDefaults, photos, file system 10 to 25 GB
~/Library/Developer/CoreSimulator/Caches/ Downloaded runtime images and dyld cache 3 to 12 GB
~/Library/Developer/CoreSimulator/Volumes/ Mounted runtime read-only volumes 5 to 20 GB
/Library/Developer/CoreSimulator/Profiles/Runtimes/ System-level runtime bundles (.simruntime) 5 to 25 GB
/System/Library/AssetsV2/com_apple_MobileAsset_iOSSimulatorRuntime/ Asset-served runtimes (newer Xcode) 0 to 30 GB
~/Library/Developer/XCTestDevices/ Headless test-runner clones 1 to 8 GB
~/Library/Logs/CoreSimulator/ Per-device logs that nobody reads 0.5 to 3 GB

xcrun simctl delete unavailable only touches the first one. Everything else needs a different command, a different folder, or a different tool.

That is the part the man page leaves implicit. If you run the command and your disk is still 80 percent full, the command did its job. The other 60 GB is in folders the command does not address.

How do I find out what xcrun simctl delete unavailable will actually remove?

Before deleting, list what simctl considers unavailable.

# List every device, grouped by runtime
xcrun simctl list devices

# Filter to just the unavailable ones (these are what the delete command targets)
xcrun simctl list devices unavailable

# Dry-run-ish: count how many devices will be removed
xcrun simctl list devices unavailable | grep -E "^\s+[A-Za-z]" | wc -l

# See the size of the device folder before vs after
du -sh ~/Library/Developer/CoreSimulator/Devices

If the count is high, that is a good sign. It means CoreSimulator has been accumulating orphan device folders and the command is going to do meaningful work. If the count is zero, do not bother. The reclaim you are looking for is in the other folders.

How do I actually run xcrun simctl delete unavailable safely?

The command itself is one line. The wrapping is what makes it safe to run on a working machine mid-sprint.

# Quit Xcode and the Simulator app so nothing is mid-write
osascript -e 'quit app "Xcode"'
osascript -e 'quit app "Simulator"'

# Shut down anything still booted (otherwise some deletes are deferred)
xcrun simctl shutdown all

# Size before
du -sh ~/Library/Developer/CoreSimulator/Devices

# The actual command
xcrun simctl delete unavailable

# Size after
du -sh ~/Library/Developer/CoreSimulator/Devices

A few things to note. simctl shutdown all prevents the "Unable to delete device, it's booted" error that locks up scripted cleanups. The du calls bracket the operation so you have receipts on the reclaim. You do not need sudo. CoreSimulator runs as your user, and any cleaner that asks for sudo to wipe simulators is doing something wrong.

If the command finishes and du shows no change, you have no orphans. Move on to the runtimes.

What does xcrun simctl delete unavailable not delete?

This is the section the docs leave out. The command leaves four large categories untouched.

Category Where it lives How to actually remove it
Runtime DMGs ~/Library/Developer/CoreSimulator/Volumes/ and /Library/Developer/CoreSimulator/Profiles/Runtimes/ xcrun simctl runtime list then xcrun simctl runtime delete <id>
AssetsV2 orphans /System/Library/AssetsV2/ Xcode > Settings > Components, uncheck old iOS versions
CoreSimulator caches ~/Library/Developer/CoreSimulator/Caches/ Manual rm -rf after simctl shutdown all
XCTestDevices ~/Library/Developer/XCTestDevices/ Delete folder contents directly, regenerated on next test run

The AssetsV2 case is worth calling out. An Apple Developer Forums thread documents a 9 GB orphaned runtime in AssetsV2 that newer Xcode versions did not expose in the UI and that no simctl command would touch. That folder is owned by the OS itself, so the only correct removal path is through Xcode's Components window, not the command line.

The runtime DMG case is the bigger reclaim in most audits. Runtimes are 4 to 7 GB each, and most developers have three or four old ones installed from previous Xcode releases.

# List installed runtimes with their UDIDs and sizes
xcrun simctl runtime list

# Delete an old one (replace with the actual UDID from the list above)
xcrun simctl runtime delete 1A2B3C4D-5E6F-7890-ABCD-EF1234567890

simctl runtime delete is a separate command from simctl delete. The distinction trips up people who assume one verb covers both.

Rogue simulators: when xcrun simctl delete unavailable cannot help

The pain point from the Apple Discussions thread is real. Devices can end up in a state where they are not addressable through simctl at all. They live on disk, they take space, and the command line does not see them.

This usually happens when:

The fix is to compare the file system against the database directly:

# Devices simctl knows about
xcrun simctl list devices --json | grep -o '"udid"\s*:\s*"[^"]*"' | wc -l

# Device folders actually on disk
ls ~/Library/Developer/CoreSimulator/Devices | grep -c '-'

# If those two numbers differ, you have rogue folders.
# List the orphans the safe way: dirs on disk that simctl does not list.
comm -23 \
  <(ls ~/Library/Developer/CoreSimulator/Devices | sort) \
  <(xcrun simctl list devices --json | grep -o '"udid"\s*:\s*"[^"]*"' | cut -d'"' -f4 | sort)

The orphan UDIDs that come out of that comm call are the ones safe to remove manually with rm -rf ~/Library/Developer/CoreSimulator/Devices/<udid>, after quitting Xcode and Simulator. CoreSimulator will not miss them because it never knew about them.

This is exactly the audit gap CleanMyDev was built to close. Walking the file system and comparing it to the database in three terminals takes ten minutes. A scanner that already knows what to look for takes one.

What about xcrun simctl delete all?

The nuclear option exists.

# Wipe contents but keep the devices themselves
xcrun simctl erase all

# Delete every device entirely
xcrun simctl delete all

erase all is useful before a clean QA pass, because it gives you fresh first-run state without redownloading runtimes. delete all is useful if you want a true reset and are happy for Xcode to recreate its default device set on next launch. Both are heavier than delete unavailable and worth holding in reserve for when you actually want them. The default workflow is delete unavailable first, then runtime delete on the runtimes you no longer need, then delete all only if you are sure.

The recommended order for a real simulator cleanup

If you have read this far, you want the full sequence, not just the one command. This is the order I use on my own Mac, ordered from safest to most aggressive.

  1. xcrun simctl shutdown all to release any booted device.
  2. xcrun simctl delete unavailable to clear orphan device folders.
  3. xcrun simctl runtime list to see what runtimes are installed.
  4. xcrun simctl runtime delete <udid> for every runtime older than the current iOS minus one.
  5. Open Xcode > Settings > Platforms and remove any iOS version you no longer test against. This is the only safe way to clear /System/Library/AssetsV2/.
  6. Compare ls ~/Library/Developer/CoreSimulator/Devices against xcrun simctl list devices and rm -rf any rogue UDIDs.
  7. Optionally, clear ~/Library/Developer/XCTestDevices/ if you do not have a Swift Testing run in progress.

That sequence usually reclaims 30 to 80 GB on a Mac that has been doing iOS development for a year. xcrun simctl delete unavailable is step two of seven.

If you want one tool to do all seven plus the rest of the System Data pile, that is what CleanMyDev does. See the reclaim disk from Xcode simulators walkthrough for the full simulator-only path, or the broader Xcode disk space full fix guide for the whole Xcode footprint at once.

Get all seven steps on one screen

CleanMyDev was built for the iOS developer who does not want to remember a seven-step shell sequence every three months. Every scan surfaces CoreSimulator devices, runtimes, the AssetsV2 orphans, XCTestDevices, and the rogue folders simctl cannot see, each with its size, last used date, and a risk label. Move-to-Trash by default. One-time license, no subscription, no telemetry. Get CleanMyDev on the pricing page.

Related reading

Stop wondering what System Data is.

CleanMyDev opens the box. 110+ developer-specific cleanup targets. Move-to-Trash by default. $9.99 lifetime.

Get CleanMyDev — $9.99