A working iOS Mac that survives two release cycles ends up carrying 100 to 180 GB of pure Xcode footprint, and almost none of it is visible in the System Settings Storage bar. The category is documented cold on jonathanspooner.com, Reclaim 100+ GB from Xcode: "The Cleanup Script I Wish I'd Written Years Ago" is the whole thesis. Xcode never cleans itself, and every iOS dev eventually writes the script by hand.
Why does Xcode reach 100 GB on a Mac without warning?
Xcode is not one folder. It is a stack of independent caches, device sets, and archives, each managed by a different subsystem, none of them expiring themselves. Every WWDC release adds a new simulator runtime and a new DeviceSupport bucket. Every archive you produce lives forever unless you delete it. Every clean build populates a fresh DerivedData tree. The math is boring and it does not stop.
The System Settings Storage bar reports only Applications/Xcode.app, which is about 15 GB after the SDKs land. The other 85 GB of Xcode reality lives under ~/Library/Developer/ and ~/Library/Caches/, which macOS folds into System Data. If you have been staring at a 180 GB gray bar wondering what's inside, that is where most of it lives. The line-item breakdown is at xcode-vs-system-data-storage.
Which six folders drive the Xcode disk space cleanup?
Every Xcode storage 100GB cleanup on a Mac routes through the same six folders. Sizes below are typical for an active iOS developer machine that has shipped through the last two Xcode releases.
| Folder | Path | Typical size | Regenerable | Risk if deleted |
|---|---|---|---|---|
| DerivedData | ~/Library/Developer/Xcode/DerivedData/ |
20 to 80 GB | Yes, next build | None |
| Archives | ~/Library/Developer/Xcode/Archives/ |
5 to 40 GB | No, review first | Loses App Store binary + dSYM |
| iOS DeviceSupport | ~/Library/Developer/Xcode/iOS DeviceSupport/ |
8 to 30 GB | Yes, on next device connect | Slower first attach per device |
| CoreSimulator devices | ~/Library/Developer/CoreSimulator/Devices/ |
10 to 60 GB | Yes, recreatable | Loses simulator state and installed apps |
| CoreSimulator caches | ~/Library/Developer/CoreSimulator/Caches/ |
5 to 20 GB | Yes | None |
| XCTestDevices | ~/Library/Developer/XCTestDevices/ |
5 to 30 GB | Yes, on next test run | None |
Six folders, six independent growth curves. The total on a healthy but neglected Mac lands between 55 and 260 GB before you count Xcode.app itself.
How do I audit Xcode disk usage on Mac without deleting anything?
Read-only pass first. Nothing gets touched. Paste this into Terminal from any directory.
# Read-only Xcode footprint audit on Mac
{
printf "\n=== Xcode.app ===\n"
du -sh /Applications/Xcode.app 2>/dev/null
printf "\n=== DerivedData ===\n"
du -sh ~/Library/Developer/Xcode/DerivedData 2>/dev/null
printf "\n=== Archives ===\n"
du -sh ~/Library/Developer/Xcode/Archives 2>/dev/null
printf "\n=== iOS DeviceSupport ===\n"
du -sh ~/Library/Developer/Xcode/iOS\ DeviceSupport 2>/dev/null
du -sh ~/Library/Developer/Xcode/watchOS\ DeviceSupport 2>/dev/null
du -sh ~/Library/Developer/Xcode/tvOS\ DeviceSupport 2>/dev/null
printf "\n=== CoreSimulator ===\n"
du -sh ~/Library/Developer/CoreSimulator/Devices 2>/dev/null
du -sh ~/Library/Developer/CoreSimulator/Caches 2>/dev/null
du -sh ~/Library/Developer/CoreSimulator/Volumes 2>/dev/null
printf "\n=== XCTestDevices ===\n"
du -sh ~/Library/Developer/XCTestDevices 2>/dev/null
printf "\n=== SPM cache ===\n"
du -sh ~/Library/Caches/org.swift.swiftpm 2>/dev/null
printf "\n=== Free disk ===\n"
df -h / | awk 'NR==2 {print $4 " available on " $1}'
}
The numbers on the first line of each block are the real footprint. Add them up. If the total is 80 GB or higher, the six-folder pass below is worth 90 to 140 GB of reclaim on the next hour of work.
What is the safe Xcode storage 100GB cleanup order?
Order matters when the Mac is under 5 GB free. Each step is reversible from Finder Trash for seven days on APFS, and each step reclaims a known amount without breaking a project.
- Quit Xcode and any Simulator windows. This releases file locks on CoreSimulator devices and DerivedData.
- Move
~/Library/Developer/Xcode/DerivedData/to Trash with a timestamp. Reclaim: 20 to 80 GB. The safety argument for this specific step is at safely-delete-xcode-deriveddata. - Open Xcode Organizer, review the Archives list, and only then Trash the
~/Library/Developer/Xcode/Archives/entries you no longer need. Reclaim: 5 to 40 GB. Keep the archives for anything you might need to re-symbolicate a crash for. The reasoning is at xcode-archives-folder-explained. - Trash
~/Library/Developer/Xcode/iOS DeviceSupport/subfolders for iOS versions you no longer test on. Reclaim: 8 to 30 GB. Every folder rebuilds on the next attach of a device on that OS version. - Run
xcrun simctl delete unavailableto drop simulator devices tied to runtimes you no longer have installed. Reclaim: 5 to 30 GB from~/Library/Developer/CoreSimulator/Devices/without touching device state you still want. - Trash
~/Library/Developer/CoreSimulator/Caches/in full. Reclaim: 5 to 20 GB. This holds runtime DMGs, dyld caches, and downloaded runtime archives, all regenerable. - Trash
~/Library/Developer/XCTestDevices/with Xcode quit. Reclaim: 5 to 30 GB. The separate test-time simulator set is documented in reclaim-disk-from-xcode-simulators. - Trash
~/Library/Caches/org.swift.swiftpm/for the SPM download cache. Reclaim: 2 to 8 GB. - Run the audit script again. If the total is still above 60 GB and you have not shipped an app since last WWDC, check for orphaned runtimes in
/Library/Developer/CoreSimulator/Volumes/and in~/Library/Developer/CoreSimulator/Volumes/. - Wait seven days. If nothing regressed, empty Trash.
The Trash-first pattern is the safety floor. mv to ~/.Trash gives a five-second restore from Finder if something breaks. rm -rf gives you nothing. The full argument for Move-to-Trash as the default is at move-to-trash-vs-rm-rf.
What do the Trash-first commands look like?
Six one-liners, one per folder. Each stamps the move with a date so a rollback is unambiguous.
STAMP="$(date +%Y%m%d-%H%M%S)"
# 1. DerivedData
mv ~/Library/Developer/Xcode/DerivedData "$HOME/.Trash/DerivedData-$STAMP"
# 2. Archives (review Organizer first)
# mv ~/Library/Developer/Xcode/Archives "$HOME/.Trash/Archives-$STAMP"
# 3. iOS DeviceSupport (delete per-OS subfolders you no longer support)
mv "$HOME/Library/Developer/Xcode/iOS DeviceSupport" \
"$HOME/.Trash/iOS-DeviceSupport-$STAMP"
# 4. Unavailable simulators
xcrun simctl delete unavailable
# 5. CoreSimulator caches
mv ~/Library/Developer/CoreSimulator/Caches \
"$HOME/.Trash/CoreSimulator-Caches-$STAMP"
# 6. XCTestDevices
mv ~/Library/Developer/XCTestDevices \
"$HOME/.Trash/XCTestDevices-$STAMP"
# 7. SPM cache
mv ~/Library/Caches/org.swift.swiftpm \
"$HOME/.Trash/swiftpm-cache-$STAMP"
# Re-audit
du -sh ~/Library/Developer/Xcode/* 2>/dev/null
df -h / | awk 'NR==2 {print $4 " available on " $1}'
Every one of these commands is reversible. Every one leaves the Finder Trash entry as a receipt. None of them ask for sudo. If a build breaks after step 2, dragging DerivedData-<stamp> out of Trash restores the exact tree, index and all.
The per-device DeviceSupport pass is worth its own read at ios-device-support-cleanup because it is the one folder where per-OS surgical delete beats a full sweep.
How much of the Xcode storage 100GB cleanup does simctl cover on its own?
xcrun simctl delete unavailable is the single most useful command in the pass. On a Mac that has survived one WWDC without a cleanup, it reclaims 15 to 60 GB by removing every simulator device tied to a runtime that is no longer installed. It runs in seconds, it never touches DerivedData, and it never invalidates a project.
What it does not cover is where the misconception lives. simctl does not touch DerivedData. It does not touch Archives. It does not touch DeviceSupport. It does not reach XCTestDevices without a --set flag pointing at the test device set, and it does not delete cached runtime DMGs under ~/Library/Developer/CoreSimulator/Caches/. The full pass is the six folders above, not one command.
What does CleanMyDev do that a shell script does not?
A shell script is fine for one machine on one afternoon. It writes to stdout, it deletes with rm, and it forgets everything the moment the terminal closes. That is why every iOS dev ends up with a different variant of the same 40-line script and a lingering fear that this month's run will delete something they still needed.
CleanMyDev maps all six Xcode folders plus SPM plus Xcode preview cache on one screen. Per-row: path, size, last-modified date, owning tool, risk label. You tick the rows you want to reclaim, the cumulative reclaim number updates live, and the deletions land in Finder Trash with a timestamp. It also maps every AI tool footprint (Claude Code, Cursor, Codex, Cline, Ollama, Hugging Face), every JS install cache (npm, pnpm, Yarn, Bun), and Docker.raw on the same screen, so the pass beyond Xcode is one workflow instead of ten.
If you are done writing the cleanup script every WWDC, grab CleanMyDev for $9.99 lifetime on the pricing page. One purchase, no subscription, no telemetry, covers the whole 100 GB Xcode surface plus everything else that hides in System Data.
Related reading
- xcode-disk-space-full-fix for the emergency triage when the build is failing right now.
- orphaned-simulator-runtimes-mac for the AssetsV2 runtimes
simctlcannot reach. - core-simulator-caches-mac for the four subpaths inside CoreSimulator caches and why they regrow.