linux-cleanup
v1.6.0
Published
Safe, modular disk and cache cleanup for Linux — prune by default, allowlist-guarded.
Maintainers
Readme
Docs · npm · GitHub · Changelog · Contributing · Support
[!IMPORTANT] This tool deletes files, and deletion is permanent — there is no undo and nothing is archived first. It removes caches and build artefacts that regenerate on next use, never your documents. Start with
npx linux-cleanup --scan, which deletes nothing and prints exactly what it would reclaim. Linux only — npm refuses to install it on macOS or Windows.
linux-cleanup reclaims disk space taken by regenerable junk on a Linux developer machine: package-manager
caches, browser caches, build caches, emulator images, stale node_modules, orphan downloads, system journals
and superseded kernels. It is a Bash tool with a thin Node launcher, so npx linux-cleanup runs it with
nothing to install. What sets it apart from a one-button cleaner is restraint — by default it deletes only
files untouched for 100+ days, refuses outright to operate inside your personal directories, and makes no
network calls of any kind.
| | |
|---|---|
| Version | 1.6.0 |
| License | MIT |
| Node | >=14 (launcher only) |
| Runtime | bash >= 4.0 + GNU coreutils |
| Platform | Linux only, including WSL2 |
| Install size | ~55 kB packed · ~174 kB unpacked |
| Undo | None — deletion is one-way |
| Status | Stable · actively maintained |
🧭 Table of Contents #
- 💡 Why linux-cleanup
- ✨ Features
- 📱 Platform Support
- 📋 Requirements
- 📦 Installation
- 🚀 Quick Start
- 🛠️ Usage
- ⚙️ Configuration
- 💻 Command Line
- 🧪 Examples
- 🎛️ Advanced Features
- 🚑 Recovery & Troubleshooting
- 🚧 Limitations
- ❓ FAQ
- 📚 Documentation
- 🔄 Changelog
- 🤝 Contributing
- 🗂️ Repository
- 💬 Support
- 📄 License
- 👤 Author
- 🔗 Links
- 🏷️ Keywords
💡 Why linux-cleanup #
A working developer machine accumulates junk in places no general-purpose cleaner knows about: the Yarn and
pnpm stores, Gradle wrapper distributions, Cypress and Playwright browser binaries, Android emulator images,
node_modules for a project you finished last spring. Clearing them by hand means maintaining a private list
of rm -rf incantations and remembering which ones are safe.
The obvious fix — a cleaner that wipes every cache it finds — trades one problem for another. A full wipe of
~/.gradle/wrapper/dists/ reclaims a few hundred megabytes and costs you the re-download next time you open
that project. linux-cleanup takes the narrower path:
| | linux-cleanup | A wipe-everything cleaner | Doing it by hand |
|---|---|---|---|
| Default action | deletes only files idle 100+ days | deletes the whole cache | whatever you typed |
| Knows dev caches | Yarn, pnpm, Gradle, Cypress, Playwright, AVDs, pub-cache | varies | you maintain the list |
| Personal directories | hard refusal, no flag bypasses it | usually configurable | nothing stops you |
| Unattended use | --all-safe -y, cron-friendly | GUI-first | scriptable |
| Network calls | none | varies | none |
| Undo | none | none | none |
Nothing here can tell you how much you will reclaim — that depends entirely on what is on your disk. Run
--scan and it will tell you, without deleting anything.
Not the right tool when you want an undo or a backup (it has neither — it deletes, it never archives); when you are on macOS or Windows; when you want a point-and-click GUI as the primary interface; or when you are looking for a security scanner — it will not find secrets, malware, or vulnerabilities.
✨ Features #
- Prune, don't wipe — for every cache target, only files whose
atimeandmtimeare both older than the threshold are removed. Recently-used files survive. - Allowlist refusal —
safe_rmrejects any path resolving inside~/Documents,~/Pictures,~/.ssh,~/.gnupg,~/.config,/etc,/boot,/usr, bare$HOMEand more. No flag bypasses it. - Symlink-aware — paths are resolved with
realpathbefore the guard runs, so a symlink into a protected directory cannot smuggle a deletion past it. - Personal data is interactive only — never batched, never covered by
--yes. - Guided walkthrough by default — every category in turn, each one asking before it acts, with a running total of bytes reclaimed.
- Refuses to guess — idle detection needs access times. On a filesystem mounted
noatimethey are not recorded, so idle-based pruning switches itself off there instead of deleting a cache that is in use. - Speed check —
--speedmeasures why a machine is slow (overheating, memory / CPU / IO pressure, boot time) and offers undoable fixes for the containers, servers and apps that start by themselves. It deletes nothing and never acts under--yes. - Read-only modes —
--scan,--list-targets,--auditand--globalsinspect and report without deleting anything. - Offline by design — zero network calls, no telemetry, no analytics, no update check. Verifiable in the source; see Safety.
- Session reports — every run writes a schema-versioned JSON record, exportable to Markdown or HTML.
- Self-test — verifies dependencies, shell syntax, and that the safety guards actually fire.
- Crash bundles — an unexpected failure packages the log, latest report and a system manifest locally for you to review and email. Nothing is ever sent for you.
📱 Platform Support #
| Platform | Supported | Notes |
|---|---|---|
| Linux (Debian, Ubuntu, Fedora, Arch, …) | ✅ | The primary and only supported target. |
| WSL2 | ✅ | Runs on the Linux side; Windows-side directories under /mnt/c/ are not scanned. |
| macOS | ❌ | os: ["linux"] makes npm refuse to install; the launcher also exits 2. |
| Windows (native) | ❌ | No Bash or GNU coreutils environment. |
📋 Requirements #
| Requirement | Version | Why |
|---|---|---|
| bash | >= 4.0 | The scripts use associative arrays and ${var,,}, absent from Bash 3.2. |
| GNU coreutils | any current | realpath -m powers the symlink-resolving safety guard; the BSD build has no -m. |
| find, du, df, awk, sed, grep, stat, sort | any | Core scanning and measurement. Pre-installed on every mainstream distro. |
| Node.js | >= 14 | Only for the npx / global-install launcher. Running cleanup.sh directly needs no Node. |
| jq | any | Optional — required only to export a JSON report to Markdown or HTML. |
| sudo | any | Optional — required only by --system. |
| whiptail or dialog | any | Optional — required only by --tui; falls back to the CLI menu. |
| numfmt, snap, crontab, xdg-open, less | any | Optional — each enables one feature; absence degrades gracefully. |
Run linux-cleanup --self-test to see which optional commands are missing on your machine.
📦 Installation #
No install needed — npx fetches and runs it:
npx linux-cleanup --scanTo keep it on your PATH:
npm install -g linux-cleanupOr clone the repository and run the Bash entry point directly, with no Node involved:
git clone https://github.com/aoneahsan/linux-cleanup.git ~/linux-cleanup
cd ~/linux-cleanup
chmod +x cleanup.sh
./cleanup.sh --self-testThere is no build step and no post-install configuration. The one thing worth knowing is where output lands, because it differs between the two paths:
| | Logs and reports |
|---|---|
| Installed via npx or npm i -g | ~/.linux-cleanup/ — outside the package, so npx cache eviction cannot delete your history |
| Run from a clone | logs/ and reports/ inside the clone |
Both are configurable — see Configuration.
🚀 Quick Start #
Start read-only. This deletes nothing; it prints every reclaimable target it found and what each one holds:
npx linux-cleanup --scanWhen you are ready to delete, run it with no flags for the guided walkthrough, which asks before every step.
🛠️ Usage #
See what could be reclaimed
linux-cleanup --scan # read-only audit, grouped by category
linux-cleanup --list-targets # every path the tool is capable of touchingClean interactively
linux-cleanup # guided walkthrough — prompts at every step
linux-cleanup --menu # jump straight to one categoryClean unattended
linux-cleanup --all-safe --yes--yes applies to regenerable caches only. No flag combination will batch-delete personal files.
Sweep more or less aggressively
linux-cleanup --all-safe -d 30 # anything idle 30+ days, instead of the default 100Find what slows the machine down
linux-cleanup --speed # measures first; each fix asks and prints its undo commandIt reports thermal throttling, pressure, the heaviest processes and boot time, then looks for auto-start Docker containers, database / web / VM services enabled at boot, and login items. Nothing is deleted.
System-level cleanup
linux-cleanup --system # apt, journal, snap revisions, old kernels, /tmp, page cachePrompts for sudo once and keeps it alive only for this step.
Work with reports
linux-cleanup --reports # interactive manager: list, view, convert
linux-cleanup --export both latest # export the newest report to Markdown + HTML⚙️ Configuration #
Behaviour is set by flags, two optional plain-text lists, and these environment variables.
| File (one absolute path per line, # comments) | Used by |
|---|---|
| ~/.config/linux-cleanup/project-roots.txt | --node-modules — where your projects live. Searched in addition to whichever of ~/code, ~/projects, ~/dev, ~/src, ~/work, ~/workspace, ~/repos, ~/git, ~/Documents/projects, ~/Documents/code exist. |
| ~/.config/linux-cleanup/personal-roots.txt | --stale — extra folders to check besides ~/Downloads and ~/Desktop. |
/, your whole home directory, and ~/.ssh, ~/.gnupg, ~/.config, ~/.claude are refused as roots.
| Variable | Default | What it does |
|---|---|---|
| LINUX_CLEANUP_HOME | ~/.linux-cleanup | Parent directory for logs and reports. Read by the Node launcher only — it has no effect when you run cleanup.sh directly from a clone. |
| LINUX_CLEANUP_LOG_DIR | ~/.linux-cleanup/logs or <clone>/logs | Where session logs are written. Honoured on every path, including a clone. |
| LINUX_CLEANUP_REPORTS_DIR | ~/.linux-cleanup/reports or <clone>/reports | Where JSON reports are written. Honoured on every path. |
| LINUX_CLEANUP_DATA_HOME | unset | Parent used to locate the feedback/ directory for debug and crash bundles. |
| NO_COLOR | unset | Any non-empty value disables ANSI colour. Same as --no-color. |
| CLEANUP_NO_COLOR | 0 | Set to 1 to disable colour for this tool only. |
| XDG_CONFIG_HOME | ~/.config | Where personal-roots.txt and project-roots.txt are read from. |
Full reference: Environment variables.
💻 Command Line #
linux-cleanup [mode] [options]Running it with no mode starts the guided walkthrough. Every mode marked 🔥 deletes files permanently. Before using one, run the read-only equivalent:
linux-cleanup --scan # the dry run: reports what would be reclaimed, deletes nothingModes
| Mode | Flag | What it does |
|---|---|---|
| Walkthrough | (default) · -w | 🔥 Guided cleanup through every category, prompting before each step |
| Menu | -m | 🔥 Jump-to menu — run a single category |
| TUI | -t --tui | 🔥 whiptail/dialog menu; falls back to the CLI menu if neither is installed |
| All-safe | -a | 🔥 Every regenerable cache in one pass |
| System | --system | 🔥 apt, journal, snap revisions, old kernels, /tmp, page cache (needs sudo) |
| Stale personal files | -p --stale | 🔥 Large personal files idle N+ days — interactive confirmation only |
| Partial downloads | --partials | 🔥 Orphan .fdmdownload, .crdownload, .part files |
| Stale node_modules | --node-modules | 🔥 node_modules in projects untouched N+ days |
| Editor extensions | --editor-ext | 🔥 Superseded VS Code / Cursor extension versions |
| Scan | -s --scan | Read-only audit — no deletions |
| List targets | --list-targets | Read-only — prints every path the tool can touch |
| Home audit | --audit | Read-only — 20 largest entries in $HOME |
| Globals audit | --globals | Read-only — stale global npm/pnpm/yarn/bun/deno packages |
| Doctor | --doctor | Repairs missing shell-init blocks. Appends only, with confirmation |
| Speed check | --speed | Why is this machine slow? Read-only report, then undoable fixes asked one by one. Never deletes; report-only under -y |
| Reports | --reports | Manage past reports — list, view, convert |
| Export | --export FMT ID | Export a report. FMT = md|html|both, ID = N|latest|all |
| Self-test | --self-test | Verify dependencies, syntax, and safety guards |
| Feedback | --feedback | Print bug-report instructions, offer a pre-filled mailto: draft |
| Debug bundle | --debug-bundle | Package the latest log and report into a local .tar.gz |
| Alias / cron | --install-alias --install-cron | Add the cleanup alias or a weekly run. Under npx or a global install they run a persistent copy in ~/.linux-cleanup/app. --uninstall-* removes them |
| Version | -V --version | Print version and author |
| Help | -h --help | Print the full flag list |
Options
| Flag | Default | What it does |
|---|---|---|
| -d N --days N | 100 | Idle threshold. A file is deleted only when both atime and mtime exceed it. Ignored — nothing idle-based is deleted — on a noatime filesystem. |
| --purge-all | off | 🔥 Disables the idle gate and empties cache targets completely. Removes rarely-used assets such as Gradle wrapper distributions. |
| -y --yes | off | Auto-confirm regenerable caches. Valid with --all-safe only; never applies to personal files. |
| --no-report | off | Skip JSON report generation. Logs are still written. |
| --cleanup-logs | off | Delete this run's logs at the end. Reports are always kept. |
| --no-color | off | Disable ANSI colour. |
Full list: CLI flags reference.
🧪 Examples #
| Goal | Command |
|---|---|
| See what is reclaimable, risk-free | linux-cleanup --scan |
| Convince yourself before deleting | linux-cleanup --self-test && linux-cleanup --list-targets |
| Reclaim the most space in one pass | linux-cleanup --all-safe -y -d 30 |
| Free space before re-imaging a machine | linux-cleanup --all-safe -y --purge-all |
| Find forgotten project dependencies | linux-cleanup --node-modules -d 180 |
| Weekly unattended run via cron | linux-cleanup --all-safe -y --no-report --cleanup-logs |
| Machine-readable output for CI | NO_COLOR=1 linux-cleanup --scan --no-report > scan.log |
Longer recipes: Reclaim the most space.
🎛️ Advanced Features #
- Visual TUI — a whiptail/dialog menu for pointing rather than typing. Docs
- Globals audit — lists global packages with no dependent and no recent use, and prints the uninstall commands. Never deletes. Docs
- Doctor — detects a runtime installed on disk but missing from
~/.bashrcand offers to append the init block. Append-only. Docs - Report export — schema-versioned JSON to self-contained HTML or Markdown. Docs
- Shell alias and weekly cron — one-command install and removal. Docs
- Crash bundles — captured locally on unexpected failure, never transmitted. Docs
🚑 Recovery & Troubleshooting #
| Symptom | Cause | Fix |
|---|---|---|
| refusing to delete inside protected path | The resolved path lands inside the allowlist — often a symlink pointing into a personal directory. | Working as designed. Check the symlink with realpath <path>. |
| bash 3.2 — version 4+ required | Bash 3.2, typically macOS. | Not supported. This tool is Linux-only. |
| export requires 'jq' | jq is missing. | sudo apt install jq. JSON reports are still written without it. |
| TUI mode needs 'whiptail' or 'dialog' | Neither is installed. | Install one, or use --menu — the message prints the command for your distro. |
| $HOME is not set | Run from a context with no $HOME, e.g. some cron or systemd units. | Set HOME explicitly in the unit or crontab. |
| Cron entry runs but nothing happens | Cron's PATH lacks the install location. | Use the absolute path to the binary in the crontab entry. |
| Reclaimed less than expected | The idle gate spared recently-used files. | Lower the threshold with -d 30, or use --purge-all. |
| Disk usage grew during the session | A running process wrote more than the run reclaimed. | Re-check with df -h once the process settles. |
| A crash bundle appeared but nothing crashed | A non-zero exit the trap treats as unexpected. | Inspect with tar -tzf; delete it if uninteresting. |
| alias cleanup … not found after --install-alias | The shell rc has not been re-read. | source ~/.bashrc, or open a new terminal. |
Every symptom in full: Troubleshooting.
🚧 Limitations #
- No undo, and no backup. Deleted files are gone. There is no archive, no trash, no restore. This is deliberate — an undo log would consume the disk you are trying to free and encourage careless use.
- Linux only. macOS and native Windows are unsupported and blocked at install.
- Bash 4+ and GNU coreutils are hard requirements. The safety guard depends on
realpath -m, a GNU extension; on a BSD userland the guard cannot resolve paths and refuses everything. - It cannot promise a number. How much you reclaim depends on your machine.
--scanmeasures it; the README will not guess it. --systemneedssudoand touches package manager state, journals and kernels. Review the prompts.- Markdown and HTML export need
jq. Without it, JSON reports are still written; only conversion is unavailable. - Idle detection needs access times. On a filesystem mounted
noatime, every idle-based prune is skipped with a warning; only--purge-alldeletes there.relatime, the Linux default, works. - Not a backup tool, not a security scanner, not a tuner. It will not find secrets or malware.
--speedfinds the usual causes of a slow machine and offers a few undoable fixes; it does not tune the kernel, and it cannot fix a CPU that overheats. Freeing disk space rarely makes a machine faster. - No automated test suite. Correctness rests on
--self-test, ShellCheck, and manual verification on a real Linux system.
❓ FAQ #
Will it delete my code?
Not from a protected directory, and not without asking. node_modules is the one project-adjacent target, it
is interactive, and it regenerates from your lockfile.
Does it phone home?
No. Zero network calls — no telemetry, no analytics, no update check. Verify it yourself with
grep -rE 'curl|wget|http(s)?://[^/]' cleanup.sh lib/ modules/; the only matches are comments, the
--feedback mailto: helper, and documentation.
Why is there no undo? Because an undo log would be write amplification on the disk you are trying to free, and it would create a false sense of safety. The allowlist, the idle gate and interactive confirmation are the real defence.
What is the safest way to try it?
--self-test, then --scan, then --list-targets. All three are read-only. After that you have seen the
safety model work without losing a byte.
Does it work under WSL?
Yes, on the Linux side. Windows-side directories under /mnt/c/ are not scanned.
Why Bash rather than Rust or Go? Bash is already on every target system, so there is no runtime to install and no binary to trust. The source is auditable in an afternoon.
More: FAQ.
📚 Documentation #
| Document | Read it when | |---|---| | Documentation index | you want the full map | | Quick start | running your first cleanup | | Safety | you want to understand the guards before deleting anything | | Speed check | the machine is slow and you want to know why | | CLI flags | you need an exact flag | | Exit codes | scripting around it in cron or CI | | Report schema | parsing the JSON output | | Troubleshooting | something failed | | Uninstall | removing it cleanly |
🔄 Changelog #
Latest release: 1.6.0 — a --speed check for what slows a machine down, idle pruning that switches itself off on noatime filesystems, configurable project and personal folders, and an alias and cron entry that survive npx cache eviction.
Full history: CHANGELOG.md.
🤝 Contributing #
Fork and open a pull request — no special access needed. See
CONTRIBUTING.md for setup, the
safety-first coding standards, and how to request collaborator access. main is protected: every change
lands through a reviewed PR.
🗂️ Repository #
cleanup.sh entry point — argument parsing and dispatch
lib/ common.sh (safe_rm, guards, UI, JSON helpers) · scan.sh (read-only scanners)
modules/ one file per mode — walkthrough, all_safe, system_sudo, reports, tui, doctor, …
bin/ Node launcher used by npx and global install
docs/ full documentation (not shipped in the npm tarball)
assets/ logo master💬 Support #
Questions and bugs: open an issue. For a bug, run
linux-cleanup --debug-bundle first and attach the archive after reviewing it — it contains $HOME paths
from your machine. Security reports go privately to
[email protected].
If this tool saved you time, you can support its maintenance at aoneahsan.com/payment.
📄 License #
MIT © Ahsan Mahmood — see LICENSE. Provided "AS IS", without warranty; this tool deletes files, so review what it proposes before confirming.
👤 Author #
Ahsan Mahmood — aoneahsan.com · GitHub · LinkedIn · [email protected]
🔗 Links #
| | | |---|---| | Documentation | https://github.com/aoneahsan/linux-cleanup/blob/main/docs/README.md | | npm | https://www.npmjs.com/package/linux-cleanup | | Repository | https://github.com/aoneahsan/linux-cleanup | | Issues | https://github.com/aoneahsan/linux-cleanup/issues | | Changelog | https://github.com/aoneahsan/linux-cleanup/blob/main/CHANGELOG.md | | Contributing | https://github.com/aoneahsan/linux-cleanup/blob/main/CONTRIBUTING.md | | Support the project | https://aoneahsan.com/payment?project-id=linux-cleanup&project-identifier=linux-cleanup |
🏷️ Keywords #
linux · cleanup · disk-cleanup · cache-cleanup · disk-space · node-modules · yarn-cache · npm-cache · developer-tools · system-utility · bash · cli
