iOS Simulators Are Quietly Using 40 GB of Your Mac
Every simulator device, every old runtime, and a dyld cache nobody mentions. The safe `simctl` commands to reclaim all of it without breaking Xcode.
Xcode downloads a new simulator runtime for each major OS version and never removes the old ones. Each runtime is 7–14 GB. Each simulated device you have ever booted carries its own data volume with the apps you installed on it.
Total it up:
du -sh ~/Library/Developer/CoreSimulator
30–60 GB is normal. It is frequently the second largest folder on an iOS developer’s Mac, behind DerivedData.
The three separate hoards
# Simulated devices: one data volume each, with every app you ever ran
du -sh ~/Library/Developer/CoreSimulator/Devices
# Runtimes: the actual OS images, 7-14 GB apiece
du -sh ~/Library/Developer/CoreSimulator/Profiles/Runtimes 2>/dev/null
# The dyld shared cache, rebuilt per runtime and never garbage collected
du -sh ~/Library/Developer/CoreSimulator/Caches
That third one surprises people. It is a build artefact of the simulator itself, it regenerates automatically, and it is regularly 5–10 GB.
Start here: delete unavailable devices
This is the safest useful command on the page:
xcrun simctl delete unavailable
It removes simulator devices whose runtime is no longer installed — orphans left behind by Xcode upgrades. They cannot be booted, they do nothing, and they are pure waste. There is no scenario in which you want them.
Follow it with the cache, which rebuilds on demand:
rm -rf ~/Library/Developer/CoreSimulator/Caches/*
Between them you will typically recover 8–20 GB for zero cost.
Then: remove old runtimes
See what you have:
xcrun simctl runtime list
That prints each installed runtime with its version, build and identifier. On a Mac that has been through three Xcode upgrades you will find runtimes for iOS versions that dropped below your deployment target long ago.
Delete by identifier:
xcrun simctl runtime delete <identifier>
Or, once you are certain nothing you build still targets them:
xcrun simctl runtime delete --all --notUsedSinceDays 90
Xcode also exposes this at Settings → Components (called Platforms in recent versions), with a size next to each and a delete button. Use that if you would rather see it in a list.
Keep the runtime matching your minimum deployment target. If your app supports iOS 17 and up, you want an iOS 17 simulator to actually test on it. Delete below that line, not above it.
Nuclear: delete every device and start fresh
xcrun simctl delete all
Every simulated device goes, along with its installed apps, its settings, its keychain, its photo library and any test data you set up. Xcode recreates a default set on next launch.
The runtimes stay — this only clears devices — so you are not re-downloading 12 GB afterwards.
Do not run this if you have simulators configured with state you would have to rebuild by hand: logged-in test accounts, seeded databases, a photo library assembled for screenshot automation. That work is not backed up anywhere.
A gentler middle ground, erasing content while keeping the devices themselves:
xcrun simctl shutdown all
xcrun simctl erase all
Useful things to know about simctl
# Every device, grouped by runtime, with UDIDs
xcrun simctl list devices
# Only the ones currently booted
xcrun simctl list devices booted
# Delete one specific device
xcrun simctl delete <UDID>
# Open the data folder of a booted simulator in Finder
open "$(xcrun simctl get_app_container booted <bundle-id> data)"
xcrun simctl list devices is worth running before any bulk delete. It shows exactly what you are
about to lose, grouped so the obsolete runtimes stand out.
Android has the same problem, worse
If you also build for Android, the equivalent is larger:
du -sh ~/.android/avd # 8-12 GB per virtual device
du -sh ~/Library/Android/sdk/system-images # 1-3 GB per API level
du -sh ~/.gradle/caches
Android Studio downloads a fresh system image per API level and keeps every AVD you ever created. Someone who wrote one React Native app two years ago routinely has 60 GB sitting here.
Why it keeps growing
Every Xcode release brings a new runtime. Every new device you simulate creates a data volume.
Neither is ever collected, and none of it appears anywhere in the macOS storage UI — it is all
inside ~/Library, which Finder hides.
DevCruft shows each runtime and each simulator device individually, sized to scale, with the
last time you booted it — so the iOS 16 runtime you have not touched in eighteen months is obvious
rather than something you have to go hunting for with simctl.
See also: clearing DerivedData and the full developer storage guide.