A developer-focused macOS app that finds and removes regenerable project artifacts — node_modules, .next, build caches, compiled outputs — and moves them safely to the Trash.
Auto-scans your home directory on launch. No config needed.
- Auto-scan on launch — scans
~immediately, no landing screen - Storage dashboard — grouped cards by type with size totals and proportional bars
- Type filter — click any card to filter the results table to that artifact type
- Smart detection — contextual checks prevent false positives (
node_modulesonly matched whenpackage.jsonexists nearby, etc.) - 15+ artifact types — node_modules, .next, .nuxt, .cache, .turbo, .parcel-cache, .svelte-kit, dist, build, __pycache__, DerivedData, .gradle, Cargo target, .vercel
- Trash or delete — move to macOS Trash (recoverable) or permanently delete, your choice in the confirmation modal
- Animated delete — rows sweep out as they're cleaned; success banner slides in
- Reveal in Finder — hover any row to open its project directory in Finder
- Parallel scanning — BFS walker with 64-dir batches; size calculation with 8 concurrent
duworkers - CLI —
devclean scan/devclean cleanwith--json,--dry-run,--yes,--typeflags
git clone https://github.com/Tanmay0215/devclean.git
cd devclean
npm install
npm run devRequires Node.js ≥ 18 and macOS (uses
shell.trashItemanddu).
| Tool | Version | Install |
|---|---|---|
| Node.js | ≥ 18 | brew install node |
| npm | ≥ 9 | bundled with Node |
| macOS | 12+ Monterey | — |
git clone https://github.com/Tanmay0215/devclean.git
cd devclean
npm installFirst install: npm will prompt to approve install scripts for
electronandesbuild. Run:npm approve-scripts electron esbuild fsevents npm install
npm run devThis starts three processes concurrently:
- Vite dev server on
localhost:5173(renderer, hot-reload) - tsc --watch compiling the Electron main process to
dist/ - Electron loading the Vite URL
# Compile everything
npm run build
# Run the built app (no dev server needed)
ELECTRON_ENV=production npx electron .# Universal binary (arm64 + x64)
npm run dist:mac
# Apple Silicon only (faster)
npm run dist:mac:armOutput lands in release/. Add a 1024×1024 icon at assets/icon.icns before packaging (see Icon below).
# Build the CLI
npm run build:main
# Link globally
npm link
# Or run directly with ts-node (no build needed)
npm run cli:dev -- scan ~/projects --sizes# Scan and list artifacts
devclean scan . # current directory
devclean scan ~/projects --sizes # include disk usage (slower)
devclean scan ~/projects --json # machine-readable JSON output
# Move artifacts to Trash (interactive)
devclean clean ~/projects
devclean clean ~/projects --yes # skip confirmation prompt
devclean clean ~/projects --dry-run # preview without deleting
devclean clean ~/projects --type node_modules # specific type onlydevclean/
├── src/
│ ├── shared/
│ │ └── types.ts # Types shared between main + renderer
│ ├── main/ # Electron main process (Node.js)
│ │ ├── index.ts # App lifecycle + all IPC handlers
│ │ ├── preload.ts # contextBridge — typed API for renderer
│ │ ├── services/
│ │ │ ├── scanner.service.ts # BFS directory walker (async generator)
│ │ │ ├── classifier.service.ts # Contextual artifact classification
│ │ │ ├── size.service.ts # Parallel du-based size calculation
│ │ │ └── cleanup.service.ts # Trash / permanent delete
│ │ └── utils/
│ │ ├── nanoid.ts # crypto.randomBytes ID generator
│ │ └── trash-cli.ts # AppleScript trash for CLI
│ └── renderer/ # React + Tailwind frontend
│ ├── index.html
│ └── src/
│ ├── App.tsx # Root — auto-scan, filter, confirm
│ ├── index.css # Tailwind + custom keyframes
│ ├── hooks/
│ │ └── useDevClean.ts # All state: scan → size → clean
│ └── components/
│ ├── Header.tsx
│ ├── StorageDashboard.tsx # Type cards + filter
│ ├── ScanningState.tsx # Animated scan beam + counter
│ ├── ScanResults.tsx # Filterable results table
│ ├── FolderRow.tsx # Row with delete animation
│ ├── TypeBadge.tsx
│ ├── ConfirmModal.tsx # Trash vs permanent delete toggle
│ └── StatusBar.tsx
└── cli/
├── index.ts # commander entry point
└── commands/
├── scan.ts
└── clean.ts
| Folder | Condition to match |
|---|---|
node_modules |
Sibling package.json must exist |
.next |
next.config.* present OR next in package.json deps |
.nuxt / .output |
nuxt in package.json deps |
.svelte-kit |
@sveltejs/kit in package.json deps |
dist |
package.json with a build script (tsc, vite build, webpack, rollup, esbuild) |
build |
CMakeLists.txt, Makefile, OR JS build script present |
target |
Cargo.toml, pom.xml, or build.gradle present |
DerivedData |
Under ~/Library/Developer/Xcode/DerivedData OR sibling .xcodeproj |
__pycache__, .cache, .turbo, .parcel-cache, .vercel, .gradle |
Always safe — no extra check |
- Trash by default —
shell.trashItem()moves files to macOS Trash, fully recoverable from Finder. - Permanent delete guard —
rm -rfis only invoked when you explicitly choose "Delete Permanently" in the modal. The service rejects any path with fewer than 3 path segments as a hard safety guard. - No false positives — every artifact type has a context check; a bare
dist/folder without a build script is ignored. - System dirs skipped —
.git,Library,.Trash,System,Applications,Volumesare never descended into.
# Convert a 1024×1024 PNG to .icns
mkdir icon.iconset
sips -z 512 512 assets/icon.png --out icon.iconset/icon_512x512.png
sips -z 256 256 assets/icon.png --out icon.iconset/icon_256x256.png
sips -z 128 128 assets/icon.png --out icon.iconset/icon_128x128.png
sips -z 64 64 assets/icon.png --out icon.iconset/icon_64x64.png
sips -z 32 32 assets/icon.png --out icon.iconset/icon_32x32.png
sips -z 16 16 assets/icon.png --out icon.iconset/icon_16x16.png
iconutil -c icns icon.iconset -o assets/icon.icns
rm -rf icon.iconsetPlace the resulting assets/icon.icns before running npm run dist:mac.
MIT