Command lineFind what to remove
Finding what to remove
Find cleanup candidates, large and forgotten files, duplicate copies, and apps with their leftovers. Every command here only reads.
census findingsRead-only
Usage
census findings [SCOPE] [--category CATEGORY] [--safety safe|review|keep] [--limit N] [--refresh] [--progress] [--json]Lists the cleanup candidates census recognizes, grouped by safety tier: safe items rebuild themselves, review items need a person, and keep items are shown but never offered.
| Option | Description |
|---|---|
--scope KIND | drive (the default) or data |
-p, --path PATH | A folder’s own scan |
--category CATEGORY | developer, app_cache, logs, trash, installers, device_backups or ai_agents |
--safety LEVEL | safe, review or keep |
--limit N | Show at most N per safety level (default: 10; 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 |
# Everything, ten per tier
census findings
# Developer caches and build output that clean would delete
census findings --category developer --safety safe --limit 0
# What AI coding agents leave behind
census findings --category ai_agents
The JSON totals count every match before --limit:
{
"schema_version": 5,
"command": "findings",
"status": "ok",
"exit_code": 0,
"errors": [],
"warnings": [],
"results": {
"findings": [],
"totals": {
"safe": { "allocated_bytes": 0, "count": 0 },
"review": { "allocated_bytes": 0, "count": 0 },
"keep": { "allocated_bytes": 0, "count": 0 }
},
"truncated": 0
}
}
ai_agents covers AI coding agents such as Claude Code, Codex and Cursor: old versions, caches, temporary files and logs, plus their history as keep. See Cleaning agent data.
census largeRead-only
Usage
census large [--folders] [--min-size SIZE] [--not-opened DAYS] [--not-modified DAYS] [--limit N] [SCOPE] [--refresh] [--progress] [--json]Lists the largest files you can delete, or folders with --folders, largest first. A drive or data scan searches your home folder and /Users/Shared.
| Option | Description |
|---|---|
--scope KIND | drive (the default) or data |
-p, --path PATH | A folder’s own scan |
--folders | List folders instead of files |
--min-size SIZE | Minimum size on disk (default: 100M) |
--not-opened DAYS | Only items not opened in DAYS days. Items never opened match too. |
--not-modified DAYS | Only items not modified in DAYS days |
--limit N | Show at most N (default: 50; 0 means all, up to 10,000) |
--refresh | Rescan first; otherwise the saved scan is read |
--progress | With --refresh, write scan progress as NDJSON to stderr |
--json | Write one JSON response |
# Files of 1 GB or more, not opened in a year
census large --min-size 1G --not-opened 365 --json
{
"schema_version": 5,
"command": "large",
"status": "ok",
"exit_code": 0,
"errors": [],
"warnings": [],
"scan": { "scope_kind": "drive", "scan_id": "…" },
"results": {
"items": [
{
"path": { "display": "/Users/me/Movies/archive.mov", "lossy": false },
"kind": "file",
"allocated_bytes": 6810000000,
"logical_bytes": 6790000000,
"modified_unix_ms": 1790000000000,
"opened_unix_ms": null,
"selectable": true,
"rule": null
}
],
"total": { "count": 1, "allocated_bytes": 6810000000 },
"truncated": 0,
"filters": {
"folders": false,
"min_size_bytes": 1000000000,
"not_opened_days": 365,
"not_modified_days": null
},
"places": [{ "display": "/Users/me", "lossy": false }],
"folder_opened_dates": null
}
}
- Never listed: macOS’s own volumes, apps and everything inside them, anything inside a package (a
.photoslibraryis one item, as Finder shows it), synced folders (iCloud Drive,~/Library/CloudStorage, Dropbox), the Trash, census’s own folders, hard-linked files, and anything you can’t delete. Protected folders such as~/Documentsare searched, but never listed themselves. - Folders never nest. A folder inside or around a listed folder isn’t listed.
- Dates:
modified_unix_msis the modification time, or for a folder the newest inside it.opened_unix_msis Finder’s Date Last Opened,nullwhen never opened. - Kept items (
safety: keep), and items inside them, haveselectable: false. totalcounts every match before--limit.
Each run saves the items it returned, so apply can delete the ones you choose. Runs on the same scan add to that list; a new scan starts a new one.
census duplicatesRead-only
Usage
census duplicates [SCOPE] [--under PATH] [--min-size SIZE] [--limit N] [--refresh] [--progress] [--json]Finds identical files and the space their extra copies take. census dupes is the same command. It searches files of at least 1 MB in your home folder, /Users/Shared, iCloud Drive and ~/Library/CloudStorage, comparing sizes, then the first 16 KiB, then the full contents. iCloud files that aren’t downloaded are skipped, never downloaded. Digests are remembered between runs, so unchanged files aren’t read again.
| Option | Description |
|---|---|
--scope KIND | drive (the default) or data |
-p, --path PATH | A folder’s own scan |
--under PATH | Only within this folder |
--min-size SIZE | Files of at least this size: bytes, or a K, M or G value (default: 1M) |
--limit N | Show at most N groups (default: 20; 0 means all) |
--refresh | Rescan first; otherwise the saved scan is read |
--progress | Write scan and hashing progress as NDJSON to stderr |
--json | Write one JSON response |
# Duplicates of 1 MB or more in your home folder and iCloud Drive
census duplicates
# Only in Downloads, smaller files too, after a fresh scan
census duplicates --under ~/Downloads --min-size 500K --limit 10 --refresh
census duplicates --path /Applications --under /Applications/Utilities --limit 1 --json
{
"schema_version": 5,
"command": "duplicates",
"status": "ok",
"exit_code": 0,
"errors": [],
"warnings": [],
"results": {
"groups": [],
"group_count": 0,
"min_size_bytes": 1000000,
"reclaimable_bytes": 0,
"roots": [{ "display": "/Applications/Utilities", "lossy": false }]
}
}
Copies that are APFS clones share their storage, so deleting one frees almost nothing. Sets whose copies are all clones of one another aren’t reported. Each search saves the copies it showed, so apply can delete the ones you choose. At least one copy of every set always stays.
census appsRead-only
Usage
census apps [SCOPE] [--all] [--limit N] [--refresh] [--progress] [--json]Lists installed apps, largest first, by the app’s size plus the Library items that belong to it. Needs a scan that includes /Applications and ~/Library, which the default drive scan does.
| Option | Description |
|---|---|
--scope KIND | drive (the default) or data |
-p, --path PATH | A folder’s own scan |
--all | Include apps that are part of macOS |
--limit N | Show at most N apps (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 |
census apps --json
{
"schema_version": 5,
"command": "apps",
"status": "ok",
"exit_code": 0,
"errors": [],
"warnings": [],
"results": [
{
"allocated_bytes": 3891544064,
"bundle_id": "com.apple.dt.Xcode",
"leftover_bytes": 2834432,
"leftover_count": 7,
"name": "Xcode",
"path": { "display": "/Applications/Xcode.app", "lossy": false },
"system": false,
"total_bytes": 3894378496,
"version": "27.0"
},
"…"
]
}
A scan without your apps returns not_found:
{
"schema_version": 5,
"command": "apps",
"status": "not_found",
"exit_code": 7,
"errors": [
{
"code": "apps_not_scanned",
"message": "This scan does not include your apps. Run \"census scan\" (the whole drive) first."
}
],
"warnings": [],
"results": []
}
census appRead-only
Usage
census app NAME_OR_BUNDLE_ID [SCOPE] [--verbose] [--refresh] [--progress] [--json]Shows one app and the Library items that belong to it, with how sure census is (confidence) and whether each is shared or needs an administrator. This is what uninstall would remove.
| Option | Description |
|---|---|
--scope KIND | drive (the default) or data |
-p, --path PATH | A folder’s own scan |
--verbose | Show the evidence for each leftover |
--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 app xcode --json
{
"schema_version": 5,
"command": "app",
"status": "ok",
"exit_code": 0,
"errors": [],
"warnings": [],
"results": {
"app": {
"name": "Xcode",
"bundle_id": "com.apple.dt.Xcode",
"version": "27.0",
"allocated_bytes": 3891544064,
"leftover_bytes": 2834432,
"total_bytes": 3894378496
},
"leftovers": [
{
"path": { "display": "/Users/me/Library/Caches/com.apple.dt.Xcode", "lossy": false },
"location": "Caches",
"confidence": "high",
"allocated_bytes": 1499136
},
"…"
],
"estimated_freed_bytes": 3894374400
}
}
estimated_freed_bytes counts the app and its high-confidence, unshared items that don’t need an administrator. Hard links and APFS clones can make the space actually freed differ.
census leftoversRead-only
Usage
census leftovers [SCOPE] [--verbose] [--limit N] [--refresh] [--progress] [--json]Lists Library items named after bundle IDs with no installed app from that developer. They are possible leftovers of apps you removed, so check them before you remove anything. If the scan couldn’t read a Library folder, not_inspected names it: what is in it is unknown, not absent.
| Option | Description |
|---|---|
--scope KIND | drive (the default) or data |
-p, --path PATH | A folder’s own scan |
--verbose | Show the evidence for each leftover |
--limit N | Show at most N apps’ leftovers (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 |
census leftovers --json
{
"schema_version": 5,
"command": "leftovers",
"status": "ok",
"exit_code": 0,
"errors": [],
"warnings": [],
"results": {
"truncated": 0,
"groups": [],
"not_inspected": [{ "display": "/Users/me/Library/Cookies", "lossy": false }]
}
}