Skip to content

mole — macOS cleanup, disk analyze, dev-artifact purge

tw93/Mole (mole, short entrypoint mo) is a macOS maintenance CLI: it clears caches, uninstalls apps together with their leftovers, explores disk usage, and — the reason it is in this repo — reclaims developer build artifacts (node_modules, target, .venv, build, dist) across every checkout you point it at.

  • Install: macOS only, Homebrew formula mole from homebrew-core (dot_config/homebrew/Brewfile.tmpl), gated on the installMole prompt.
  • Not available on Linux — see Why macOS only.
  • Managed config: ~/.config/mole/whitelist and ~/.config/mole/purge_paths, seeded once by chezmoi (create_ prefix).
  • Shell helpers: dot_config/shell/33_mole.sh → moa, moclean, mowl.
  • Completions: zsh + bash, regenerated by scripts/generate_completions.sh.

Daily commands

mo                       # interactive menu
mo purge                 # remove old project build artifacts (the dev-facing one)
mo purge --dry-run       # preview it first
mo analyze ~/Documents   # visual disk explorer, scoped to a path
mo status                # live CPU / GPU / memory / disk / network dashboard
mo clean --dry-run       # preview a cache cleanup
mo history               # what previous runs deleted

Helpers this repo adds

Function What it does
moa [dir] mo analyze scoped to dir (default: cwd). Bare mo analyze explores $HOME, which is rarely what you want.
moclean [args…] Runs mo clean --dry-run first, prints the plan, then asks before the real run. mo clean on its own deletes without a confirmation step.
mowl Prints the effective entries of both managed config files plus the commands to edit or re-baseline them.

They live in dot_config/shell/33_mole.sh and self-disable when mole is not on PATH, so the fragment is inert on Linux. mo is upstream's own short entrypoint — nothing here aliases over it.


The two managed config files

Both are chezmoi create_ seeds: chezmoi writes them once and never touches them again, because mole rewrites them itself through mo clean --whitelist and mo purge --paths. To promote your local edits back into the repo, copy directly — chezmoi add strips the create_ prefix and chezmoi re-add silently skips:

cp ~/.config/mole/whitelist "$(chezmoi source-path ~/.config/mole/whitelist)"

whitelist — replacement, not addition

The existence of the file disables mole's built-in defaults

From mole V1.7.5 on, a present ~/.config/mole/whitelist is treated as the complete protected set. DEFAULT_WHITELIST_PATTERNS is dropped entirely; only SAFETY_WHITELIST_PATTERNS (Spotlight, FontRegistry, CloudKit, Poetry virtualenvs, Finder metadata) still merge unconditionally. Upstream documents the resulting regression at lib/core/base.sh:188-192.

That is why the seeded file re-lists upstream's own defaults verbatim before it adds anything. Deleting a line from that first block silently removes a protection, it does not fall back to the default. tests/unit/mole.bats locks the list so the block cannot be trimmed by accident.

On top of the upstream defaults the seed protects this repo's own bootstrap surfaces:

Path Why
~/.cache/uv/* uv bootstraps every PEP723 script here (fleet, tsnet, mlf, yth, ytmv, pqsum, dotfiles_init) and the just recipes that call them. mole targets ~/.cache/uv in lib/clean/dev.sh; a cold cache turns the next chezmoi apply into a full re-download.
~/.bun/install/cache/* bun runs copilot-throttle-shim.js on every copilot-proxy call.
~/.local/share/mise/* mise keeps real runtime installs here, not just cached downloads.

Format: one absolute path or glob per line, # comments, ~ and $HOME expanded, no .., no //.

purge_paths — mole cannot be pointed at a directory any other way

mo purge takes no path argument. The only way to choose what it scans is this file, and when it has entries they replace mole's auto-discovery entirely (lib/clean/project.sh).

Auto-discovery would not find this machine's main checkout anyway: it globs $HOME/*/ at depth 1 and probes maxdepth 2 for project indicators, so ~/Documents/Program/<repo> sits one level too deep to be detected. The seed therefore lists:

  • ~/Documents/Program — the main checkout root
  • ~/Worktrees — where worktrunk / dev-cli park git worktrees, each with its own node_modules / target / .venv copy

Add more with mo purge --paths, then re-baseline with the cp command above.


Upgrading

mole is a Homebrew formula, so just upgrade-brew already covers it and there is no just upgrade-mole recipe.

Never run mo update on a Homebrew install

mole ships its own updater, which installs into /usr/local/bin and fights the symlinks Homebrew owns there. mo update is for the install.sh channel only.


Why macOS only

Mole is not a cross-platform tool that happens to be untested elsewhere; it is built on macOS system surfaces from top to bottom.

Status
macOS Fully supported. homebrew-core formula, GPL-3.0-or-later, releases roughly weekly. Note that homebrew-core ships arm64 bottles only — an Intel Mac builds it from source (build dependency: go), which adds a minute or two to the first apply.
Linux Not supported, and not a porting candidate. install.sh refuses to run when $OSTYPE is not darwin* ("This tool is designed for macOS only"). cmd/analyze is entirely //go:build darwin with a !darwin stub that prints "analyze is only supported on macOS" and exits 1. The ~46k lines of shell reference Library/Caches 335 times, com.apple 282 times, mdfind 74 times, plus defaults, osascript, tmutil, launchctl, diskutil.
Windows A native PowerShell port lives on the windows branch, but it is not adopted here. Upstream's own README opens with a warning that the Windows version "is currently not mature… please do not use this tool". It sits at 1.30.0 against main's 1.53.0, its scoop / winget / chocolatey manifests are all unpublished and point at a contributor fork, and installation is a git clone of the branch with mo update implemented as git pull.

The cross-repo decision record, including what would have to change before the Windows branch is reconsidered, lives in the superproject at docs/mole-macos-only.md.


  • btop — the cross-platform live monitor; mo status overlaps with it on macOS only.
  • macOS swap & memory — memory pressure diagnosis.
  • chezmoi prefixes — why these two files use create_.
  • mo touchid configures Touch ID for sudo. It is deliberately not wired into this repo's apply — it edits /etc/pam.d/sudo_local, which is outside chezmoi's remit. Run it by hand if you want it.