How oops works
Philosophy
macOS doesn’t ship with gparted or anything like it. When your disk fills up, you’re stuck clicking through Finder or running du -sh * one directory at a time. oops fixes that.
The design principles:
- Fast by default. Parallel scanning with rayon. Most directories render instantly.
- Honest sizes. Reports on-disk block usage, not apparent file sizes. A 1 TiB sparse Docker image that only uses 20 GiB of blocks shows as 20 GiB.
- Terminal-native. Colored output with progress bars, tree drawing, and proportional bars — all to stderr. Machine-readable output goes to stdout.
- No config needed. Run
oopsand get a directory breakdown immediately. Useoops volwhen you need volume info.
Architecture
oops is a Rust workspace with two crates:
crates/
├── oops-core/ # Library: scanning, volumes, waste detection
└── oops-cli/ # Binary: commands, UI rendering, terminal output
oops-core handles the heavy lifting:
scan_top_entries()— parallel scan of immediate children with aggregated sizesscan_directory()— recursive flat scan up to a max depthlist_volumes()— portable volume detection viadf -Pksweep_directory()— waste pattern matching (node_modules, caches, build artifacts)
oops-cli handles presentation:
- Each command implements an
Optrait with typed errors and output - All rendering lives in a single
uimodule — commands never format output directly - A
command_enum!macro generates the dispatch enum from individual command structs
On-disk sizing
Most disk usage tools report apparent size — what metadata.len() returns. This is the logical file size. For normal files, this is fine. But for sparse files (like Docker.raw on macOS), the apparent size can be wildly larger than the actual disk blocks allocated.
oops uses stat.blocks * 512 — the same metric du reports by default. This gives you the real on-disk footprint.
A Docker.raw file might report 1 TiB apparent size but only consume 20 GiB of actual disk blocks. oops shows you the 20 GiB.