What's Taking Up All the Space on My Developer Mac?
Find which developer tool is filling your Mac’s disk, such as uv, Xcode or Docker, and which cleanup applies.

On this page
TL;DR
Record the free space, then narrow down one level at a time with du until a
directory belongs to one tool. That tells you which cleanup you need. Clean it
with that tool’s own command where it has one, never with rm on a cache a
tool manages, and record the free space again; the cleanup’s own report is not what the Mac got back.
$ diskutil info / | grep "Container Free Space"
$ du -hd 1 ~ 2>/dev/null | sort -hr | head -15Tested with
- macOS
- 27.0.1, MacBook Pro (Apple silicon)
- Date
- October 2026
My Mac had 37.7 GB free on a 1 TB disk. I expected Xcode to be the reason,
since I keep a full set of iOS simulators, and Xcode did hold 79 GiB. The
largest directory was a 132 GiB uv cache, which I had never thought about: most
of the entries in it were environments uvx had built for MCP servers,
covered in part 2.
Which directory is largest on your Mac depends on what you build and which
tools you run. The method for finding it is below, and the
series covers each cause.
Record the free space before you start
On a modern Mac, df -h / reports the sealed system volume, so its Used
column is misleading:
$ df -h /Output
Filesystem Size Used Avail Capacity iused ifree %iused Mounted on
/dev/disk3s1s1 926Gi 13Gi 40Gi 24% 484k 423M 0% // is the sealed system snapshot. Your files live on the Data volume in the
same APFS container. Every volume in a container draws on one pool of free
space, so Used for / counts the system alone, and Avail is the pool. The
container’s own figure comes from the startup disk’s container only, so an
external APFS drive cannot be mistaken for it:
$ diskutil info / | grep "Container Free Space"Output
Container Free Space: 65.8 GB (65847853056 Bytes) (exactly 128609088 512-Byte-Units)This reading was taken after the cleanup, so it does not match the df
output above, which was taken partway through, or the 37.7 GB before any
cleanup. df -h prints GiB and
diskutil prints GB, so the same moment looks different in the two units. Use one of them for every reading, or the difference
between the units looks like progress. A Mac keeps writing while you work, so
treat a change of a gigabyte or two as noise.
Find what’s taking up space with du
du reads sizes and changes nothing. 2>/dev/null hides the permission
errors that protected directories print.
List the largest directories in your home directory:
Command$ du -hd 1 ~ 2>/dev/null | sort -hr | head -15Skip the first line, which is the total for the directory you ran it on. Run the same command on the largest directory below it, and repeat until the directory belongs to one tool. On this Mac, that took three levels:
~/.cache, then~/.cache/uv, then~/.cache/uv/archive-v0.Check the two places that hide the most, even if they didn’t top the first list:
Command$ du -hd 1 ~/Library/Caches 2>/dev/null | sort -hr | head -15 $ du -hd 1 ~/Library/Developer 2>/dev/null | sort -hrFor a package manager, ask the tool where its cache is rather than assuming a path. pip on macOS uses
~/Library/Caches/pip, not~/.cache/pip:Command$ uv cache dirOutput
/Users/<user>/.cache/uvCommand$ python3 -m pip cache dirOutput
/Users/<user>/Library/Caches/pip
A du total is an upper bound on what deleting frees. APFS clones share
their blocks with the original until one of them changes, and du counts a
cloned file at full size wherever it appears.
Match the directory to its cause
These are the directories that were large on this Mac, and the part of this series that covers each one:
| Directory and what fills it | Size here | Covered in |
|---|---|---|
~/.cache/uvEnvironments that uvx builds for MCP servers | 132 GiB | Part 2 |
~/Library/Developer/CoreSimulator/DevicesiOS simulators and the apps installed in them | 44 GiB | Part 5 |
~/Library/Developer/Xcode/iOS DeviceSupportDebug symbols for each device and iOS version you’ve connected | 35 GiB | Part 5 |
~/Library/Containers/com.docker.dockerDocker Desktop’s VM disk, Docker.raw | 32 GiB | Part 3 |
~/.npm/_npxPackages that npx runs, MCP servers among them | 8.9 GiB | Part 4 |
.build, node_modules, .venv in your projectsBuild output and dependencies, including projects you no longer work on | varies | Part 6 |
~/Library/Caches/HomebrewCached downloads of formulae and casks | 1.1 GiB | Below |
~/.ollama/logsOllama’s server and app logs | 947 MB | Below |
For the uv cache, read part 2 before you prune: a running coding session holds a lock that makes the prune wait, and the prune reports far more than the disk gets back. The other parts are listed on the series page.
Some directories stay whatever their size. A Docker volume holds an app’s
data, not cache. An app’s Application Support directory holds its state.
Clear Homebrew downloads and Ollama logs
Two directories on the list need no part of their own.
brew cleanup -s removes old versions and the cached downloads of anything no
longer installed. It keeps the downloads of what is installed now, so on this
Mac it freed about 270 MB of the 1.1 GiB:
$ brew cleanup -sAn app can keep its data somewhere else and still write its logs to the internal disk. My Ollama models live on an external SSD, linked into place:
$ ls -ld ~/.ollama/modelsOutput
lrwxr-xr-x 1 <user> staff ... /Users/<user>/.ollama/models -> /Volumes/<drive>/ollama/modelsThe logs aren’t linked. List them first:
$ ls -lh ~/.ollama/logsHere they had reached 947 MB in two files, server-1.log and app-1.log.
Yours may have other names. Ollama has no cleanup command for them, so quit
Ollama and delete the files that list showed, by name:
$ rm ~/.ollama/logs/server-1.log ~/.ollama/logs/app-1.logDeleting a log leaves the models and the settings as they are.
Ollama wasn’t in Open at Login, but App Background Activity, under System Settings > General > Login Items, allowed it to run in the background. I turned that off. I didn’t check whether background runs are what filled the logs.
Record the free space again
Run the same command you started with:
$ diskutil info / | grep "Container Free Space"Here it went from 37.7 GB before any cleanup to 65.8 GB after the uv prune. The cleanup commands had reported more than 140 GB between them. A cleanup command reports what it removed from its own storage; only the container’s figure says what the Mac got back.
Do this with a coding agent
Paste this prompt into your own local coding agent. It finds and reports, and it deletes nothing:
Find what is taking up space on this Mac's internal disk. Measure and report
only; delete, prune or clean nothing. Stay in my home directory, and don't
follow links to external drives.
1. Report free space with diskutil info / (Container Free Space) and
df -h /, and say which units each prints.
2. Run du -hd 1 on my home directory, then on the largest subdirectory it
lists (not the total line for the directory itself), and keep going down
until each large directory belongs to one tool. Also check
~/Library/Caches and ~/Library/Developer. Ask package managers for their
cache paths (for example uv cache dir, python3 -m pip cache dir) instead of
assuming them.
3. For each directory over 1 GB, report its size, which tool owns it, what
fills it, and the tool's own cleanup command if it has one.
4. Mark anything that is in use or holds work: running processes using the
directory (lsof), open coding-agent or editor sessions, uncommitted or
unpushed changes in any git checkout, Docker volumes, app data under
Application Support. Say what would be lost if each were removed.
5. Note that du counts APFS clones at full size, so a total is an upper bound
on what deleting frees.
Then stop and wait. I will choose what to clean.Common failures
Free space barely moved after a cleanup
Docker reports space inside its VM disk, and du and uv cache size count
cloned files at full size. Measure the container with diskutil info /
before and after; that is the only figure that says what the Mac got back.
With Time Machine on, a local snapshot can keep a deleted file’s space in use. Time Machine keeps hourly snapshots for 24 hours and deletes them as they age or as space is needed, per Apple’s Time Machine guide (opens in a new tab). List them; on this Mac the list was empty:
$ tmutil listlocalsnapshots /uv cache prune waits, then times out
uv cache prune waits while any other uv process is running, and every uvx
server counts. After five minutes by default (UV_LOCK_TIMEOUT) it gives up;
the uv cache documentation (opens in a new tab) covers
the lock. Quit the coding sessions that started the servers, then run it again.
To see what holds the lock:
$ lsof "$(uv cache dir)/.lock"Part 2 shows how to find which session holds it.
npm cache clean left ~/.npm large
npm cache clean --force empties npm’s package cache, _cacache. The space
is in _npx, where npx
keeps the packages it runs; part 4 covers it.