macOS Disk Cleanup
Perform a two-phase, evidence-driven cleanup: analyze and rank first, then execute only the scope the user approves. Treat source code, personal data, active developer state, and simulator/device data as protected by default.
Non-negotiable rules
- Measure live state every run. Never reuse old sizes, process state, PR state, or free-space figures as current truth.
- Do not delete during an analysis-only request.
- Never classify a Worktree as finished from age, name, or a clean status alone.
- Before every Worktree removal, require all three:
- no process has a current working directory inside it;
git status --porcelain=v1 --untracked-files=normal is empty;
- its HEAD is contained in a verified-current remote main ref, or its matching GitHub PR is merged.
- Recheck those conditions immediately before deletion. A preflight snapshot is not enough.
- Use
git worktree remove <exact-path> without --force, then git worktree prune. Do not delete branches unless separately requested.
- Never run destructive commands against
$HOME, ~, a workspace root, a glob, a command substitution, or an unresolved variable. Resolve and validate every exact target first.
- Do not invoke
sudo, change ownership, or weaken permissions automatically. Report root-owned residues separately.
- Do not delete active caches, open files, personal media, messages, browser profiles, virtual machines, app sessions, common simulators, Android AVDs, or data with uncertain recovery value.
- Preserve dirty worktrees even when their PR is merged or HEAD is in main.
Read references/cleanup-policy.md when assigning risk tiers, handling Conductor workspaces, or deciding what must remain.
Phase 1: Establish live truth
Start with read-only checks:
- Record
/System/Volumes/Data capacity, used space, free space, and percentage.
- Check SMART status and local APFS snapshots. Treat OS update snapshots separately from user-data snapshots.
- List active process current working directories with
lsof.
- Check Trash without assuming it is large.
- Measure targeted high-yield paths before broad scans. Prefer
gdu, du -x, max-depth scans, and exact known directories over unrestricted recursive scans.
- Inspect package/build caches,
/private/tmp, the user's per-session /private/var/folders/.../X, developer directories, Downloads installers, and project/worktree roots.
Never chain analysis into deletion unless the user already authorized execution.
Phase 2: Audit Worktrees
Discover the real repository families first. Include ordinary repos and their .codex, .claude, sibling, and /private/tmp worktrees.
Run the bundled read-only auditor with every main repository root:
python3 scripts/audit_worktrees.py --online \
--root /absolute/path/to/repo-a \
--root /absolute/path/to/repo-b
Use --sizes only when per-worktree sizing is worth the scan cost. Use --json for machine-readable output.
Interpret classifications conservatively:
SAFE_MAIN_CONTAINS: clean, inactive, and HEAD is in a local origin/main that exactly matches live ls-remote.
SAFE_PR_MERGED: clean, inactive, and the branch has a merged GitHub PR.
KEEP_ACTIVE: a process CWD is inside the Worktree.
KEEP_DIRTY: tracked or untracked changes exist.
KEEP_CLEAN_UNPROVEN: clean and inactive, but merge/completion proof is missing.
KEEP_ACTIVE_UNKNOWN: active-process detection was unavailable; do not delete.
An initially active Worktree may become eligible later only after a fresh audit proves it inactive, clean, and merged/current-main. State this explicitly in the report.
When multiple repositories are cleaned concurrently, use at most one removal worker per repository root. Never run concurrent git worktree mutations against the same repository metadata.
Phase 3: Build a graded plan
Report actual measured sizes and separate overlap where possible.
- P0 / high confidence: proven-finished Worktrees; inactive generated
.next, .open-next, build, dist, DerivedData, package caches; verified installed-app installers; old unregistered temporary copies after source recovery; inactive Xcode caches while preserving devices/runtimes.
- P1 / conditional: recent temp data, general app caches, browser models, stopped-but-unproven project copies, simulator devices the user may still need.
- Keep: active/dirty/unproven Worktrees, WeChat/messages, photos/videos, browser profiles, VMs, Claude/Codex sessions, current npm/build caches, common simulators, Android AVDs, and unknown data.
- Admin-only residue: root-owned generated files that normal permissions cannot remove.
Include a reclaim estimate, but distinguish logical directory totals from APFS free-space change and hardlink-deduplicated totals.
Phase 4: Execute approved P0 in stages
1. Standard Git Worktrees
For each exact candidate:
- Re-read active CWDs.
- Recheck clean status and unchanged HEAD.
- Reconfirm live main containment or merged PR proof.
- Run non-force
git worktree remove.
- Record success, safety skip, or permission failure.
- Prune only after removals.
If Git unregisters a Worktree but leaves root-owned generated files, label it as an unregistered filesystem residue rather than a preserved Worktree.
2. Conductor workspaces and unregistered project copies
Preserve every valid Git workspace with changes. For invalid/broken/no-Git workspaces:
- Establish the exact directory set and verify none are active or open.
- Create a recovery archive containing source and non-rebuildable files.
- Exclude rebuildable directories such as
node_modules, .next, .open-next, build, dist, .turbo, .dart_tool, coverage, target, Pods, and caches.
- Verify the archive with
gzip -t, list its members, and confirm every intended workspace root appears.
- Revalidate the exact set after archive creation.
- Delete only the archived exact roots.
- Preserve and measure root-owned residues if deletion is denied.
Do not claim an orphan directory was fully removed when only its user-owned portion disappeared.
3. Generated caches and temporary data
Before deleting each exact cache:
- verify it is not a symlink;
- check for open files and active project roots;
- record allocated size;
- delete only the exact generated directory;
- verify it is absent or measure the residue.
For .next, skip the entire repository when a process CWD is within that repository. For npm/Gradle/pnpm caches, recheck running build processes. If a cache regenerates, inspect logs: retain it when it belongs to current activity.
For Xcode/CoreSimulator:
- preserve installed runtimes and common simulator devices unless the user explicitly approves device deletion;
- require devices to be Shutdown and no Simulator/xcodebuild/XCTest activity before clearing caches;
- verify devices still exist afterward.
For installers, confirm the corresponding application/input method is installed and the image is not mounted before deleting the installer.
Phase 5: Verify and report
Do not call the cleanup complete until all checks pass:
- Re-run disk usage and report before/after free space and capacity.
- Re-run the Worktree auditor. There should be no remaining safe candidate inside the approved scope.
- Confirm representative dirty and active Worktrees still exist with their changes.
- Confirm recovery archives pass integrity checks and provide clickable paths.
- Confirm preserved iOS devices, runtimes, and Android AVDs still exist.
- Confirm no cleanup processes remain.
- Measure permission residues and current regenerated caches.
- Report SMART and snapshot state without deleting OS update snapshots.
Lead with the measured outcome. Then summarize removed categories, protected items, recoverable archives, and any exact blocker requiring administrator authorization.
1---2name: macos-disk-cleanup3description: Safely analyze and clean a nearly full macOS disk, with special handling for Git Worktrees, Codex/Claude worktrees, Conductor workspaces, build artifacts, package caches, Xcode/CoreSimulator data, Android AVDs, installers, temporary directories, active processes, and root-owned residues. Use when the user says the Mac disk is full, asks for a deep disk-space analysis, wants cleanup candidates graded by safety, approves P0/high-confidence cleanup, or suspects many project Worktrees are consuming space.4---56# macOS Disk Cleanup78Perform a two-phase, evidence-driven cleanup: analyze and rank first, then execute only the scope the user approves. Treat source code, personal data, active developer state, and simulator/device data as protected by default.910## Non-negotiable rules1112- Measure live state every run. Never reuse old sizes, process state, PR state, or free-space figures as current truth.13- Do not delete during an analysis-only request.14- Never classify a Worktree as finished from age, name, or a clean status alone.15- Before every Worktree removal, require all three:16 1. no process has a current working directory inside it;17 2. `git status --porcelain=v1 --untracked-files=normal` is empty;18 3. its HEAD is contained in a verified-current remote main ref, or its matching GitHub PR is merged.19- Recheck those conditions immediately before deletion. A preflight snapshot is not enough.20- Use `git worktree remove <exact-path>` without `--force`, then `git worktree prune`. Do not delete branches unless separately requested.21- Never run destructive commands against `$HOME`, `~`, a workspace root, a glob, a command substitution, or an unresolved variable. Resolve and validate every exact target first.22- Do not invoke `sudo`, change ownership, or weaken permissions automatically. Report root-owned residues separately.23- Do not delete active caches, open files, personal media, messages, browser profiles, virtual machines, app sessions, common simulators, Android AVDs, or data with uncertain recovery value.24- Preserve dirty worktrees even when their PR is merged or HEAD is in main.2526Read [references/cleanup-policy.md](references/cleanup-policy.md) when assigning risk tiers, handling Conductor workspaces, or deciding what must remain.2728## Phase 1: Establish live truth2930Start with read-only checks:31321. Record `/System/Volumes/Data` capacity, used space, free space, and percentage.332. Check SMART status and local APFS snapshots. Treat OS update snapshots separately from user-data snapshots.343. List active process current working directories with `lsof`.354. Check Trash without assuming it is large.365. Measure targeted high-yield paths before broad scans. Prefer `gdu`, `du -x`, max-depth scans, and exact known directories over unrestricted recursive scans.376. Inspect package/build caches, `/private/tmp`, the user's per-session `/private/var/folders/.../X`, developer directories, Downloads installers, and project/worktree roots.3839Never chain analysis into deletion unless the user already authorized execution.4041## Phase 2: Audit Worktrees4243Discover the real repository families first. Include ordinary repos and their `.codex`, `.claude`, sibling, and `/private/tmp` worktrees.4445Run the bundled read-only auditor with every main repository root:4647```bash48python3 scripts/audit_worktrees.py --online \49 --root /absolute/path/to/repo-a \50 --root /absolute/path/to/repo-b51```5253Use `--sizes` only when per-worktree sizing is worth the scan cost. Use `--json` for machine-readable output.5455Interpret classifications conservatively:5657- `SAFE_MAIN_CONTAINS`: clean, inactive, and HEAD is in a local `origin/main` that exactly matches live `ls-remote`.58- `SAFE_PR_MERGED`: clean, inactive, and the branch has a merged GitHub PR.59- `KEEP_ACTIVE`: a process CWD is inside the Worktree.60- `KEEP_DIRTY`: tracked or untracked changes exist.61- `KEEP_CLEAN_UNPROVEN`: clean and inactive, but merge/completion proof is missing.62- `KEEP_ACTIVE_UNKNOWN`: active-process detection was unavailable; do not delete.6364An initially active Worktree may become eligible later only after a fresh audit proves it inactive, clean, and merged/current-main. State this explicitly in the report.6566When multiple repositories are cleaned concurrently, use at most one removal worker per repository root. Never run concurrent `git worktree` mutations against the same repository metadata.6768## Phase 3: Build a graded plan6970Report actual measured sizes and separate overlap where possible.7172- **P0 / high confidence:** proven-finished Worktrees; inactive generated `.next`, `.open-next`, build, dist, DerivedData, package caches; verified installed-app installers; old unregistered temporary copies after source recovery; inactive Xcode caches while preserving devices/runtimes.73- **P1 / conditional:** recent temp data, general app caches, browser models, stopped-but-unproven project copies, simulator devices the user may still need.74- **Keep:** active/dirty/unproven Worktrees, WeChat/messages, photos/videos, browser profiles, VMs, Claude/Codex sessions, current npm/build caches, common simulators, Android AVDs, and unknown data.75- **Admin-only residue:** root-owned generated files that normal permissions cannot remove.7677Include a reclaim estimate, but distinguish logical directory totals from APFS free-space change and hardlink-deduplicated totals.7879## Phase 4: Execute approved P0 in stages8081### 1. Standard Git Worktrees8283For each exact candidate:84851. Re-read active CWDs.862. Recheck clean status and unchanged HEAD.873. Reconfirm live main containment or merged PR proof.884. Run non-force `git worktree remove`.895. Record success, safety skip, or permission failure.906. Prune only after removals.9192If Git unregisters a Worktree but leaves root-owned generated files, label it as an unregistered filesystem residue rather than a preserved Worktree.9394### 2. Conductor workspaces and unregistered project copies9596Preserve every valid Git workspace with changes. For invalid/broken/no-Git workspaces:97981. Establish the exact directory set and verify none are active or open.992. Create a recovery archive containing source and non-rebuildable files.1003. Exclude rebuildable directories such as `node_modules`, `.next`, `.open-next`, build, dist, `.turbo`, `.dart_tool`, coverage, target, Pods, and caches.1014. Verify the archive with `gzip -t`, list its members, and confirm every intended workspace root appears.1025. Revalidate the exact set after archive creation.1036. Delete only the archived exact roots.1047. Preserve and measure root-owned residues if deletion is denied.105106Do not claim an orphan directory was fully removed when only its user-owned portion disappeared.107108### 3. Generated caches and temporary data109110Before deleting each exact cache:111112- verify it is not a symlink;113- check for open files and active project roots;114- record allocated size;115- delete only the exact generated directory;116- verify it is absent or measure the residue.117118For `.next`, skip the entire repository when a process CWD is within that repository. For npm/Gradle/pnpm caches, recheck running build processes. If a cache regenerates, inspect logs: retain it when it belongs to current activity.119120For Xcode/CoreSimulator:121122- preserve installed runtimes and common simulator devices unless the user explicitly approves device deletion;123- require devices to be Shutdown and no Simulator/xcodebuild/XCTest activity before clearing caches;124- verify devices still exist afterward.125126For installers, confirm the corresponding application/input method is installed and the image is not mounted before deleting the installer.127128## Phase 5: Verify and report129130Do not call the cleanup complete until all checks pass:1311321. Re-run disk usage and report before/after free space and capacity.1332. Re-run the Worktree auditor. There should be no remaining safe candidate inside the approved scope.1343. Confirm representative dirty and active Worktrees still exist with their changes.1354. Confirm recovery archives pass integrity checks and provide clickable paths.1365. Confirm preserved iOS devices, runtimes, and Android AVDs still exist.1376. Confirm no cleanup processes remain.1387. Measure permission residues and current regenerated caches.1398. Report SMART and snapshot state without deleting OS update snapshots.140141Lead with the measured outcome. Then summarize removed categories, protected items, recoverable archives, and any exact blocker requiring administrator authorization.