AI agents and git worktrees are filling your Mac's disk

Updated 19 October 2026

Coding agents that work in parallel usually give each task its own git worktree, so one agent's edits can't collide with another's. Claude Code, for example, creates them under .claude/worktrees/ in your repository. Source code is small. The build output each worktree produces is not, and every worktree builds its own. Here is why it adds up, how to measure it and how to keep it down.

Why worktrees multiply build output

A worktree is a separate checkout of the same repository in its own folder. Git shares the history between them, but build tools treat each folder as a different project:

Removing a worktree's folder takes its target and node_modules with it. DerivedData in Xcode's default location and extra simulators stay behind, so they keep piling up after the agents are done.

How to measure it

Inside any checkout of the repository, list its worktrees and the size of each:

git worktree list
git worktree list --porcelain | sed -n 's/^worktree //p' | while IFS= read -r wt; do du -sh "$wt"; done

If your worktrees live inside the main checkout, as with .claude/worktrees/, the main checkout's total includes them.

To see which project each DerivedData folder belongs to, with its size:

for d in ~/Library/Developer/Xcode/DerivedData/*/; do
  printf '%s\t%s\n' "$(du -sh "$d" | cut -f1)" "$(plutil -extract WorkspacePath raw "$d/info.plist" 2>/dev/null)"
done | sort -hr

Each folder's info.plist records the path of the project it was built from, so several entries for the same project at different worktree paths are the duplicates.

Simulators and their runtimes:

du -sh ~/Library/Developer/CoreSimulator
xcrun simctl list devices
xcrun simctl runtime list

Keep Xcode DerivedData inside each worktree

Open Xcode › Settings › Locations and set Derived Data to Relative. Xcode then puts build output in a DerivedData folder next to the project or workspace, inside the worktree, instead of in ~/Library. When the worktree goes, its build output goes with it.

This setting applies to every project you open in Xcode, not just one. Two things to do with it:

Folders already in the default location stay there. Delete the ones for worktrees you have removed, or see how to clear Xcode DerivedData.

Clean up simulators

Remove devices whose runtime is no longer installed. This only deletes devices that can't run anyway:

xcrun simctl delete unavailable

Remove a device an agent created and you no longer need, using its UDID from xcrun simctl list devices. This deletes the device and the apps and data on it:

xcrun simctl delete <UDID>

Runtimes are the largest part, several GB each. List them, then delete one you no longer test on by its identifier from the list:

xcrun simctl runtime list
xcrun simctl runtime delete <identifier>

Run xcrun simctl help runtime to see the options your Xcode version supports. You can also remove runtimes in Xcode › Settings › Components (Platforms in older versions of Xcode): click the information button next to a runtime and then Delete. Check the size of ~/Library/Developer/CoreSimulator afterwards, since a runtime can take a while to be removed.

Shrink each Rust target folder

Most of a debug build's size is debug info, and most of that is for dependencies you never step through. In the Cargo.toml at the root of your workspace:

[profile.dev.package."*"]
debug = false

"*" matches every dependency but none of your workspace's own packages, so your code keeps full debug info and backtraces still show your own file and line numbers. The cost is that you can't inspect variables inside dependency code in a debugger. Dependencies recompile once after the change, and every worktree's target is smaller from then on. Cargo only reads profiles from the workspace root, so a setting in a member crate's Cargo.toml is ignored.

Share compiled dependencies with sccache

sccache caches compiler output, so when a second worktree compiles the same dependency at the same version, it is copied from the cache instead of compiled again. Install it and turn it on for every Cargo build:

brew install sccache

Then in ~/.cargo/config.toml:

[build]
rustc-wrapper = "sccache"

Check that it is getting hits with sccache --show-stats.

This saves build time, not disk space. Each worktree still gets a full target folder, and the cache itself lives in ~/Library/Caches/Mozilla.sccache and grows up to 10 GB by default (set SCCACHE_CACHE_SIZE to change it). It also has limits:

Pointing every worktree at one shared target folder with CARGO_TARGET_DIR would save disk, but Cargo locks the build directory while it builds, so parallel agents end up waiting on each other.

Delete build output when you retire a worktree

Remove finished worktrees with git rather than by deleting the folder:

git worktree remove <path>

This deletes the worktree folder, including gitignored build output inside it such as target, node_modules and a Relative DerivedData folder. Things to know:

To keep a worktree but free its space, delete just its build output inside it with cargo clean and rm -rf node_modules. Both come back on the next build or install.

Or find it all in one scan

SymbolSweep finds Rust target folders, node_modules and Xcode DerivedData across your project folders, including the worktrees inside them, and lists each with its size and project. Scanning is free and never deletes anything. Build output you choose to delete is moved to the Trash, so you can put it back, and simulators are listed with instructions rather than deleted.

Download for Mac

Deleting needs a one-time $12 license for one Mac. Requires macOS 13 or later on Apple silicon. See how it works.

FAQ

Does git worktree remove delete the build output inside the worktree?

Yes, if the build output is gitignored. git worktree remove deletes the whole worktree folder, including ignored folders such as target, node_modules and a Relative DerivedData folder. It refuses if there are untracked or modified files unless you pass --force. It doesn't touch DerivedData in Xcode's default location, simulators or the sccache cache.

Why not point every worktree at one shared Cargo target folder?

It saves disk, but Cargo locks the build directory while it builds, so parallel agents end up waiting for each other. That defeats the point of running them in parallel.

Does sccache reduce disk usage?

No. It saves build time by reusing compiled dependencies across worktrees, but each worktree still gets its own target folder, and the cache itself uses up to 10 GB by default.

Does each worktree get its own iOS simulators?

No. Simulator devices and runtimes are shared by every project on the Mac. They grow when agents create extra devices to test in parallel and when old runtimes pile up.

Related guides