Command lineSee what uses space
Seeing what uses space
Scan a scope, then ask the saved scan where the space went, by folder, file, bucket, file type and over time.
These commands read. scan walks the disk and saves the result; the others answer from the newest saved scan, or rescan first with --refresh. Every one accepts a scope: --scope drive (the default), --scope data, or --path PATH. See Scans and scopes.
census scanRead-only
Usage
census [scan] [PATH] [SCOPE] [--full] [--no-save] [--workers N] [--backend MODE] [--verbose] [--progress] [--json]Scans a scope and saves its tree and report for later queries. scan is the default command, so census alone scans the startup drive.
| Option | Description |
|---|---|
--scope KIND | drive (the whole startup drive, the default) or data |
-p, --path PATH | Scan this folder. A bare PATH does the same. |
--full | Walk the whole scope even when the saved scan could be updated |
--no-save | Don’t update the saved scan or history |
-j, --workers N | Traversal workers (1–128) |
--backend MODE | auto, std or bulk |
--verbose | Print scan diagnostics before the summary |
--progress | Write scan progress as NDJSON to stderr |
--json | Write one JSON response |
# The whole startup drive
census
# One folder, with progress events on stderr
census scan --path /Applications --json --progress 2>progress.ndjson
{
"schema_version": 5,
"command": "scan",
"status": "complete",
"exit_code": 0,
"errors": [],
"warnings": ["…"],
"metrics": { "files_seen": 130141 },
"read_errors": { "actionable_total": 0 }
}
The JSON keeps the full scan report, shortened above. coverage_details compares the scan with the disk:
| Field | Meaning |
|---|---|
capacity.volume_name | The volume’s name in Finder, such as Macintosh HD. |
capacity.total_bytes, used_bytes, free_bytes | The container’s size, space in use and free space. used_bytes matches diskutil. |
capacity.purgeable_bytes | Space macOS can free on its own, which Finder counts as available. null when macOS doesn’t say. |
capacity.hidden_bytes | Used space in no file the scan could read: snapshots, staged updates, Recovery, protected or unreadable folders. null for folder scans. |
volumes[].used_bytes, volumes[].scanned_bytes | Each volume’s space in use, and what the scan counted on it. |
access_hint | What would let the scan see more: full_disk_access_required, other_accounts_unreadable (run with sudo), or null. |
capacity is null when it couldn’t be read.
census reportRead-only
Usage
census report [SCOPE] [--refresh] [--progress] [--json]Shows the last saved scan report for a scope. --refresh scans again first.
census report
census report --path /Applications --json
{
"schema_version": 5,
"command": "report",
"status": "complete",
"exit_code": 0,
"errors": [],
"warnings": ["…"],
"scan_id": "…",
"metrics": { "files_seen": 130141 },
"read_errors": { "actionable_total": 0 }
}
census breakdownRead-only
Usage
census breakdown [SCOPE] [--refresh] [--progress] [--json]Shows how the scanned space is grouped into storage buckets, such as macOS, Applications, Developer, AI agents, Caches and System Data. For a folder scan, it says that only that folder is included, and the JSON sets partial_scope to true.
census breakdown
census breakdown --path /Applications --json
{
"schema_version": 5,
"command": "breakdown",
"status": "ok",
"exit_code": 0,
"errors": [],
"warnings": [],
"results": {
"buckets": [
{
"bucket": "applications",
"label": "Applications",
"allocated_bytes": 5491449856,
"files": 130141,
"share": 1.0
}
],
"partial_scope": true,
"total_allocated_bytes": 5491449856
}
}
census topRead-only
Usage
census top [SCOPE] [--files] [--kind KIND] [--min-size SIZE] [--older-than DAYS] [--under PATH] [--depth N] [--limit N] [--refresh] [--progress] [--json]Shows the largest folders. With --files, the largest files.
| Option | Description |
|---|---|
--scope KIND | drive (the default) or data |
-p, --path PATH | A folder’s own scan |
--files | List files instead of folders |
--kind KIND | With --files, only this kind: video, audio, images, documents, archives, disk_images, code, apps, app_data or other |
--min-size SIZE | With --files, at least this size: bytes, or a K, M or G value |
--older-than DAYS | With --files, not modified in the last DAYS days |
--under PATH | Only within this folder (default: the scan’s root) |
--depth N | Folder depth to look down (default: 3) |
--limit N | Show at most N rows (default: 20; 0 means all) |
--refresh | Rescan first; otherwise the saved scan is read |
--progress | With --refresh, write scan progress as NDJSON to stderr |
--json | Write one JSON response |
# Largest folders, three levels deep
census top
# Largest folders inside ~/Applications, two levels deep
census top --under ~/Applications --depth 2
# Code files of 1 MB or more, untouched for a year
census top --files --kind code --min-size 1M --older-than 365 --limit 10
The filters combine before the row limit. Files with an unknown modification time never match --older-than.
census top --path /Applications --limit 1 --json
{
"schema_version": 5,
"command": "top",
"status": "ok",
"exit_code": 0,
"errors": [],
"warnings": [],
"scan": { "scope_kind": "path", "scan_id": "…" },
"results": [
{
"path": { "display": "/Applications/Xcode.app/Contents", "lossy": false },
"allocated_bytes": 3891544064,
"files": 125827,
"folders": 29829,
"share": 0.7087
}
]
}
With --files, results is an object holding files and the filters you chose:
{
"results": {
"files": [
{
"path": { "display": "/Applications/ChatGPT.app/Contents/Resources/app.asar", "lossy": false },
"kind": "apps",
"allocated_bytes": 480194560,
"logical_bytes": 480193694
}
],
"filters": { "kind": null, "min_size_bytes": null, "older_than_days": null }
}
}
census lsRead-only
Usage
census ls [PATH] [SCOPE] [--sort size|name] [--limit N] [--refresh] [--progress] [--json]Shows a saved folder’s contents, largest first. PATH defaults to the scan’s root. Without a scope, it reads the newest saved scan that contains PATH.
| Option | Description |
|---|---|
--scope KIND | drive (the default) or data |
-p, --path PATH | A folder’s own scan |
--sort ORDER | size (the default) or name |
--limit N | Show at most N rows (default: 50; 0 means all) |
--refresh | Rescan first; otherwise the saved scan is read |
--progress | With --refresh, write scan progress as NDJSON to stderr |
--json | Write one JSON response |
census ls ~/Applications --limit 50
census ls ~/Applications --sort name --json
{
"schema_version": 5,
"command": "ls",
"status": "ok",
"exit_code": 0,
"errors": [],
"warnings": [],
"scan": { "scope_kind": "path", "scan_id": "…" },
"results": {
"directory": {
"path": { "display": "/Applications", "lossy": false },
"files": 130141
},
"entries": [
{
"name": { "display": "Xcode.app", "lossy": false },
"kind": "folder",
"allocated_bytes": 3891544064
}
],
"truncated": 5
}
}
truncated counts the entries --limit left out.
census typesRead-only
Usage
census types [SCOPE] [--under PATH] [--limit N] [--refresh] [--progress] [--json]Shows file types and their share of the scan. It groups files by their package, their Library location, or their extension, without opening them. Apps (.app bundles) count as a whole, and libraries such as .photoslibrary count as their media kind. The kinds add up to the folder’s total.
| Option | Description |
|---|---|
--scope KIND | drive (the default) or data |
-p, --path PATH | A folder’s own scan |
--under PATH | Only within this folder. Default: the scan’s root for a folder scan, your home folder for a drive or data scan. |
--limit N | Show at most N kinds (default: all; 0 means all) |
--refresh | Rescan first; otherwise the saved scan is read |
--progress | With --refresh, write scan progress as NDJSON to stderr |
--json | Write one JSON response |
# File types in your home folder
census types
# File types in /Applications
census types --under /Applications --json
{
"schema_version": 5,
"command": "types",
"status": "ok",
"exit_code": 0,
"errors": [],
"warnings": [],
"results": {
"root": { "display": "/Applications", "lossy": false },
"allocated_bytes": 5491449856,
"files": 130141,
"truncated": 0,
"kinds": [
{
"kind": "apps",
"label": "Apps",
"allocated_bytes": 5491441664,
"files": 130138,
"share": 0.9999985
},
"…"
]
}
}
census historyRead-only
Usage
census history [--path PATH] [--record] [--json]Shows how the disk’s used space changed over the last hour, day, week and month, and which category grew most this week. Each run records a sample when the newest is more than 55 minutes old; scans and drive breakdowns add samples too.
| Option | Description |
|---|---|
-p, --path PATH | The volume that holds PATH (default: the startup disk) |
--record | Record a space sample now, whatever the newest one’s age |
--json | Write one JSON response |
census history --json
{
"schema_version": 5,
"command": "history",
"status": "ok",
"exit_code": 0,
"errors": [],
"warnings": [],
"results": {
"volume": {
"name": "Macintosh HD",
"uuid": "6F0E5A4C-3C0B-4C8B-9F0E-0123456789AB",
"total_bytes": 62826479616,
"used_bytes": 60784128000,
"free_bytes": 2042351616
},
"changes": [
{
"period": "hour",
"since_unix_ms": 1791354381631,
"exact": true,
"used_bytes_then": 60664128000,
"change_bytes": 120000000,
"change_ratio": 0.002,
"categories": null
},
{
"period": "week",
"since_unix_ms": 1790753181631,
"exact": true,
"used_bytes_then": 48384128000,
"change_bytes": 12400000000,
"change_ratio": 0.256,
"categories": [
{ "bucket": "developer", "label": "Developer", "change_bytes": 8100000000 }
]
}
]
}
}
The full response has one entry per period: hour, day, week and month. exact is true when a sample lies near the start of the period, and false when the history is shorter than the period and the oldest sample stands in for it. A period with no sample near its start has null for since_unix_ms and every number.