A CLI utility that audits your local machine for stuff you forgot and helps you safely reclaim disk space.
Project description
bekas
One audit. Every kind of forgotten thing. Nothing deleted you cared about.
bekas is a CLI utility that audits your local machine for stuff you forgot — orphaned Docker images, unused git branches, old node_modules, dangling Python venvs, stale downloads, screenshots from years ago — and helps you safely reclaim disk space. Every destructive action is logged to an SQLite undo log and can be quarantined before permanent deletion.
Table of Contents
- Installation
- Quick Start
- Commands
- Plugins
- Configuration
- Safety Model
- Comparison
- Architecture & File Structure
- License
Installation
Recommended — use pipx or uv so bekas stays isolated from your project dependencies:
# pipx (most systems)
pipx install bekas
# uv (fastest)
uv tool install bekas
# Or plain pip if you prefer
pip install bekas
Requires Python 3.11+. Some plugins (e.g. Docker, Git) require the corresponding CLI tools to be installed.
Quick Start
# 1. Run a read-only audit
bekas audit
# 2. Preview what a clean would remove
bekas plan
# 3. Clean only the safest items (dry-run by default)
bekas clean --apply --safe-only
Commands
bekas audit
Runs a read-only scan across all available plugins and prints candidates.
bekas audit # Human-readable output
bekas audit --json # JSON output
bekas audit --plugin docker # Only run Docker plugins
bekas audit --serial # Run plugins one at a time
bekas audit --sort-by size # Sort by reclaimable size
bekas audit --top 20 # Only show top 20 candidates
bekas plan
Converts the latest audit into a concrete removal plan. You can save a cryptographically signed plan to disk and apply it later.
bekas plan # Preview in human-readable format
bekas plan --safe-only # Only SAFE-tier items
bekas plan --include-review # Include REVIEW-tier items
bekas plan --save plan.json # Save a signed plan file
bekas clean
The only command that actually removes files. Dry-run by default — you must pass --apply to delete anything.
bekas clean --apply --safe-only # Auto-clean safe items
bekas clean --apply --yes-all # Skip per-category prompts
bekas clean --apply --non-interactive \
--accept-categories "docker,tmp" # CI-friendly mode
bekas clean --apply --plan-file plan.json # Apply a signed plan
Options:
--apply— Actually delete (default is dry-run).--safe-only— Only includeSAFE-tier candidates.--review/--include-review— IncludeREVIEW-tier candidates.--yes-all— Skip all interactive prompts.--non-interactive— Requires--accept-categories.--accept-categories— Comma-separated category whitelist for non-interactive runs.--plan-file— Apply a previously saved signed plan instead of re-auditing.
bekas inspect <id>
Show full metadata and reasoning for a single candidate.
bekas inspect ss:Screenshot_2023-01-01.png
bekas history / bekas undo
Every clean --apply is persisted to an SQLite undo log.
bekas history # List past runs
bekas history <run_id> # Show details for one run
bekas undo # Undo the most recent run
bekas undo <run_id> # Undo a specific run
bekas quarantine
Files removed by plugins that support quarantine are moved to a quarantine directory instead of being permanently deleted. You can restore them later.
bekas quarantine list # Show quarantined items
bekas quarantine restore <quarantine_id> # Restore to original path
bekas quarantine purge # Empty quarantine immediately
bekas plugins
List, enable, or disable plugins.
bekas plugins list # Show installed plugins and availability
bekas plugins enable <name> # Enable a plugin (edit config)
bekas plugins disable <name> # Disable a plugin (edit config)
bekas config
Print the current effective configuration.
bekas config
bekas config show --resolved # Effective config after profile merge
bekas config validate # Validate config file syntax
bekas doctor
Diagnose the bekas runtime environment.
bekas doctor # Human-readable health check
bekas doctor --json # Machine-readable output
bekas doctor --skip docker # Skip specific checks
bekas tui
Launch an interactive Textual TUI for browsing candidates and cleaning interactively.
bekas tui
Plugins
| Plugin | Category | What it finds | Needs docker / git |
|---|---|---|---|
docker.images |
docker.image.* |
Dangling & unused Docker images | docker |
docker.containers |
docker.container.* |
Stopped containers | docker |
docker.buildx.cache |
docker.buildx.cache |
Stale BuildKit cache entries | docker |
python.venvs |
python.venv |
Orphaned Python virtual environments | — |
python.cache |
python.cache |
__pycache__, .pytest_cache, .mypy_cache, .ruff_cache |
— |
pip.cache |
pip.cache |
Stale pip download & wheel cache | — |
node.modules |
node.modules |
Old node_modules directories |
— |
rust.target |
rust.target |
Old target/ build directories |
— |
git.branches |
git.branch |
Fully-merged local branches | git |
downloads |
downloads.file |
Old files in ~/Downloads |
— |
screenshots |
screenshots.file |
Old screenshots (Desktop / Pictures) | — |
system.tmp |
system.tmp |
Old temp files owned by you | — |
system.trash |
system.trash |
macOS/Linux Trash contents | — |
dotfiles.backups |
dotfiles.backups |
Backup files like .zshrc.bak |
— |
xcode.derived_data |
xcode.derived_data |
Stale Xcode build caches (macOS only) | — |
Plugins are auto-discovered via entry_points in pyproject.toml. You can write your own by subclassing bekas.plugin.Plugin.
Configuration
The first time you run bekas, a config file is created at the platform-specific config directory (e.g. ~/.config/bekas/config.yaml on Linux).
Example:
version: "0.2.0"
active_profile: default
profiles:
default:
enabled_plugins: ["*"]
quarantine_enabled: true
# Per-plugin thresholds
plugin_settings:
screenshots:
min_age_days: 90
downloads:
min_age_days: 180
python.venvs:
min_idle_days: 90
node.modules:
min_idle_days: 180
rust.target:
min_idle_days: 60
python.cache:
min_idle_days: 90
system.tmp:
min_age_days: 30
git.branches:
min_idle_days: 90
# Repositories for the git.branches plugin
git_repos:
- ~/code
- ~/projects
Safety Model
- Read-only by default —
auditandplannever touch the filesystem. - Dry-run by default —
cleanwithout--applyonly prints a preview. - Confidence tiers — Every candidate is classified as:
SAFE— Low risk (e.g. dangling Docker image, no project nearby).REVIEW— Medium risk (e.g. old download, active project but untouched).MANUAL— High risk (e.g. branch on an active project, container in use).
- Hard exclusions — System paths and sensitive files are automatically excluded. See
docs/SAFETY.mdfor the full exclusion list. - Quarantine — Deletable files are moved to a quarantine folder so you can
restorethem later. - Undo log — Every
clean --applyis recorded in SQLite with per-candidate results and undo tokens. - Signed plans — Saved plan files include a signature to detect tampering.
- Typed confirmation gate —
clean --applyrequires typing"yes"(or a random token for high-risk plans) before any destructive action.
Architecture & File Structure
bekas/
├── src/bekas/
│ ├── __init__.py # Package metadata
│ ├── cli.py # Click CLI entry point & commands
│ ├── models.py # Core dataclasses: Candidate, Plan, AuditReport, etc.
│ ├── plugin.py # Plugin base class & discovery
│ ├── runner.py # Orchestrates plugin discovery and runs audits
│ ├── clean.py # Applies a Plan: removes, quarantines, logs
│ ├── safety.py # Exclusion engine (path safety, pattern matching)
│ ├── config.py # Config file I/O and profile resolution
│ ├── formatters.py # Human, JSON, Markdown output formatters
│ ├── database.py # SQLite undo log & quarantine registry
│ ├── quarantine.py # Move / restore / purge quarantined items
│ ├── signing.py # Plan file signing & verification
│ ├── doctor.py # Runtime environment diagnostics
│ ├── locking.py # Single-instance process lock
│ ├── tui.py # Textual interactive UI
│ └── plugins/
│ ├── docker_images.py # Dangling & unused Docker images
│ ├── docker_containers.py # Stopped containers
│ ├── docker_buildx.py # BuildKit cache
│ ├── python_venvs.py # Orphaned Python virtual environments
│ ├── python_cache.py # __pycache__ & tool caches
│ ├── pip_cache.py # pip download & wheel cache
│ ├── node_modules.py # Old node_modules directories
│ ├── rust_target.py # Rust target/ directories
│ ├── git_branches.py # Stale merged local branches
│ ├── downloads.py # Old files in ~/Downloads
│ ├── screenshots.py # Old screenshots
│ ├── system_tmp.py # Old temp files
│ ├── system_trash.py # macOS/Linux Trash
│ ├── dotfiles_backups.py # Dotfile backup files
│ └── xcode_derived_data.py # Xcode DerivedData (macOS)
├── tests/ # pytest test suite (80%+ coverage)
├── pyproject.toml # Project metadata, deps, entry points
└── README.md # This file
Key design principles
- Plugin architecture — Every scanner is a
Plugin. The runner loads them viaentry_points, so third-party plugins can be added without touching core code. - Context-driven — Each plugin receives a
Contextcarrying the active profile, dry-run flag, and verbosity. This keeps plugins stateless and testable. - Immutable models —
Candidate,Plan,RemovalResult, etc. are dataclasses with strong typing.AuditReportuses Pydantic for JSON serialization. - Quarantine-first — Plugins that support quarantine (
supports_quarantine() -> True) move items to a staging area instead of deleting immediately. The CLI controls whether quarantine is enabled per profile. - Audit trail —
database.pywrites every run to an SQLite DB;undoreads it back and restores quarantined items via their undo tokens.
License
MIT
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file bekas-0.3.0.tar.gz.
File metadata
- Download URL: bekas-0.3.0.tar.gz
- Upload date:
- Size: 84.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c99b5603fb8fde3d638b97042b4fdddd164588e74ffb05e4c3a2ffaeb8aa9ad8
|
|
| MD5 |
708594d6013abf7c00cb1bc9a22b1674
|
|
| BLAKE2b-256 |
765b0a4fb4a4376907d4cf05d84adb6c79790f9b1ac862066a73b6ffbafc37df
|
File details
Details for the file bekas-0.3.0-py3-none-any.whl.
File metadata
- Download URL: bekas-0.3.0-py3-none-any.whl
- Upload date:
- Size: 75.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e190349487bd05867fe78222340d170428c64364c99f0e8ec3ca990e3a3d2001
|
|
| MD5 |
802f5c3b7005420b2478078d5ac7dd7a
|
|
| BLAKE2b-256 |
1a2e369e460abec7e8ff996bea1561a0195b43da0894df987cf3dce264278fbd
|