- The problem. One developer’s Mac was storing 30.18 GB twice. Most of it sat in other apps’ containers and source checkouts, where deleting a copy isn’t safe.
- What we found. A tool that frees space by deleting could honestly offer about 3% of it. APFS can make two identical files share their blocks, so both stay and the space comes back.
- What we built. A scan that shares the copies’ storage across the whole home directory. The first run got back 17.21 GB from 8,414 copies in 28 seconds, and the files passed every check afterwards.
Finding duplicate files does not tell you which copy you can remove. A project may need a file at its current path even when the bytes exist elsewhere. We measured 30.18 GB of duplicate storage on one Mac, then tested when APFS could recover space while keeping both files. The amount your Mac can recover depends on its files and which blocks they already share.
We walked one developer's home directory to find out what was filling it up: 523,217 files, grouped by the space they actually occupy, hashed where two sizes matched, compared byte for byte, with every pair that already shares its blocks on disk thrown out. What was left is 30.18 GB the machine is storing twice, across 44,830 groups.
We could have stopped there and put 30 GB on a page. Reading the same census a second way is what changed the product.
First, count bytes that exist
On a modern Mac the obvious way to count is wrong, and it's wrong in the direction that makes a storage tool look good.
A file's size and the space it takes are different numbers. That home directory measures 670.0 GB by size and 225.5 GB by what's on disk. Most of the gap is 14,759 files that iCloud and other sync clients keep as placeholders: they have a name, an icon and a size, and no bytes behind them. A tool that adds up sizes will promise you hundreds of gigabytes that don't exist, and deleting a placeholder takes away your only copy while freeing nothing.
So every number in this post is allocated bytes. The totals come out smaller, and they're the numbers you can check against your own free space.
Two ways to read 30 GB
The first reading is what the copies are. The largest block is 13.06 GB of AI model weights, and one 2.9 GB model file was sitting in four places at once: an app's container, a test fixture, a backup and a support directory. After that come other app data, build output, then media and documents.
The second reading is where they sit, and that's the one that decided everything. 13.51 GB is inside other apps' containers. 12.69 GB is inside source checkouts. Under a gigabyte is in folders where a cleaning tool is welcome to suggest deleting something.
A tool that frees space by removing files can honestly offer about 3% of what it just found. Nobody wants a cleaner proposing deletions inside another app's container, or in a source tree they're still working in. We could have shipped a scanner that reports 30 GB and acts on 1 GB, as plenty of tools do.
The verb decides the scope
APFS can make two files share the same blocks. The call is clonefile, Finder uses it when you duplicate a file, and it takes no time and no extra space. Both files stay, each with its own name, folder, permissions, timestamps and contents. Only the storage underneath is shared.
On a 200 MB file, the numbers look like this:
The space came back at the moment they started sharing, and neither file noticed.
Because the verb carries no risk, the scope can be the entire home directory instead of the handful of folders where a deletion may be proposed. The net ends up about thirty times wider than a duplicate finder's, and the only reason is that the verb stopped deleting.
One rule holds throughout: the hash never decides a write. It only narrows the field. Before anything is written, the two files are compared byte for byte, so a hash collision can't cost anyone their data.
A scan of the whole home directory, 870,229 files, takes 7.3 seconds the first time and 5.4 after that, down from 59.8 in the first version, so it can run every time you click instead of on a schedule.
A promise you can check
Storage tools are full of numbers nobody can verify. This one has a receipt, and we made the receipt checkable by three unrelated mechanisms.
The promise is what the rows added up to before the run. The receipt is measured afterwards by re-reading each replaced file's private bytes. df is the volume's own accounting and knows nothing about any of this. When the three disagree, the promise was wrong, and we'd rather find that out here than have someone find it on their own disk.
Then we checked the files themselves, against records that existed before the run and that we never write:
- 3,478 copies tracked by Git still hash to the blob Git recorded. Zero differ.
- 1,877 PNGs pass their internal chunk checksums, 77 disk images pass their own data-fork checksum, 11 SQLite databases pass an integrity check, and every ZIP and gzip entry passes its CRC.
- 164 Mach-O signatures are valid, 54 signed app bundles keep their
codesignverdict and their code directory hash, and 20 debug symbol bundles keep their UUIDs. - Two copies of a notarized app still pass Gatekeeper with the same verdict as before.
A file that shares its blocks is still the file it was. Those checks are why we can say it.
Two things the first real run got wrong
It changed two things it shouldn't have: Finder's Date Added and, on 301 of the 8,414 copies in the first whole-home run, the record of which app downloaded the file. Mint now compares each file's attributes before and after, so nothing about the file changes but the space it takes.
What we measured and did not build
macOS has a transparent compression flag, and on this machine the arithmetic was tempting. Sampled across the disk, compression would have given back 57.5 GB, more than sharing blocks, with every file staying fully usable. Apple uses it on most of the system.
If you run coding agents, this is your machine
The 13.06 GB of duplicated model weights is what a machine that runs agents looks like. A Mac that does not run them rarely has that shape.
Agents copy things by design. A model gets pulled once for the app and once into its sandbox container. Every worktree an agent creates carries its own build output. A test fixture holds a copy of the file it tests against. None of this is a mistake, and none of it is something you want to delete by hand, because you can't always tell which copy something depends on.
Sharing blocks fits this case well. You don't need to know which copy matters, because they all keep working, and you don't have to quit the agent or decide anything. On the first whole-home run: 3,262 groups, 8,414 copies, 28 seconds, nothing refused, 17.21 GB back. A fresh scan afterwards found 37 MB left, held open by apps that were running at the time.
What we took from this
The total was never the useful number. The split by location was, because it showed that what a scanner can report and what a cleaner can act on were two different figures, thirty times apart. Everything after that came from changing the verb instead of asking for a wider permission.
A tool that promises space should also be able to prove it afterwards. On a run that touched 8,414 of someone's real files, the promise, the receipt and the volume agreed to the byte.
Decide whether copies should stay
Use the duplicate-files guide to tell files you can remove from copies that should keep working where they are. For a large System Data figure, start with the System Data diagnosis: the category total alone won't tell you what to delete.