Repository navigation
CLI reference
sdtally explains macOS System Data with measurements, no estimates. It is read-only and writes nothing to disk, not even a cache. Grant Full Disk Access to your terminal app before using it.
- Text and JSON go to stdout. Errors go to stderr. A progress counter goes to stderr only when stderr is a terminal.
-
sdtally --helpprints the built-in usage;sdtally --versionprints the version. - Where to find it: inside the app at
SDTally.app/Contents/Helpers/sdtally, or attarget/release/sdtallyaftercargo build --release.
sudo sdtally [--top N] [--json] [--binary] [--lang pt|en] [--color auto|always|never]
sdtally <path> [--top N] [--depth N] [--json]
sdtally why <path> [--json]
sdtally --quick --json [--since EPOCH_SECONDS] [--parts LIST] [--redact names|off]
sdtally --quick --json --watch
sdtally --auto
sdtally --last --json [--redact names|off]
sdtally --history --json [--redact names|off]
sdtally --mcp [--redact off]
sdtally --redact names --stdin
sdtally --catalog --json
sdtally --verify [--json]
The Data volume account: the Settings screen reproduced, what takes the most space, what was partial or not measured, the unexplained remainder, informational blocks (purgeable, repeated clones and hard links, cloud-only files, APFS metadata, Trash by age) and "Why space may not come back".
- Run with
sudofor the complete breakdown. Without root it still runs, marked INCOMPLETE (no sudo) with the list of what is missing. - With
sudo, the home folder measured is the one ofSUDO_USER. - Ctrl-C stops the scan and prints the partial report marked INCOMPLETE (interrupted); exit code 130.
-
--jsonprints the whole report as JSON, including the full ranking,advice("What to Do") andnot_freed. See JSON output.
The children of a folder by unique allocated size, with freed if deleted (the private bytes: what deleting it would actually give back, excluding blocks shared with clones). The path must be a folder on the Data volume; other volumes are refused.
sdtally ~/Library --top 10
sdtally ~/Library --depth 2
sdtally ~/Library/Caches --jsonRoot is not needed. Protected folders show as protected, without private bytes.
Raw attributes of one file or folder: logical and allocated size, private size, file ID, clone ID, flags, link count, xattr count and size, and for folders whether it is a graft root and its APFS directory statistics.
sdtally why ~/.colima
sdtally why ~/Library/Caches --jsonOnly what changes all the time, without scanning the disk: the Settings screen, used, free (capacity), purgeable by service, APFS containers and swap. Requires --json. No root.
| Option | Meaning |
|---|---|
--since EPOCH_SECONDS |
The start time of the previous reading. Reads the Settings log only from there on, and only while the Storage pane is open. With the pane closed the log is not read and settings_screen.screen is not_measured
|
--parts LIST |
Comma-separated subset of meta, volumes, swap, uso, purgeable, tela. Keys of other parts are left out of the JSON. An unknown name or an empty list is an error |
--watch |
Follows the Settings log (log stream) and writes one compact JSON line per new Storage screen, until stdin closes. Not combinable with --since or --parts
|
One full pass, then only the folders FSEvents reports. Writes one compact JSON line per change of 10 MB or more (and periodically for smaller changes), until stdin closes. As root (the app's helper runs it this way when "Automatic with root" is on) it also opens protected folders. Takes no other options. See Automatic vs Full measurement.
They read what the app saved in ~/Library/Application Support/SDTally/Medicoes/. They never measure.
-
sdtally --last --json: the newest full measurement, re-serialized. -
sdtally --history --json: a summary of every saved measurement, oldest first (generated_at,tool,root,full_disk_access,complete,used,unexplained,percent_of_used).
Both require --json and refuse to run as root. Symlinks, files over 20 MB and files with an unexpected schema are skipped with a warning on stderr.
An MCP server over stdio (JSON-RPC 2.0, one message per line) with three tools and no arguments: quick, last_measurement, history. Redacts personal names by default; --redact off disables that. Refuses root. See JSON output.
claude mcp add sdtally -- sdtally --mcpReads a measurement JSON from stdin (up to 20 MB) and prints it with the user name and personal folder names replaced. This is what the app uses for exports with "Replace Personal Names" on.
sdtally --redact names --stdin < measurement.json > shareable.jsonAll explanation cards (what an item is, whose it is, what is lost, whether macOS cleans it on its own, the next step, references, the macOS version it was checked on) and, for every data source, how it was checked against Apple's numbers. Requires --json.
Checks, now and side by side, the numbers that an Apple command shows the same way: Data volume used against df -k, swap against sysctl vm.swapusage, Time Machine snapshots against tmutil listlocalsnapshots /. Each check runs Apple's command, then sdtally's reading, then Apple's command again; the result is equal, within (the disk changed between readings) or outside. Sources that cannot be checked this way are listed as not_checkable with the reason. Refuses root.
Exit code: 0 if nothing is outside, 1 if something is outside, 2 on a usage error.
| Option | Applies to | Meaning | Default |
|---|---|---|---|
--top N |
text output | Ranking lines shown (JSON always has the full ranking) | 15 |
--depth N |
<path> |
Levels below the path | 1 |
--json |
most modes | JSON on stdout | off |
--quick |
Quick mode; requires --json and no path |
off | |
--since EPOCH_SECONDS |
--quick |
Incremental Settings log reading | off |
--parts LIST |
--quick |
Only these parts | all |
--watch |
--quick --json |
Follow the Settings log | off |
--binary |
text output | GiB (2^30) instead of GB (10^9) | GB, as in System Settings |
--lang pt|en |
text output, messages | Language |
pt if the first non-empty of LC_ALL, LC_MESSAGES, LANG starts with pt, otherwise en
|
--color auto|always|never |
text output | Color |
auto: only on a terminal and without NO_COLOR
|
--redact names|off |
measurement JSON (--json, --quick, --last, --history, --mcp, --stdin) |
Replace the user name and personal folder names | on only with --mcp
|
-V, --version
|
Print the version and exit | ||
-h, --help
|
Print help and exit |
Numbers given to --top and --depth must be greater than 0.
-
--quickonly with--jsonand no path. -
--sinceand--partsonly with--quick. -
--watchonly with--quick --json, without--sinceor--parts. -
--lastand--historyrequire--json;--mcpgoes without--json. None of them takes a path,--quickor another of them. -
--catalogrequires--jsonand takes no path or other mode. -
--stdinrequires--redact namesand takes no path or other mode. -
--verifytakes no path,--quickor other mode. -
--autotakes no other options. -
--redactonly where a measurement JSON is printed.
Breaking a rule prints a message and exits with code 2.
| Code | Meaning |
|---|---|
| 0 | Success |
| 1 |
--verify found a value outside Apple's; or the safety policies could not be set (nothing was read) |
| 2 | Usage error, refused path, or a mode that failed (for example no saved measurement for --last) |
| 130 | Interrupted with Ctrl-C (a partial report was printed) |
| Variable | Effect |
|---|---|
LC_ALL, LC_MESSAGES, LANG
|
Default language |
NO_COLOR |
Disables color in auto mode |
SUDO_USER |
With sudo, whose home folder is measured |
SDC_PANIC=1 |
Development and CI: print panic messages on stderr instead of recording them as stage errors |
- The System Data line comes from the Storage pane's log, which keeps the value for less than about 21 hours. Open System Settings > General > Storage, wait for it to load, and run again if it says there is no record.
-
Units: GB means 10^9 bytes, like System Settings. Use
--binaryfor GiB. -
Safety: before reading anything,
sdtallydisables, for its own process, materializing dataless files and updating access times. If that fails, it exits without reading.
Getting started
Understanding
Reference
Trust
Development