How to clear Developer storage on a Mac: Xcode, simulators, Docker and package caches
A developer's Mac fills up in places Finder never shows you: ~/Library/Developer, dot-folders in your home folder and Docker's disk image. This guide covers where the space goes, what deleting each folder costs you, and the command that removes it.
The short version
- The biggest wins are usually Derived Data, simulator runtimes you no longer test on, device support folders for old iOS versions, Docker images and build cache, and the npm and Gradle caches.
- All of these come back by themselves when needed. What you lose is time spent rebuilding or downloading again, not data.
- Two things are not caches. Keep the Xcode archives of builds you shipped, because they hold the symbols you need for crash reports. Leave Docker volumes alone unless you know what is in them, because they often hold databases.
- Quit Xcode and the Simulator, and stop Docker containers and Gradle daemons, before you delete their files.
Measure first
On the Mac this guide was written on, Derived Data was 11 GB across 33 projects, one iOS device support folder was 6.6 GB, one iOS simulator runtime was 7.3 GB and the npm cache was 2.0 GB. Your numbers will be different, so look before you delete:
# Xcode and the Simulator
du -hsH ~/Library/Developer/Xcode/* ~/Library/Developer/CoreSimulator/* 2>/dev/null | sort -h
xcrun simctl runtime list
# Package managers and toolchains
du -hs ~/.npm ~/.gradle ~/.cargo ~/go/pkg/mod ~/Library/Caches/* 2>/dev/null | sort -h | tail -15
# Docker
docker system df
The -H matters if you moved Derived Data or Archives to another drive and left a symbolic link behind. Without it, du measures the link and reports almost nothing.
| What and where | Safe to delete? | What it costs you |
|---|---|---|
Derived Data~/Library/Developer/Xcode/DerivedData | Yes | A full build and a re-index the next time you open each project |
Simulator runtimesManaged by xcrun simctl runtime | Yes, for OS versions you don't test on | A multi-gigabyte download if you need it again |
Device support~/Library/Developer/Xcode/iOS DeviceSupport | Yes, for OS versions your devices no longer run | Xcode copies them again the next time you connect that device, which takes a few minutes |
Unavailable simulators~/Library/Developer/CoreSimulator/Devices | Yes | Nothing; they can't start any more |
Previews, docs, simulator caches~/Library/Developer/Xcode/UserData/Previews and others | Yes | Slower first preview or documentation load |
Archives~/Library/Developer/Xcode/Archives | Only old development builds | The dSYMs you need to symbolicate crash reports |
| Docker images and build cacheDocker Desktop's disk image | Yes, if unused | Pulls and rebuilds |
| Docker volumesDocker Desktop's disk image | Only if you know what's in them | Possibly a local database |
npm, pnpm, Yarn caches~/.npm, the pnpm store, ~/Library/Caches/Yarn | Yes | Packages download again on the next install |
node_modulesInside each project | Yes, for projects you aren't working on | One npm install |
Homebrew downloads~/Library/Caches/Homebrew | Yes | Downloads again if you reinstall |
Gradle caches~/.gradle/caches | Yes, with Gradle stopped | Dependencies download again |
Xcode
Derived Data
Derived Data holds build products, intermediate files and the index for every project you have opened in Xcode, one folder per project with a random suffix (for example MyApp-abcdefgh…). Projects you stopped working on months ago are still in it. Quit Xcode, then delete either individual project folders or the lot:
rm -rf ~/Library/Developer/Xcode/DerivedData/*
The trailing /* deletes what is inside and keeps the folder itself, or the symbolic link if you moved it to another drive. Product › Clean Build Folder in Xcode is not the same thing: it removes only the current project's build products and keeps the index.
Simulator runtimes
Since Xcode 15, simulator runtimes are disk images that simctl manages, so you won't find them by browsing folders. Each iOS runtime is several gigabytes; the iOS 27.1 runtime on our Mac was 7.3 GB. List them, check what would go, then delete:
xcrun simctl runtime list
xcrun simctl runtime delete --notUsedSinceDays 30 --dry-run
xcrun simctl runtime delete --notUsedSinceDays 30
Other useful options are --outdated, which deletes runtimes that have a newer version with the same identifier, and a runtime's identifier from the list, which deletes just that one. Xcode › Settings › Components shows the same runtimes, and you can download any of them again from there.
Simulators that can't start any more
When you delete a runtime or update Xcode, the simulators built on older runtimes stay behind. Remove every simulator the current Xcode doesn't support with:
xcrun simctl delete unavailable
Simulators that still work hold your test apps and their data, so delete those only on purpose, from Window › Devices and Simulators.
Device support files
Each time you connect an iPhone, iPad, Apple Watch or Apple TV running a new OS build, Xcode copies that build's debug symbols to the Mac. Every version gets its own folder, named after the device and build, for example iPhone17,2 27.0.1 (24A446), and the folders are never removed. The one on our Mac was 6.6 GB. Delete the folders for versions your devices no longer run:
ls ~/Library/Developer/Xcode/"iOS DeviceSupport"
The same applies to the watchOS DeviceSupport and tvOS DeviceSupport folders next to it.
Archives
Archives are the builds you made with Product › Archive. Each one contains the app plus the dSYM files that turn crash reports from that build into readable stack traces. Keep the archives of everything you shipped. Old development and TestFlight archives can go. Delete them in Window › Organizer so Xcode stays in sync.
The smaller ones
~/Library/Developer/Xcode/UserData/Previews: SwiftUI preview builds.~/Library/Developer/Xcode/DocumentationCache: downloaded documentation.~/Library/Developer/CoreSimulator/Caches: simulator caches, rebuilt on demand.~/Library/Developer/Xcode/iOS Device Logs: copies of logs pulled from your devices.
Docker
Docker Desktop keeps every image, container, volume and build cache inside one disk image. Docker Desktop › Settings › Resources shows where that image lives and caps its size. Finder may show the image at its maximum size even when it is mostly empty, because it is a sparse file, so trust docker system df instead:
docker system df # what is using the space
docker system prune # stopped containers, unused networks, dangling images, build cache
docker system prune -a # also every image no container is using
docker builder prune # just the build cache
Careful with volumes. docker system prune --volumes and docker volume prune delete unused volumes. A volume is often where a local Postgres or MySQL keeps its data. List them with docker volume ls first.
The disk image may not shrink in Finder straight away after a prune; Docker Desktop gives space back to macOS over time.
Package managers and toolchains
npm, pnpm and Yarn
npm cache clean --force # ~/.npm
pnpm store prune # unreferenced packages in the pnpm store
yarn cache clean # Yarn 1; use "yarn cache clean --all" on Yarn 2 and later
Old node_modules folders are often bigger than all the caches together. Find the largest ones:
find ~/Projects -name node_modules -type d -prune -exec du -hs {} + 2>/dev/null | sort -h | tail -20
Replace ~/Projects with wherever you keep your code. Deleting node_modules in a project you aren't working on is safe; npm install or npm ci puts it back.
Homebrew
brew cleanup --prune=all -n # show what would be removed
brew cleanup --prune=all # remove old versions and every cached download
brew autoremove # remove dependencies nothing needs any more
Gradle and Android
Stop Gradle before you touch its caches, or a running daemon may hold files open or write half a cache back:
./gradlew --stop # or: gradle --stop
rm -rf ~/.gradle/caches
Android emulator images are another large item. Delete the devices you don't use from Android Studio's Device Manager rather than from ~/.android/avd by hand.
CocoaPods, Swift packages, Python, Rust and Go
pod cache clean --all # ~/Library/Caches/CocoaPods
rm -rf ~/Library/Caches/org.swift.swiftpm
pip cache purge # or: uv cache clean
cargo clean # inside a Rust project; target/ is usually the big one
go clean -cache -modcache # Go build cache and downloaded modules
What CleanMacster does with all this
The Cleanup scan has an Xcode Junk section. It selects Derived Data, iOS device logs and simulators whose runtime is gone, because Xcode recreates or no longer needs them. It lists device support folders, simulator runtimes and caches, the documentation cache, SwiftUI previews and archives with their sizes, but leaves them unselected, because getting them back means a long download or rebuild. You decide.
The same scan lists every folder in ~/Library/Caches, which is where Homebrew, CocoaPods, Swift Package Manager and pip keep their caches, and the Gradle caches in ~/.gradle. Before it cleans Gradle caches it checks for a running Gradle build or daemon and stops if it finds one.
It doesn't touch Docker, npm, node_modules, Cargo or Go. Those belong to tools that have their own clean commands, listed above. Space Map shows you where they are and how big they have grown.