# DiskForge
Intelligent disk cleanup CLI for developers. Scans your system for build caches, package manager artifacts, Docker leftovers, iOS simulators, Android SDK components — and now also uninstalls apps cleanly, finds forgotten large files, and detects duplicates.
**macOS-first. Written in Rust. Single binary.**
[](https://github.com/joicodev/diskforge/actions/workflows/ci.yml)
[](LICENSE)
## Install
### Homebrew (macOS)
```bash
brew tap joicodev/tap
brew install diskforge
```
### Cargo
```bash
cargo install diskforge
```
### From Source
```bash
git clone https://github.com/joicodev/diskforge.git
cd diskforge
cargo install --path crates/diskforge-cli
```
## Quick Start
Just run `diskforge` with no arguments for the unified smart scan dashboard:
```bash
diskforge # Full smart scan: artifacts + large files + duplicates
diskforge --no-dupes # Skip duplicate detection (faster)
diskforge dashboard # Explicit alias for the same
```
The dashboard combines all scan types into a single view showing "You can free X.XX GB" with a category breakdown, disk usage bar, and one-click cleanup.
## Commands
### `scan` — Scan & show cleanable items
```bash
diskforge scan ~ # Everything cleanable
diskforge scan ~ --min-size 100MB # Only items > 100 MB
diskforge scan ~ --older 30d # Untouched for 30+ days
```
### `clean` — Interactive TUI cleanup
```bash
diskforge clean # TUI, nothing pre-selected
diskforge clean --dry-run # Preview mode (no deletion)
diskforge clean --risk low # Pre-select None + Low risk items
diskforge clean --budget 20 # Auto-select safest items until 20% disk is free
```
### `uninstall` — Remove an app + all its traces
When you drag an app to Trash, it leaves behind caches, preferences, containers, launch agents, cookies, and more scattered across ~/Library. `uninstall` finds all of them.
```bash
diskforge uninstall --list # Show all installed apps
diskforge uninstall slack # Find & remove all Slack traces
diskforge uninstall docker --dry-run # Preview what would be removed
```
**How it works:**
1. Parses `Info.plist` to extract the bundle ID (e.g., `com.tinyspeck.slackmacgap`)
2. Searches **14 ~/Library subdirectories** for matches (Application Support, Caches, Preferences, Containers, Group Containers, LaunchAgents, Saved Application State, HTTPStorages, WebKit, Logs, Cookies, Application Scripts, SyncedPreferences, Preferences/ByHost)
3. Shows all traces in the interactive TUI for selective deletion
4. Cross-references other installed apps to avoid deleting shared directories
### `find` — Find large & old forgotten files
Surfaces DMGs, ISOs, videos, archives, and other large files you forgot about.
```bash
diskforge find # Default: ~/Downloads + ~/Desktop, > 50MB
diskforge find ~ --min-size 500MB --older 90d # Big old files anywhere
diskforge find ~/Downloads --type disk-image # Only DMGs/ISOs
diskforge find ~ --type video --min-size 1GB # Forgotten large videos
diskforge find ~/Downloads ~/Desktop --top 20 # Top 20 largest files
```
**File types detected:** disk images (.dmg, .iso), archives (.zip, .tar, .7z, .rar), videos (.mp4, .mov, .mkv), installers (.pkg), VM images (.vmdk, .vdi), documents (.pdf, .psd).
**Smart detection:**
- Two-tier type detection: extension + magic bytes validation (via `infer` crate)
- Download detection via `com.apple.quarantine` xattr — knows if a file was downloaded from the internet
- Uses `mtime` for staleness (APFS disables `atime` by default)
### `dupes` — Find & remove duplicate files
Finds duplicate files using a high-performance 4-stage pipeline.
```bash
diskforge dupes ~/Documents # Interactive TUI to select duplicates
diskforge dupes ~/Downloads --min-size 5MB
diskforge dupes ~/Pictures --no-tui # Table output only
diskforge dupes ~ --dry-run # Preview without deleting
```
**How the pipeline works:**
1. **Size grouping** — files with unique sizes can't be duplicates (eliminates ~95%)
2. **Inode dedup** — filters hard links (same file, different paths)
3. **Partial hash** — blake3 hash of first 4KB (eliminates ~90% of remaining)
4. **Full hash** — complete blake3 hash confirms true duplicates
**Safety:**
- Grouped TUI enforces **"keep at least 1"** — you can never delete all copies
- Detects APFS clones (shared blocks, deleting one frees zero space)
- Filters empty files (all identical, zero space savings)
- Hard links detected and excluded
## TUI Keybindings
### Clean / Uninstall TUI
| `j` / `k` | Navigate up/down |
| `Space` | Toggle item |
| `a` | Select/deselect all |
| `n` | Select all Risk None items |
| `l` | Select all Risk Low items |
| `Enter` | Confirm selection |
| `y` / `n` | Confirm/cancel deletion |
| `q` / `Esc` | Quit |
### Dupes TUI
| `j` / `k` | Navigate within group |
| `Tab` | Next group |
| `Shift+Tab` | Previous group |
| `Space` | Toggle file for deletion |
| `Enter` | Confirm selection |
| `q` / `Esc` | Quit |
## What It Detects (scan/clean)
| **Dev Artifacts** | `node_modules`, `target/`, `build/`, `.next/`, `Pods/`, `__pycache__/` |
| **Package Managers** | npm, cargo, pub, gradle, bun, cocoapods, yarn, homebrew |
| **IDE Caches** | Xcode DerivedData, VS Code, Cursor |
| **Browser Caches** | Chrome, Edge, Brave |
| **App Caches** | Figma, Slack |
| **Docker** | Images, containers, volumes, build cache (via `docker system df`) |
| **iOS Simulator** | Individual devices + runtime downloads |
| **Android** | NDK versions, platforms, build-tools, system images, AVDs |
| **System** | Logs, Trash |
| **User Rules** | Custom paths via `~/.config/diskforge/rules.toml` |
15 project types detected: Node, Rust, Flutter, Gradle, Maven, Swift, CMake, .NET, Python, Go, Zig, Turborepo, Next.js, CocoaPods, React Native.
## Risk Levels
| **None** | Safe to delete anytime. Regenerates automatically. | Yes |
| **Low** | Regenerates with a rebuild command (`npm install`, `cargo build`, etc.) | Yes |
| **Medium** | May require manual reinstall (simulators, SDK components). | No |
| **High** | User data (Downloads, Movies). Never auto-selected. | No |
## Custom Rules
Create `~/.config/diskforge/rules.toml` to add your own paths:
```toml
[[rules]]
name = "Windsurf Cache"
path = "~/Library/Application Support/Windsurf/CachedData"
category = "ide"
risk = "none"
regenerates = true
[[rules]]
name = "pnpm Store"
path = "~/Library/pnpm/store"
category = "pkg"
risk = "none"
regenerates = true
hint = "pnpm install"
```
See `rules.example.toml` for more examples.
### Auto-generate with AI
Instead of writing rules by hand, paste this prompt into Claude Code, ChatGPT, or any AI coding agent to generate a personalized `rules.toml` based on what's actually on your machine:
<details>
<summary>Click to copy the AI prompt</summary>
```
Scan my machine and generate a ~/.config/diskforge/rules.toml file with custom cleanup rules.
Instructions:
1. List large directories (>100MB) in these paths:
- ~/Library/Application Support/
- ~/Library/Caches/
- ~/Library/Developer/
- ~/Library/Containers/
- ~/.local/
- Any other common cache/data paths you find
2. Exclude paths already built into diskforge:
- npm, cargo, pub, gradle, bun, cocoapods, yarn, homebrew (package managers)
- Xcode DerivedData, VS Code, Cursor (IDE caches)
- Chrome, Edge, Brave (browser caches)
- Figma, Slack (app caches)
- Docker, iOS Simulator, Android SDK
- Trash, Downloads, Movies, Logs
3. For each remaining large directory, create a [[rules]] entry with:
- name: human-readable name (e.g., "Discord Cache")
- path: using ~ for home (e.g., "~/Library/Caches/com.discord")
- category: one of ide, browser, pkg, system, or the app name
- risk: "none" if it's clearly a cache, "low" if regenerable, "medium" if unsure
- regenerates: true if the app will recreate it automatically
- hint: (optional) how to regenerate if known
4. Create the config directory if needed: mkdir -p ~/.config/diskforge
5. Write the file to ~/.config/diskforge/rules.toml
Focus on apps I actually have installed. Don't add rules for apps that aren't on my machine.
```
</details>
## Architecture
```
crates/
diskforge-core/ # Library: scanning, detection, rules, cleaner, file finder, duplicate engine
diskforge-cli/ # Binary: clap CLI + ratatui TUI
```
- **Parallel scanning** via `rayon` (known paths) and `ignore::WalkParallel` (dev artifacts, file finder)
- **Marker-file detection** for 15 project types (inspired by kondo)
- **Budget mode** selects safest + largest items first to reach target free space
- **Plist parsing** via `plist` crate for app uninstaller (binary + XML transparent)
- **File type detection** two-tier: extension + magic bytes via `infer` crate
- **Download detection** via `com.apple.quarantine` xattr
- **Duplicate detection** 4-stage pipeline: size group -> inode dedup -> partial hash (4KB) -> full hash (blake3)
- **87 tests** across unit and integration suites
## License
MIT