Metadata-Version: 2.4
Name: purger
Version: 0.4.0
Summary: Find and clean rebuildable developer caches to free disk space.
Keywords: cache,cleanup,cli,disk-space,docker,homebrew,uv,xcode
Author: Nate Landau
Author-email: Nate Landau <github@natenate.org>
License-Expression: MIT
License-File: LICENSE
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: Operating System :: MacOS
Classifier: Operating System :: POSIX :: Linux
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Programming Language :: Python :: 3.15
Classifier: Topic :: System :: Filesystems
Classifier: Topic :: Utilities
Requires-Dist: cyclopts>=5.4.0,<6
Requires-Dist: nclutils>=4.0.0,<5.0.0
Requires-Dist: psutil>=7.0.0,<8
Requires-Dist: rich>=15.0.0,<16
Requires-Python: >=3.13
Project-URL: Changelog, https://github.com/natelandau/purger/releases
Project-URL: Homepage, https://github.com/natelandau/purger
Project-URL: Issues, https://github.com/natelandau/purger/issues
Project-URL: Repository, https://github.com/natelandau/purger
Description-Content-Type: text/markdown

# purger

purger finds the caches that developer tools leave on your disk, shows how much space each cache uses, and removes the caches that you approve. It uses the cleanup command of each tool when the tool has one. It deletes a cache directory by hand only when no command exists, and only inside your home directory.

Without `--dangerous` and your explicit confirmation, purger never deletes your files, your projects, or data that cannot be rebuilt.

## What purger cleans

purger runs on macOS and Linux. Each supported tool is a plugin, and each plugin has one or more cleanup actions.

- `apt` (Linux): downloaded package files. Both actions run with sudo.
- `brew` (macOS, Linux): old formula versions, the download cache, and dependencies that nothing needs anymore.
- `bun` (macOS, Linux): packages unused for 30 days, or the entire cache with `--dangerous`.
- `cocoapods` (macOS): the pod download cache.
- `conda` (macOS, Linux): downloaded package tarballs, packages that no environment uses, the index cache, and logs.
- `corepack` (macOS, Linux): downloaded yarn, pnpm, and npm versions.
- `dnf` (Linux): downloaded package files. Runs with sudo.
- `docker` (macOS, Linux): the build cache, unused images, stopped containers, unused networks, and unused volumes.
- `flatpak` (Linux): runtimes and extensions that no app uses, in your user installation and, with sudo, the system installation.
- `go` (macOS, Linux): the build cache and the module download cache.
- `macports` (macOS): build files, source archives, and inactive ports. Both actions run with sudo.
- `maestro` (macOS, Linux): logs, screenshots, and local recordings of past `maestro test` runs. Skipped while Maestro runs.
- `mise` (macOS, Linux): stale cache files and unused tool versions, or the entire cache with `--dangerous`.
- `npm` (macOS, Linux): unneeded cache data and the npx cache, or the entire cache with `--dangerous`.
- `pacman` (Linux): cached package versions beyond the newest 3, and every cached version of uninstalled packages. Needs `paccache` from pacman-contrib, and runs with sudo.
- `pip` (macOS, Linux): the download and wheel cache, even when pip is no longer installed.
- `playwright` (macOS, Linux): browser builds older than the newest of each browser.
- `poetry` (macOS, Linux): the package cache and the virtualenvs Poetry created, even when Poetry is no longer installed. Follows `POETRY_CACHE_DIR` and `POETRY_VIRTUALENVS_PATH`.
- `pnpm` (macOS, Linux): store packages that no project uses, and registry metadata in formats the installed pnpm can no longer read.
- `podman` (macOS, Linux): unused images, stopped containers, pods, networks, and build cache, and unused volumes with `--dangerous`.
- `pre-commit` (macOS, Linux): unused hook repos, or the entire cache with `--dangerous`.
- `prek` (macOS, Linux): unused hook environments, or the entire cache with `--dangerous`.
- `projects` (macOS, Linux): tool caches, installed dependencies, and build output inside the project folders you list in the config. It does nothing until you set `paths`. See [Configuration](#configuration).
- `rip2` (macOS, Linux): the rip2 graveyard of deleted files. Runs only when `rip` on PATH is rip2.
- `ruby` (macOS, Linux): old gem versions that no installed gem needs.
- `simulators` (macOS): simulator devices the installed Xcode cannot run.
- `swiftpm` (macOS, Linux): cached package clones, manifests, and binary frameworks.
- `thumbnails` (Linux): the desktop file thumbnail cache.
- `trash` (macOS, Linux): everything in the Trash in your home folder. On macOS, the terminal needs Full Disk Access.
- `uv` (macOS, Linux): unused cache entries, or the entire cache with `--dangerous`.
- `xcode` (macOS): build products, device debug symbols, and app archives.
- `yarn` (macOS, Linux): the global package cache, even when yarn is no longer installed.

purger skips a plugin when its tool is not installed, is not running, is running a command that could use the files a cleanup removes, or does not apply to your platform. Run `purger clean --dry-run` to see the actions that would run, with their risk tiers.

## Install

purger needs Python 3.13 or later.

To install purger with uv, run this command:

```bash
uv tool install purger
```

To install purger with pip, run this command:

```bash
pip install purger
```

Run purger as your normal user. purger refuses to run as root. It asks for sudo only for the actions that need it, such as the `apt` and `macports` actions.

## Quick start

Start with `purger info`. It measures each cache and prints a table with one row for each tool: the size of its cache and a short description. A check in the `Partial purge` column means that a clean removes only part of that size. `purger info` deletes nothing.

```bash
purger info
```

Then run `purger clean`. It prints the same table, asks for confirmation, and runs the cleanups that you approve. At the end, it prints a table with the size of each cache before and after the clean, and the space that was freed.

```bash
purger clean
```

## Commands

Both commands accept plugin names as arguments. Without names, a command uses every plugin.

```bash
purger info uv brew              # measure only the uv and Homebrew caches
purger info projects -v          # list each project and the space it uses
purger clean xcode --dry-run     # show what would be cleaned, change nothing
purger clean docker --dangerous  # also offer to remove unused Docker volumes
```

These options apply to both commands:

| Option        | Effect                                                                                                                                |
| ------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| `--dangerous` | Include `dangerous` actions. Without it, purger hides them.                                                                           |
| `--json`      | Print exactly one JSON document on stdout instead of tables and messages.                                                             |
| `-v`, `-vv`   | Show what each size holds, such as each project or simulator, and the output of the tool commands. `-vv` also lists each row's paths. |

These options apply to `purger clean` only:

| Option            | Effect                                                                                                                        |
| ----------------- | ----------------------------------------------------------------------------------------------------------------------------- |
| `--dry-run`, `-n` | Show one line per action, with the size it would delete or the command it would run. purger asks nothing and changes nothing. |
| `--yes`, `-y`     | Skip the single prompt for `safe` actions.                                                                                    |

## Configuration

purger works without a config file. Create one to turn off plugins or to change plugin settings.

purger looks for the file in this order:

1. The path in the `PURGER_CONFIG` environment variable. The file must exist.
2. `$XDG_CONFIG_HOME/purger/config.toml`.
3. `~/.config/purger/config.toml`.

If no file exists, purger uses its defaults.

```toml
# Plugins that `purger info` and `purger clean` leave out when you name no plugin.
skip = ["docker", "xcode"]

# Settings for one plugin. This table is an example: `example` and `roots` are
# placeholders, not a real plugin or setting.
[plugins.example]
roots = ["~/code", "~/work"]
```

The `skip` setting applies only when you name no plugins. If you name a plugin on the command line, purger measures it even when `skip` lists it. A skipped plugin appears in the `skipped` list with the reason `disabled`.

An environment variable replaces the same setting in the file. Set `PURGER_SKIP` for the general `skip` setting. For a plugin setting, join the plugin name and the setting name with two underscores, in upper case. A hyphen in the plugin name becomes an underscore. Write a list as comma-separated values.

```bash
PURGER_SKIP=docker,xcode purger info
PURGER_EXAMPLE__ROOTS=~/code,~/work purger info example
```

purger prints a warning on stderr for an unknown key or plugin name. It exits with code `2` for an invalid value or a file that is not valid TOML. With `--json`, the error document has the code `config_error`.

The config never changes what needs confirmation. You cannot set `--yes`, `--dangerous`, or a tier in the file.

### Clean project folders

The `projects` plugin looks for leftovers inside your project folders, such as `.mypy_cache`, `node_modules`, and `.venv`. It scans only the folders in `paths`. Each one must be an absolute path (or start with `~/`) to an existing folder inside your home folder, on the same device as your home folder. purger ignores these paths and prints a warning: a relative path, a path outside your home folder, your home folder itself, a folder that does not exist, and a path on another device.

```toml
[plugins.projects]
# Folders that hold your projects. Env var: PURGER_PROJECTS__PATHS
paths = ["~/repos"]
# Folder levels to search below each path. Env var: PURGER_PROJECTS__MAX_DEPTH
max_depth = 6
# Leave a project alone when a file in it changed within this many days.
# 0 turns the check off. Env var: PURGER_PROJECTS__RECENT_DAYS
recent_days = 7
# Folder names, patterns, or absolute paths that purger never removes or
# searches for leftovers. A recent change inside one still keeps its project.
# A path must start with / or ~/.
# Env var: PURGER_PROJECTS__EXCLUDE
exclude = ["~/repos/keep", "vendor"]
# Extra folder names or patterns to offer for removal. No slashes.
# Env var: PURGER_PROJECTS__INCLUDE
include = ["scratch"]
```

purger always leaves alone folders that hold git-tracked files. It also leaves alone a project with recent file changes, for every action, including the `safe` caches. It removes `build`, `dist`, and `target` only when git tracks the project file next to them, such as `package.json` or `Cargo.toml`. The `caches` action is `safe`. The `dependencies`, `builds`, and `custom` actions are `caution`.

## Risk tiers

Each cleanup action has one tier. The tier controls how purger asks for confirmation.

| Tier        | Meaning                                                                               | Confirmation                                    |
| ----------- | ------------------------------------------------------------------------------------- | ----------------------------------------------- |
| `safe`      | The tool rebuilds the cache cheaply and automatically.                                | One prompt for all `safe` actions.              |
| `caution`   | The cache can be rebuilt, but the rebuild is slow or a large download.                | One prompt for each action.                     |
| `dangerous` | The action can destroy data that cannot be recreated, or it removes a complete cache. | Shown only with `--dangerous`. One prompt each. |

The `--yes` flag skips only the prompt for `safe` actions. A `caution` or `dangerous` action never runs unless a person answers its prompt.

> **Warning:** Docker `volumes` is a `dangerous` action. It deletes every volume that no container uses, which includes the data of local databases.

## Use purger in scripts and agents

Add `--json` to a command to get exactly one JSON document on stdout. Every document has `"schema_version": 1`, and every size is an integer number of bytes.

```bash
purger info --json
purger clean --json --yes
```

`purger clean --json` never prompts. With `--yes`, it runs the `safe` actions only. It reports each `caution` and `dangerous` action as `declined`. Without a terminal, purger applies the same rules.

Each entry in `skipped` has a `reason`: `platform`, `missing_binary`, `unavailable`, `disabled`, or `not_configured`. The `disabled` reason means the `skip` setting in the config file turned the plugin off. The `not_configured` reason means the plugin needs a setting, such as search paths, that the config file does not provide.

The help pages give the full document shape and the status values:

```bash
purger info --help
purger clean --help
```

## Exit codes

Both commands use these exit codes:

| Code  | Meaning                                                                                                         |
| ----- | --------------------------------------------------------------------------------------------------------------- |
| `0`   | Success. This includes a run where you declined every action.                                                   |
| `1`   | An action that you approved failed. Only `purger clean` uses this code.                                         |
| `2`   | A usage error, such as an unknown plugin name, an invalid config file or `PURGER_*` variable, or a run as root. |
| `130` | You pressed Ctrl-C.                                                                                             |

## Contributing

To build purger, run the tests, or add a plugin, read [CONTRIBUTING.md](CONTRIBUTING.md).

## License

purger is available under the [MIT License](LICENSE).
