devclean: A CLI Tool for Efficient Development Cleanup
Primary Purpose:
devclean is a robust command-line interface (CLI) tool designed specifically for developers working with Rust and Node.js. It streamlines the process of cleaning up unnecessary build files, caches, and other redundant data without compromising essential project files.
Key Features:
Selective File Removal: Safely removes targets, node_modules, build caches, and other non-essential files while preserving Git-tracked repositories, backups, databases, symlinks, mounts, and Docker volumes.
Integration with Rust and Node.js: Optimized to work seamlessly with Rust projects using Cargo and JavaScript/TypeScript projects, ensuring efficient cleanup without disrupting development workflows.
Disk Cleanup Expertise: Specializes in eliminating unused Docker data, framework caches, and package caches, freeing up valuable disk space while maintaining project integrity.
Target Audience and Benefits:
Ideal for Rust and JavaScript developers seeking to optimize their workflow. devclean helps save time and resources by speeding up builds, reducing unnecessary storage usage, and preventing accidental data loss. Available via Winget, it simplifies installation on Windows systems with ease, making it a go-to tool for efficient development cleanup.
This tool is perfect for those looking to enhance productivity without the hassle of manual file management.
README
devclean
devclean is a safety-first Rust CLI and native SwiftUI macOS menu bar app for auditing and removing rebuildable development artifacts. Learning Mode measures local growth, surfaces unknown cache-like directories as review-only observations, and can promote an exact path only through a scanner-owned rule approved by the user. Structured local diagnostics and opt-in, privacy-filtered Sentry monitoring keep failures visible.
Safety by construction
Scan read-only and classify candidates using filesystem evidence.
Block candidates containing Git-tracked files by default.
Show an exact, size-sorted cleanup plan.
Require confirmation unless --yes is explicit.
Revalidate containment, category, type, and Git state immediately before deletion.
Atomically rename each candidate into a same-filesystem quarantine before recursive removal.
Never pass --volumes to Docker cleanup.
Keep Learning Mode observations separate from cleanup authority.
Quick start
# Audit generated artifacts older than one week and at least 500 MiB
devclean scan --older-than 7d --min-size 500MiB
# Save a privacy-safe HTML audit
devclean scan --global-caches --docker \
--redact-paths --format html --output devclean-audit.html
# Observe active artifacts and unknown cache-like project directories
devclean scan --learning --format json
# Watch roots read-only and notify when reclaimable artifacts exceed the threshold
devclean watch --threshold 5GiB --interval 1h
# Browse candidates in a read-only terminal UI; Enter only prints a clean command
devclean tui
# Preview the exact cleanup plan without confirmation or filesystem changes
devclean clean --dry-run
# Conservative cleanup: target, node_modules, framework caches, Python caches/environments
devclean clean --select --report devclean-before.html
# Keep selected artifacts restorable for seven days (space is released on purge)
devclean clean --select --quarantine-for 7d
devclean quarantine list
devclean quarantine purge
# Permanently delete one exact hold immediately
devclean quarantine purge --id
# Restore one exact hold through the clean UX shorthand
devclean clean --undo
# Reclaim only enough to reach 100 GiB free
devclean clean --all --target-free 100GiB --yes
# Build cache only; volumes are untouched
devclean clean --docker --docker-older-than 168h --yes
# Broader Docker cleanup requires a distinct flag; still never volumes
devclean clean --docker-system --docker-older-than 168h --yes
# Install a platform-native timer after previewing it
devclean schedule install --every 7d --older-than 30d --min-size 1GiB --all --yes --dry-run
# Inspect aggregate local history (candidate paths are never stored)
devclean stats --days 30 --format html --output devclean-stats.html
# Correlate the current read-only scan with local aggregate history
devclean analyze --days 30 --stale-after-days 60 --redact-paths
Run devclean doctor to inspect roots, config search paths, tools, and active safety guarantees.
When no roots are supplied, devclean uses existing conventional project folders under the home
directory: Dev, Developer, Projects, Code, src, workspace, Workspaces, Repos,
Repositories, GitHub, Documents/GitHub, AndroidStudioProjects, and IdeaProjects. It never
creates these folders or falls back to scanning the entire home directory. Explicit CLI/config roots
replace automatic discovery; duplicate and nested roots are collapsed before traversal.
What it cleans
Category
Default clean
Opt-in
Evidence
Cargo target
Yes
—
Exact name plus Cargo build markers
node_modules
Yes
—
Exact dependency-directory name
Framework cache
Yes
—
Known names such as .next and .svelte-kit
Python bytecode/test cache
Yes
—
__pycache__, or .tox/.nox beside a direct Python project marker
Python virtual environment
Yes
—
.venv/venv directly beside pyproject.toml, requirements, or another dependency manifest
Build/test output
No
--all
Recognized manifest plus exact generated name
Gradle/CMake/Zig output
No
--all
Direct build manifest plus build, .zig-cache, zig-cache, or zig-out
Ambiguous cache-like output
Never
--learning observes only
Project marker plus names such as dist, out, .cache, or coverage
Build/package/tool cache
No
--global-caches
Exact platform-aware allowlist for package caches, Gradle cache/distributions, macOS Xcode DerivedData, and a Go module cache that honors GOMODCACHE or go env GOMODCACHE
Model/runtime cache
No
--expensive-caches
Separate allowlist because redownload cost is high
Docker build cache
No
--docker
docker builder prune, never volumes
Docker system data
No
--docker-system
Stopped containers, unused images/networks/cache; never volumes
Ambiguous dist, out, and coverage directories can appear as Learning Mode review-only observations but never enter a cleanup plan. Archives, user data, databases, VCS metadata, and Docker volumes remain protected.
The global-cache allowlist deliberately excludes the Gradle user-home root, CoreSimulator, Android
SDK/AVD data, JetBrains system storage, and Docker Desktop's disk image. Those locations can contain
credentials, toolchains, Local History, simulator state, or container data and require dedicated
vendor-aware management rather than recursive filesystem deletion.
Filters and selection
--older-than 30d: require the newest observed file to be old enough.
--min-size 1GiB: ignore small candidates.
--exclude 'vendor/**': skip matching absolute, root-relative, or basename paths.
--select: choose candidate numbers and ranges interactively.
--only-path PATH: clean exact paths emitted by a previous JSON scan; every path must pass a fresh scan or the operation aborts.
--target-free 100GiB: select only enough largest candidates to reach a free-space target on the first root filesystem.
--allow-tracked: explicit escape hatch for vendored/generated content committed to Git.
--learning: measure active known artifacts independently of age filters and surface large unknown cache-like directories as review-only.
--approve-review-path PATH: approve an exact observation only when it still matches a scanner-owned rule: SwiftPM .build beside Package.swift, DerivedData beside an Xcode project, .gradle beside a Gradle script, or Pods beside both Podfile and Podfile.lock.
--quarantine-for 7d: retain selected artifacts in adjacent safety holds; this delays disk reclamation until purge.
--dry-run: render the fully filtered clean plan and optional HTML report, then exit without confirmation, Docker invocation, quarantine, or deletion.
--undo ID: restore one exact safety hold; shorthand for quarantine restore ID.
Configuration
devclean loads the first existing file from ./.devclean.toml, ./devclean.toml, or the platform config directory. Pass --config PATH to select one explicitly. CLI values override config values. devclean init creates a reviewed starter file; devclean config fetch clones a shared policy and validates it before replacing the local file.
Custom rules remain evidence-based: names are exact, every marker must be a direct sibling, path traversal is rejected, and the rule is revalidated immediately before cleanup. See devclean.example.toml.
HTML and JSON can contain private absolute paths unless --redact-paths is used. JSONL emits safe candidates, review-only observations, Learning Mode observations, then a summary event. Scan reports also group candidates under the nearest Cargo, npm-workspaces, or Nx root. analyze combines the current scan with aggregate-only SQLite history to flag stale categories, repeated category growth, cleanup failures, and workspace concentration without persisting candidate paths.
Generate shell integrations without extra packages:
Scheduled cleanup uses launchd on macOS, a systemd user timer on Linux, and Task Scheduler on Windows. Installation requires both --yes and an explicit profile; use --dry-run to inspect generated paths and commands first. Cleanup results are appended as JSONL under the platform log directory.
Installation
GitHub release
Download the archive for your platform from the latest release, verify SHA256SUMS, then verify build provenance:
The crates.io package is named devclean-cli; the installed executable is devclean.
cargo install devclean-cli --locked
Homebrew
# Command-line tool
brew install tuanle96/tap/devclean
# Native macOS menu bar app
brew install --cask tuanle96/tap/devclean-menubar
The Cask installs and opens DevCleaner.app after installation. On its first launch, the app registers itself with macOS Launch at Login; this can be disabled at any time in DevCleaner Settings or System Settings > General > Login Items.
Native macOS menu bar app
The SwiftUI app scans at launch and every six hours, displays growth history, separates safe and review-only observations, exposes approve/revoke controls for scanner-owned rules, accepts Always select / Never clean feedback, and offers both a restorable safety hold and a separately confirmed Delete Now path for immediate reclamation. Settings can restore or permanently delete one exact hold. The app registers with macOS Launch at Login by default, keeps structured local logs, bundles the same Rust helper used by the CLI, and never deletes files from Swift.
apps/macos/scripts/build-app.sh
open dist/DevCleaner.app
Local source builds are ad-hoc signed unless CODE_SIGN_IDENTITY is provided. Published menu bar archives are Developer ID signed, notarized by Apple, stapled, and Gatekeeper-verified. See apps/macos.
VS Code extension
The source extension in editors/vscode shows reclaimable workspace bytes in the status bar, opens a privacy-explicit HTML report, and keeps preview separate from cleanup. Cleanup always requires a modal confirmation and invokes devclean directly without a shell.
Download the source-traceable VSIX from the vscode-v0.1.0 release, then install it with code --install-extension devclean-vscode-0.1.0.vsix. Marketplace publication uses the same package once the tuanle96 publisher credential is configured.
cd editors/vscode
npm ci
npm test
Build from source
git clone https://github.com/tuanle96/devclean.git
cd devclean
cargo install --path . --locked