A small, super fast tool to scan and remove gitignored build artifacts (e.g. target/, node_modules/, dist/) across a workspace, grouped by Git repo root.
Instead of blindly deleting by directory name, it verifies candidates with git check-ignore first.
- Recursively scans from
--root(default: current directory). - When a directory name matches the built-in (or user-provided) artifact list, it:
- finds the nearest Git repo root (
.git), - checks if the directory is actually ignored by that repo (
git check-ignore), - computes total size and newest mtime (recursive; skips symlinks),
- groups results by repo root.
- finds the nearest Git repo root (
- Default mode is an interactive TUI:
- auto-selects repos whose artifacts are >= 180 days old and >=
--min-size(default1MiB), - deletes selected repos’ artifacts after a confirmation step.
- auto-selects repos whose artifacts are >= 180 days old and >=
scanmode prints a report sorted by repo head commit time (oldest first).
Option 1: via npm (prebuilt binary)
npx clean-my-code
# or
npm i -g clean-my-codeOption 2: build from source (Rust required)
# From the project root
cargo install --path .
# Or run directly
cargo run --release -- --helpDefault (TUI):
clean-my-codeChoose scan root:
clean-my-code --root /path/to/workspaceControl parallelism (Rayon):
clean-my-code --threads 8TUI options:
clean-my-code tui --min-size 1MiB
clean-my-code tui --dry-runScan-only report (no TUI):
clean-my-code scanAdd artifact dir names (repeatable):
clean-my-code --artifact .gradle --artifact .venvOnly use your custom list (disable built-ins):
clean-my-code --no-default-artifacts --artifact target --artifact node_modulesRun clean-my-code --help for the full CLI reference.
- Up/Down: move cursor
- Space: toggle selection
- a: select all
- n: select none
- Tab: toggle sort (age/size)
- Enter: confirm and delete (with a second confirmation)
- q / Esc: quit
These directory names are treated as candidates (they are only counted/deleted if git check-ignore says they are ignored):
targetdistbuildoutbinobjDebugReleasenode_modulesbower_componentselm-stuff.next.nuxt.svelte-kit.astrostorybook-static_sitepublic.vercel.turbo.cache.parcel-cache.vite.angular__pycache__.pytest_cache.mypy_cache.ruff_cache.tox.nox.venvvenvenvENV.direnv.ipynb_checkpointshtmlcov.pyre.pytype.gradledist-newstyle.stack-work.vspackagesCMakeFilescmake-build-debugcmake-build-releasecmake-build-relwithdebinfocmake-build-minsizerelPodsCarthage.swiftpm.buildDerivedData.dart_tool.terraform.serverlesscoveragetmptemp
- Size is computed as the sum of file sizes (not disk blocks like
du). - Requires
gitonPATHand follows Git ignore rules (.gitignore,.git/info/exclude, global excludes). - The built-in list intentionally does not include some stateful directories (e.g.
.pulumi,.vagrant). Add them explicitly via--artifactif you really want to clean them. - The TUI is built with
ratatui+crossterm. If keybindings/rendering are odd, check your terminal settings and input method conflicts.