Open source CLI · MIT
Reclaim gigabytes.
Delete nothing by surprise.
sweep finds node_modules, target, .next and other build output across your projects, shows what each one is, and removes only what you tick.
0 B queued of 4.3 GB found
- Cargo build output
- npm, bun or pnpm install output
- Next.js build cache
- npm, bun or pnpm install output
- Turborepo cache
- Small workspace folder beside a large root install. Not queued in bulk as safe.
- Opt-in name: dist can hold files you wrote. Bulk actions never queue it.
- Inside a Git directory. Sweep never removes it.
Scanning. No file changes.
- ScanStreams what it finds. Changes nothing.
- ChooseThe queue starts empty. You tick what goes.
- ReviewEvery queued path and the deletion mode, named.
- ReceiptCompleted, failed and unattempted, reported.
Knows 28 kinds of build output
On by defaultOpt-in
- node_modules
- .next
- .nuxt
- .svelte-kit
- .turbo
- .parcel-cache
- .vite
- .nyc_output
- *.tsbuildinfo
- target
- dist
- coverage
- .output
- bower_components
- __pycache__
- .venv
- venv
- .pytest_cache
- .mypy_cache
- .ruff_cache
- *.egg-info
- .gradle
- obj
- Pods
- cmake-build-*
- .dart_tool
- build
- out
Built to refuse
A name match is a candidate, not a verdict. sweep explains every item, checks it again right before removal, and accounts for every outcome. Read the safety model
- Path
- web/node_modules
- Why
- npm, bun or pnpm install output
- Default
- on
- Risk
- safe
- Selected
- no, until you tick it
Every item explains itself
Pattern, reason, default and risk tier, visible before anything is selected.
$ sweep apply --plan sweep-plan.json
removed engine/target
removed web/node_modules
refused web/.next
replaced since the scan
Checked again at apply
Scans record each entry's filesystem identity. An entry replaced since then is refused.
Cleanup receipt
- Completed
- 2
- Failed
- 1
- Unattempted
- 0
- Freed
- 3.2 GB
Every run ends in a receipt
Completed, failed and unattempted items, reported separately. Stopping never undoes completed work.
| Rule | Applies to | Result |
|---|---|---|
| Filesystem roots | Scan target | Refused |
| Anything inside .git | Any candidate | Blocked |
| Replaced since the scan | Entry at apply | Refused |
| Replaced scan root | Whole apply | Refused |
| Mount crossings (Linux) | During removal | Refused |
| Incomplete scan | Apply and export | Blocked |
| Over the size ceiling | Apply | Needs --force-large |
Refusals no flag can talk past
These hold however a run starts: terminal UI, plan file or agent.
~/projects/
└ .sweep-trash-1761400000/
├ engine/target
└ web/node_modules
3.2 GB · still on disk
Trash stays local
Trash mode moves items into the scan target. It keeps the disk space until you clear it.
Fast enough to stay out of the way
The Rust engine streams the first result in about two milliseconds, so the list fills while you are still reading it. Set a tree size and see the measured median.
7.6ms
Median scan to plan, interpolated between measured runs of 32 and 1,024 candidates. Intel Core i5-13450HX, warm cache. One dot is one candidate.
1.9 ms
to the first result
Rust engine, 32 candidates
26.4 ms
for 1,024 candidates
Rust engine, scan to plan
10×
faster than the JS engine
262.8 ms against 26.4 ms, wide tree
No p99
production guarantee
Local qualification, not a promise
Made for the terminal. Fine with a mouse.
Arrows work everywhere; letters are speed aliases. Esc unwinds one layer at a time and never quits, so a stray key cannot cost you a review.
- Move the cursor↑↓orjk
- First or last itemgG
- Page up or downCtrl-UCtrl-D
- Filter artifacts/
- Search actions and settingsCtrl+KorF2
FILTER/kind:node_modules >100MB !path:web1 of 8
- api/node_modules412 MBsafe
7 hidden by the filter. Review still names every queued artifact.
Space toggles queue safeEsc clear filter
Same rules for scripts and agents
Plans, previews and streams go through the validated paths the terminal UI uses. Evidence comes first; deletion is a separate, approved step. Read the automation guide
$ sweep scan . --json > sweep-plan.jsonA saved plan. Check the exit status before trusting the file.
- scan_started
- scan_progress
- candidate_found
- candidate_updated
- scan_completed
A lifecycle you can check
Treat a nonzero exit or a missing scan_completed as incomplete.
| invalid_arguments | Usage error, exit 2 | stop |
|---|---|---|
| apply_outcome_unknown | Final report lost, exit 4. Rescan. | stop |
| size_limit_exceeded | Selection is over the byte ceiling | stop |
| apply_busy | Another apply holds the lock | retry |
Failures stay failures
Fatal errors end stderr with a JSON record. Only lock contention is retryable.
Or install it for good