DEV Community

Cover image for Shatter: One Command to Reclaim Gigabytes of Build Junk Across Every Language You Use
Aymen Hmani
Aymen Hmani

Posted on

Shatter: One Command to Reclaim Gigabytes of Build Junk Across Every Language You Use

TL;DR: shatter is a cross-platform CLI tool that finds and obliterates build caches (node_modules, .next, __pycache__, .gradle, …) across all your projects with a single command. Think npkill but for every ecosystem.


The Problem

If you're like me, you have dozens of repos sitting on disk — course projects, side projects, experiments. Each one hoards node_modules, .next build caches, Python virtual environments, and more. Manually hunting them down is tedious. shatter automates the whole thing.

What Is Shatter?

Shatter is a Python CLI tool that:

  • Scans any directory tree for known build artifacts and dependency folders
  • Supports 10+ ecosystems — JavaScript, Python, Rust, Go, PHP, Ruby, Java, .NET, Dart, Expo
  • Computes sizes in parallel using threaded I/O for fast results
  • Deletes safely with dry-run mode, .shatterignore protection, and confirmation prompts
  • Works in CI/CD with --yes for non-interactive cleanup

Comparison (How it differs from alternatives)

There are existing tools in this space, but Shatter was built to solve their specific friction points:

Vs. npkill: npkillis fantastic but strictly interactive—you must manually navigate its UI to delete folders. Shatter can be run headlessly via flags, allowing for total automation.

Vs. kondo: kondo(written in Rust) takes a blunt approach; if it detects a project, it wipes all artifacts. Shatter allows for surgical precision—you can wipe your gigabytes of build caches while keeping your local dependencies intact for offline work.

The Safety Net: Neither of the major alternatives has persistent, per-project protection. Shatter’s .shatterignore file acts just like .gitignore, ensuring you never accidentally wipe a legacy project that takes 45 minutes to re-compile.

Real-World Demo: My tabaani Repos

I have two course project repos on my machine:

  • tabaani_cours_v2 — a Next.js project
  • tabaani-course — contains a travel-agency sub-project

Let's see what shatter finds.


1. Full Scan — tabaani_cours_v2

shatter shatter "C:\Users\everp\Documents\GitHub\tabaani_cours_v2" --all --dry-run
Enter fullscreen mode Exit fullscreen mode
     _____ __          __  __
    / ___// /_  ____ _/ /_/ /____  _____
    \__ \/ __ \/ __ `/ __/ __/ _ \/ ___/
   ___/ / / / / /_/ / /_/ /_/  __/ /
  /____/_/ /_/\__,_/\__/\__/\___/_/     v0.1.3

                         Scan Results
╭──────┬──────────────────────────────────────────────┬────────────┬──────────────╮
│    # │ Directory                                    │    Type    │         Size │
├──────┼──────────────────────────────────────────────┼────────────┼──────────────┤
│    1 │ tabaani_cours_v2\node_modules                │     deps   │     884.6 MB │
├──────┼──────────────────────────────────────────────┼────────────┼──────────────┤
│    2 │ tabaani_cours_v2\.next                       │    cache   │     269.9 MB │
╰──────┴──────────────────────────────────────────────┴────────────┴──────────────╯

╭──────────────────────────── Summary ─────────────────────────────╮
│                                                                  │
│   🗑  Caches:  269.9 MB                                          │
│   📦 Deps:     884.6 MB                                          │
│                                                                  │
│   💎 Total:    1.1 GB                                            │
│                                                                  │
│     ↑ Nothing was deleted (dry run)                              │
│                                                                  │
╰──────────────────────────────────────────────────────────────────╯
Enter fullscreen mode Exit fullscreen mode

1.1 GB of reclaimable space in a single project. The node_modules alone is 884 MB.


2. Full Scan — tabaani-course

shatter shatter "C:\Users\everp\Documents\GitHub\tabaani-course" --all --dry-run
Enter fullscreen mode Exit fullscreen mode
     _____ __          __  __
    / ___// /_  ____ _/ /_/ /____  _____
    \__ \/ __ \/ __ `/ __/ __/ _ \/ ___/
   ___/ / / / / /_/ / /_/ /_/  __/ /
  /____/_/ /_/\__,_/\__/\__/\___/_/     v0.1.3

                               Scan Results
╭──────┬──────────────────────────────────────────────────────┬────────────┬──────────────╮
│    # │ Directory                                            │    Type    │         Size │
├──────┼──────────────────────────────────────────────────────┼────────────┼──────────────┤
│    1 │ tabaani-course\travel-agency\node_modules            │     deps   │     420.0 MB │
╰──────┴──────────────────────────────────────────────────────┴────────────┴──────────────╯

╭──────────────────────────── Summary ─────────────────────────────╮
│                                                                  │
│   📦 Deps:     420.0 MB                                          │
│                                                                  │
│   💎 Total:    420.0 MB                                          │
│                                                                  │
│     ↑ Nothing was deleted (dry run)                              │
│                                                                  │
╰──────────────────────────────────────────────────────────────────╯
Enter fullscreen mode Exit fullscreen mode

Another 420 MB from a nested node_modules inside a sub-project.

Combined total across both repos: ~1.5 GB — and these are just two projects!


3. Targeted Scans — Deps Only

You can isolate the scan to just dependencies:

shatter shatter "C:\Users\everp\Documents\GitHub\tabaani_cours_v2" --deps --dry-run
Enter fullscreen mode Exit fullscreen mode
                         Scan Results
╭──────┬──────────────────────────────────────────────┬────────────┬──────────────╮
│    # │ Directory                                    │    Type    │         Size │
├──────┼──────────────────────────────────────────────┼────────────┼──────────────┤
│    1 │ tabaani_cours_v2\node_modules                │     deps   │     884.6 MB │
╰──────┴──────────────────────────────────────────────┴────────────┴──────────────╯

╭──────────────────────────── Summary ─────────────────────────────╮
│   📦 Deps:     884.6 MB                                          │
│   💎 Total:    884.6 MB                                          │
│     ↑ Nothing was deleted (dry run)                              │
╰──────────────────────────────────────────────────────────────────╯
Enter fullscreen mode Exit fullscreen mode

4. Fast Mode — Skip Size Calculation

When you don't care about exact sizes and just want to see what's there:

shatter shatter "C:\Users\everp\Documents\GitHub\tabaani_cours_v2" --all --dry-run --fast
Enter fullscreen mode Exit fullscreen mode
                         Scan Results
╭──────┬──────────────────────────────────────────────┬────────────┬──────────────╮
│    # │ Directory                                    │    Type    │        Count │
├──────┼──────────────────────────────────────────────┼────────────┼──────────────┤
│    1 │ tabaani_cours_v2\.next                       │    cache   │            — │
├──────┼──────────────────────────────────────────────┼────────────┼──────────────┤
│    2 │ tabaani_cours_v2\node_modules                │     deps   │            — │
╰──────┴──────────────────────────────────────────────┴────────────┴──────────────╯

╭──────────────────────────── Summary ─────────────────────────────╮
│   🗑  Caches:  1 dir(s)                                          │
│   📦 Deps:     1 dir(s)                                          │
│   💎 Total:    2 directories (run without --fast to see sizes)   │
│     ↑ Nothing was deleted (dry run)                              │
╰──────────────────────────────────────────────────────────────────╯
Enter fullscreen mode Exit fullscreen mode

Instant results — no waiting for size computation.


5. Directory Protection with .shatterignore

Sometimes you want to protect a directory from being scanned (e.g. a project you're actively working on). Just drop an empty .shatterignore file in it:

# Protect the travel-agency sub-project
touch tabaani-course/travel-agency/.shatterignore

# Re-run the scan
shatter shatter "C:\Users\everp\Documents\GitHub\tabaani-course" --all --dry-run
Enter fullscreen mode Exit fullscreen mode
     _____ __          __  __
    / ___// /_  ____ _/ /_/ /____  _____
    \__ \/ __ \/ __ `/ __/ __/ _ \/ ___/
   ___/ / / / / /_/ / /_/ /_/  __/ /
  /____/_/ /_/\__,_/\__/\__/\___/_/     v0.1.3

  ⏭  Skipped travel-agency (found .shatterignore)
╭──────────────────────────────────────────────────────────────────╮
│                                                                  │
│  ✨ Nothing to clean — your project tree is spotless!            │
│                                                                  │
╰──────────────────────────────────────────────────────────────────╯
Enter fullscreen mode Exit fullscreen mode

The 420 MB node_modules inside travel-agency is now completely invisible to shatter. Remove the .shatterignore file when you're ready to clean it up.


6. Verbose Mode — Group by Project

shatter shatter "C:\Users\everp\Documents\GitHub\tabaani_cours_v2" --all --dry-run --verbose
Enter fullscreen mode Exit fullscreen mode
                    Scan Results — by Project
╭──────────────────────────────────────────────┬────────────┬──────────────╮
│ Project / Directory                          │    Type    │         Size │
├──────────────────────────────────────────────┼────────────┼──────────────┤
│ 📁 (no project)                              │            │       1.1 GB │
├──────────────────────────────────────────────┼────────────┼──────────────┤
│    └─ node_modules                           │     deps   │     884.6 MB │
├──────────────────────────────────────────────┼────────────┼──────────────┤
│    └─ .next                                  │    cache   │     269.9 MB │
╰──────────────────────────────────────────────┴────────────┴──────────────╯

╭──────────────────────────── Summary ─────────────────────────────╮
│   🗑  Caches:  269.9 MB                                          │
│   📦 Deps:     884.6 MB                                          │
│   💎 Total:    1.1 GB                                            │
│     ↑ Nothing was deleted (dry run)                              │
╰──────────────────────────────────────────────────────────────────╯
Enter fullscreen mode Exit fullscreen mode

Key Features Recap

Feature What it does
--dry-run / -n Preview what would be deleted — nothing touches disk
--deps / -d Target only dependency folders (node_modules, .venv, target, …)
--cache / -c Target only build caches (.next, __pycache__, .gradle, …)
--all / -a Target everything
--fast / -f Skip size computation for instant results
--verbose / -v Group results by project root
--yes / -y Skip confirmation for CI/CD automation
--older-than / -o Only target dirs older than a period (e.g. 30d, 3m, 1y)
.shatterignore Drop in any directory to protect it from scanning

Install

git clone https://github.com/TheLime1/shatter.git
cd shatter
pip install -e .
Enter fullscreen mode Exit fullscreen mode

Requires Python 3.10+.


Built by TheLime1. Give it a star if it saved you some disk space!
Shatter repo

Top comments (0)