Repository navigation
Understanding System Data
System Settings > General > Storage sorts files into Applications, Documents, Photos, Music, Developer, macOS and other lines. System Data is the remainder: whatever the classifier did not put in another line. There is no folder called "System Data" on disk.
To explain N GB of System Data you have to measure the whole Data volume and account for what Settings already placed elsewhere. There is no shortcut.
In practice, most of it is ~/Library. In the audit that started this project (about 166 GB of System Data), ~/Library alone was about 153 GB, with the rest in /private/var, /opt/homebrew, /Library and /usr/local.
-
macOS in Settings is the sum of the separate system volumes in the same APFS container (System, Preboot, Recovery, Update, VM). They are not inside System Data. SDTally reads them with
diskutiland DiskArbitration (containersin the JSON). -
System Data is computed by Apple's
StorageManagementServiceand written to the system log while the Storage pane is open. SDTally reads that log line (settings_screen) and also reproduces the screen from the pane's own "Sum of categories" line. The log keeps it for less than about 21 hours. -
Available in Settings is free space plus purgeable space: caches macOS can remove on its own (CacheDelete). Tools such as
dfdo not count purgeable as free.
SDTally also reproduces 15 of the Settings categories from what it measures (system_data.reproduced), each graded A (rule read in Apple's code) or B (hypothesis or approximation), and compares them with the screen when the pane's log is available.
| Where | What it is | Notes |
|---|---|---|
~/Library/Mobile Documents |
iCloud Drive data | Real user data, synced across devices. Not a cache |
~/Library/Application Support |
App state | Mixed: real data and regenerable data |
~/Library/Caches |
Caches | Usually regenerable, with exceptions (for example a cache in use by an active upload) |
~/Library/Containers, ~/Library/Group Containers
|
Data of sandboxed apps | Mixed. Messaging apps keep real media here |
~/Library/Preferences |
Settings files | Should be kilobytes. Gigabytes here are an anomaly |
~/Library/CloudStorage |
Google Drive, Dropbox, OneDrive and others | Mostly placeholders |
Dotfolders in your home (~/.npm, ~/.ollama, ...) |
Developer tool caches and models | Often missed by tools that skip hidden files |
| Local snapshots | Time Machine and other snapshots | Hold blocks of files you already deleted |
| Swap, sleep image | Virtual memory | On the VM volume |
| Open-but-deleted files | Files deleted while an app still has them open | Space returns when the app closes them |
| APFS metadata | The file system's own trees | Not a file anywhere |
Four ways a disk misreports its own size, all observed in the audit. A tool that ignores any of them produces a wrong report. SDTally handles each one.
A sparse file declares a large size but only allocates the blocks that were written. VM disks are the classic case: one observed disk declared 100 GB and occupied 2.66 GB.
- Wrong:
statst_size,du --apparent-size, Finder's "Size". - Right: allocated blocks (
st_blocks,stat -f %b). Plaindualready uses them. - SDTally: counts allocated size only.
iCloud Drive, OneDrive and Google Drive keep files "online only": the file appears with its full size, but the content is not on disk. macOS marks these with the SF_DATALESS flag. In the audit, two copies of one video in two OneDrive folders appeared as 72 GB; the folders actually occupied under 2 GB.
The worse trap: reading a dataless file downloads it. A duplicate finder that hashes everything can download hundreds of gigabytes and fill the disk it was meant to clean.
- SDTally: sets its process policy so dataless files are never materialized, never descends into dataless folders, reports them separately (
informational.dataless, apparent size) and counts them as 0 on disk.
clonefile(2) creates a new file that shares blocks with the original (copy on write). Both report their full size and du counts both, but the blocks exist once. Deleting one copy may free nothing.
- SDTally: reads each file's physical extents (
F_LOG2PHYS_EXT) and counts each shared block once in the tree. For each row it reports private bytes ("freed if deleted"): what deleting it would actually return. Repeated clones are listed underinformational.repeated_full_clonesandrepeated_shared_blocks.
Shell globbing (du -sh ~/*) skips names that start with a dot. On a developer's Mac that hides caches like ~/.ollama, ~/.npm, ~/.colima, ~/.rustup: about 21 GB in the audit.
- SDTally: the traversal includes hidden entries.
-
Hard links and firmlinks: deduplicated by device and inode, so
/Applicationsand similar firmlinked paths do not count twice. - Graft roots: skipped, because their blocks are already counted.
- Mount points: the traversal does not cross into other volumes.
-
Folders the traversal cannot open: counted through APFS directory statistics when APFS keeps them (
protected_folders), otherwise listed inprotected_without_size. -
Large extended attributes: measured with
listxattr(large_xattrs). - Access times: the process disables atime updates, so measuring does not write metadata.
-
GB vs GiB: Settings uses GB (10^9).
duanddfuse GiB (2^30), about 7 percent different. SDTally uses GB by default and labels it;--binaryswitches to GiB.
SDTally adds up only parts that do not overlap:
used (Data volume) = tree + large_xattrs + snapshots + deleted_open + protected_folders + apfs_metadata + unexplained
Everything else (purgeable, repeated clones, cloud-only files, Trash age, Time Machine state) is informational: either already inside one of the terms or a different kind of measure. The text output keeps the two apart, and the JSON puts them under informational.
unexplained is what is left: the space macOS would not let SDTally see (without root or Full Disk Access) plus anything not measured. Running as root with Full Disk Access makes it small. In the text output it is labeled "Blocked by macOS".
Deleting something does not always return its size. SDTally lists only causes it measured at 1 GB or more:
| Cause | Why |
|---|---|
| Local snapshots | A snapshot still holds the deleted file's blocks until the snapshot is removed. macOS removes Time Machine snapshots on its own when space runs low |
| Open-but-deleted files | The app that has the file open keeps the space until it closes it. Quitting the app or restarting returns it |
| APFS clones | Blocks shared with another file stay until the last copy is gone |
| Cloud-only files | They were not taking disk space to begin with |
| Purgeable | Settings already counts it as available; df does not count it as free until macOS releases it |
| Trash | Space returns only when the Trash is emptied |
Recommendations come from fixed rules over measured rows. Each has a level:
| Level | Meaning |
|---|---|
measurement |
Measure better first (for example grant Full Disk Access or measure as administrator) |
system_handles |
macOS manages this on its own |
safe |
Regenerates or is disposable; no loss of function |
cost |
Regenerates, but you pay in time or bandwidth (rebuilds, re-downloads, reindexing) |
check_first |
Depends on state that must be checked first (active sync, app open) |
anomaly |
Unusual; explained for a human to judge |
do_not_touch |
Real data or system data |
Recommended steps go through Finder, the owning app, System Settings, or an official command from a fixed list (with its dry-run form). SDTally never recommends touching /System, disabling SIP, or deleting local snapshots other than through tmutil, and it never runs any of these steps itself.
Further reading in the repository (Portuguese): storage model, measurement pitfalls, target catalog.
Getting started
Understanding
Reference
Trust
Development