CLI tools for cleaning artifacts and builds
Project description
Artifact-Scythe
Reclaim disk space by harvesting the build artifacts you forgot about.
scythe is a Python CLI that walks your projects directory, identifies each
project's ecosystem (Node, Python, Rust, Java, Go, Ruby, .NET) from its
marker files, and locates the bulky build artifacts that ecosystem leaves
behind — node_modules, .venv, __pycache__, target/, build/, and
the rest. It reports how much space each one is wasting and, when you tell
it to, deletes them.
It is safe by default: every clean previews what is about to happen and
asks for confirmation, and a --dry-run mode lets you check the plan
before running for real.
Why
A laptop used daily for a year typically holds 30–80 GB of stale
node_modules, abandoned virtualenvs, cached compiler output, and CI
scratch directories. None of it is load-bearing — but finding and removing
it by hand across dozens of project folders is tedious and error-prone.
scythe does it in two commands.
How does this compare to npkill / kondo / cleanpy?
Existing tools cover one ecosystem each, well. scythe covers a
mixed-stack ~/projects folder in one workflow.
| Tool | Ecosystems covered | UX | Filters | Reports | Distribution |
|---|---|---|---|---|---|
npkill |
Node only (node_modules) |
Interactive TUI | Sort by size / age | None | npm |
kondo |
Rust + a handful (Node, JS, Java, Haskell, …) | Interactive prompt | Older-than | None | Cargo, Homebrew |
cleanpy |
Python only | CLI | Cache types | None | pip |
scythe |
Node, Python, Rust, Java (Maven + Gradle), Go, Ruby, .NET (Swift planned) | CLI today, TUI mode scythe ui planned |
--only, --older-than, --min-size (--ignore planned) |
JSON / CSV export, dry-run report, recoverable trash + scythe restore |
pipx, pip, Docker (multi-arch), standalones planned |
When to reach for which:
- Only have a
node_modulesproblem?npkillis purpose-built. - Mostly Rust?
kondois great. - Mixed-stack folder, want filters / reports / scripting / CI integration,
or you also need to clean Python virtualenvs and Java build dirs in the
same pass? That's where
scytheis meant to live.
Quick start
pipx install artifact-scythe # one-line global install
scythe scan ~/projects # see what's eating your disk
scythe clean ~/projects --dry-run # preview the deletions
scythe clean ~/projects # do it (with confirmation)
Install
With pipx (recommended)
pipx installs scythe into its own isolated
virtual environment and exposes the scythe command globally on your
PATH. It's the right tool for Python CLIs: no clash with your project
deps, no sudo, one command to upgrade.
pipx install artifact-scythe # install
pipx upgrade artifact-scythe # update later
pipx uninstall artifact-scythe # remove cleanly
Don't have pipx yet? python -m pip install --user pipx && python -m pipx ensurepath
(restart your shell once).
With pip
If you don't want the isolated install, plain pip works too:
pip install --user artifact-scythe # user-level install
Naming note
The PyPI distribution is artifact-scythe (the scythe slot on PyPI was
taken), but the installed command and the Python module are both scythe.
Scripts written against scythe ... keep working unchanged.
With Docker
If you'd rather not install anything locally (CI agents, throwaway VMs,
or just trying it out), the official image is published on GHCR for both
linux/amd64 and linux/arm64:
# scan the current directory
docker run --rm -v "$PWD":/work ghcr.io/elielmengue/scythe:latest scan /work
# clean with a dry-run
docker run --rm -v "$PWD":/work ghcr.io/elielmengue/scythe:latest \
clean /work --dry-run
Tags follow the PyPI release: :latest, :0.5.3, :0.5, :0. The
rolling :edge tag tracks main.
From source
git clone https://github.com/elielMengue/scythe.git
cd scythe
pip install -e ".[dev]"
Usage
scythe scan — discover projects and measure artifacts
scythe scan . # current directory
scythe scan ~/dev --depth 2 # bound recursion depth
scythe scan ~/dev --only node,python # filter by ecosystem
scythe scan ~/dev --older-than 30 # only artifacts older than 30 days
scythe scan ~/dev --min-size 500MB # only artifacts at or above 500 MB
scythe scan ~/dev --format tree # table | tree | compact | json
scythe scan ~/dev --format json -o report.json # also csv via .csv suffix
scan is read-only. It produces a report; nothing is deleted.
scythe clean — delete detected artifacts
scythe clean ~/dev --dry-run # simulate (always do this first)
scythe clean ~/dev --trash # recoverable cleanup (undo with `scythe restore`)
scythe clean ~/dev --interactive # pick projects manually
scythe clean ~/dev --only rust # only Rust target/ directories
scythe clean ~/dev --older-than 30 --dry-run # only target stale artifacts
scythe clean ~/dev --min-size 1GB --dry-run # only large artifacts worth deleting
scythe clean ~/dev --force # skip the confirmation prompt
scythe clean ~/dev -o run-report.json # export a JSON report
clean runs the same scan first, prints a summary, then either prompts
before deleting or executes immediately depending on flags.
By default deletion is permanent — files are unlinked, not moved to the
OS bin. Pass --trash to route them through scythe's recoverable trash
instead, then use scythe restore to bring them back.
scythe restore — undo a clean --trash run
scythe restore --list # show recoverable runs (id, date, items, size)
scythe restore # undo the most recent --trash run
scythe restore 20260502-153000-123456 # undo a specific run by id
Trashed runs live under the per-user data dir
(%LOCALAPPDATA%\scythe on Windows, ~/Library/Application Support/scythe
on macOS, $XDG_DATA_HOME/scythe or ~/.local/share/scythe on Linux).
A run that's already been restored, has a missing trash payload, or whose
destination has been re-created since the clean, is reported as skipped
rather than failing.
scythe info
Prints the installed version and the list of supported ecosystems and patterns.
Supported ecosystems
| Ecosystem | Marker files | Artifact patterns |
|---|---|---|
| Node.js | package.json, yarn.lock, pnpm-lock.yaml |
node_modules, dist, build, .next, .nuxt, out, .cache, .parcel-cache, .turbo, coverage |
| Python | requirements.txt, setup.py, pyproject.toml, Pipfile, poetry.lock |
.venv, venv, env, __pycache__, .pytest_cache, .mypy_cache, .ruff_cache, .tox, *.egg-info, dist, build, .eggs, htmlcov |
| Rust | Cargo.toml, Cargo.lock |
target |
| Java (Maven) | pom.xml |
target, .m2/repository |
| Java (Gradle) | build.gradle, build.gradle.kts, settings.gradle |
build, .gradle, out |
| Go | go.mod, go.sum |
bin, pkg, vendor |
| Ruby | Gemfile, Gemfile.lock, .ruby-version |
vendor/bundle, .bundle, tmp |
| .NET | *.csproj, *.fsproj, *.vbproj, *.sln |
bin, obj, packages, .vs |
The --only flag accepts both canonical names (node, python,
java_maven, java_gradle, dotnet, ...) and short aliases (py,
js, rs, golang, .net, cs).
Safety
cleandeletes viashutil.rmtree/Path.unlink— files are gone, not in the trash bin. Run--dry-runfirst when in doubt.- Source-control dirs (
.git,.svn,.hg,.bzr), editor metadata (.idea,.vscode), and OS metadata (.DS_Store,Thumbs.db) are skipped during traversal. - Symlinks are not followed unless
--follow-symlinksis passed. - Use
--depth Non very large filesystems to avoid runaway scans.
Development
Python 3.10+ is required.
git clone https://github.com/elielMengue/scythe.git
cd scythe
pip install -e ".[dev]"
pytest -v # full test suite
pytest --cov=scythe # with coverage
pytest tests/test_scanner.py # a single file
CI runs the test suite on Linux, macOS, and Windows for Python 3.10,
3.11, and 3.12. See .github/workflows/ci.yml.
Contributing
Issues and pull requests are welcome.
To add support for a new ecosystem, extend two places:
PROJECT_MARKERSinscythe/scanner/scanner.py— how to recognise the project.ARTIFACT_PATTERNSinscythe/detector/detector.py— what to clean.
Then add a fixture and an assertion in tests/test_detector.py that
exercises the new pattern. Keeping these two maps in sync is the core
invariant of the codebase.
Roadmap
Shipped
- Configuration & foundations
- Directory scanner
- Artifact detection — 8 ecosystems
- Rich-based output (table / tree / compact / JSON)
- Cleaning engine (
--dry-run,--interactive,--force, JSON report) - Filters:
--only,--older-than,--min-size - Recoverable trash +
scythe restore—scythe clean --trashmoves artifacts under a per-user data dir and writes a per-run manifest;scythe restoreundoes the most recent run (or a specific one by id). (v0.6.0) - Distribution: PyPI (
pipx), Docker (multi-arch GHCR)
Safety & UX
-
scythe ui— interactive TUI mode (Textual) — full-screen browse-and-clean experience: filterable project list, expandable artifact tree per project, live total-size readout, item-level toggles, and an undo stack that pairs naturally with trash-mode. The CLI stays for scripts and CI; the TUI is for exploration.
Filters & customization
-
--ignore PATTERN— extra ignore patterns on top of the built-in defaults (e.g.--ignore "*.archive,~/projects/keepme"). - Config file —
pyproject.toml [tool.scythe]and/or~/.scythercto persist--only/--ignore/ depth defaults per machine.
Distribution & polish
- Standalone binaries on GitHub Releases for users without Python:
- macOS — Apple Silicon (
arm64) and Intel (x86_64) - Linux —
x86_64andarm64(glibc); musl/static build for Alpine - Windows —
x86_64(.exe) - Optional: FreeBSD
x86_64
- macOS — Apple Silicon (
- Package-manager distribution — Homebrew tap, Scoop bucket, winget manifest, and an AUR package.
- Shell completions —
scythe completion {bash,zsh,fish,powershell}.
Telemetry & quality
- Lifetime stats — track total space reclaimed across runs and
surface it in
scythe info. - Comprehensive integration tests — broader scanner/cleaner coverage (large directory trees, permission edge cases, symlink loops).
See CHANGELOG.md for the release history.
License
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 artifact_scythe-0.6.0.tar.gz.
File metadata
- Download URL: artifact_scythe-0.6.0.tar.gz
- Upload date:
- Size: 36.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2df2cd04bc755015a3455c1a1e316b5f6d9cd8ae2bf2f626a697e863e4f4de19
|
|
| MD5 |
d24038fbc75b0898142948e68998889a
|
|
| BLAKE2b-256 |
389b15e93803f506f9c594329491cc804502821bfe165813b25ee33c678e206d
|
Provenance
The following attestation bundles were made for artifact_scythe-0.6.0.tar.gz:
Publisher:
release.yml on elielMengue/scythe
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
artifact_scythe-0.6.0.tar.gz -
Subject digest:
2df2cd04bc755015a3455c1a1e316b5f6d9cd8ae2bf2f626a697e863e4f4de19 - Sigstore transparency entry: 1429436253
- Sigstore integration time:
-
Permalink:
elielMengue/scythe@fa3629652aa30f35c9ad24be6e71230dcc32cbee -
Branch / Tag:
refs/tags/v0.6.0 - Owner: https://github.com/elielMengue
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@fa3629652aa30f35c9ad24be6e71230dcc32cbee -
Trigger Event:
push
-
Statement type:
File details
Details for the file artifact_scythe-0.6.0-py3-none-any.whl.
File metadata
- Download URL: artifact_scythe-0.6.0-py3-none-any.whl
- Upload date:
- Size: 32.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
148e0867b0598b2b3d89a49c7ee2802f03b75c5740fa22717e78c765c8093d88
|
|
| MD5 |
75beeed02c70b84c9905ae3923325f02
|
|
| BLAKE2b-256 |
79ad3801f9994fde24493cded0fe22c60acc7197a808f0b52b0d6d0b3e27df69
|
Provenance
The following attestation bundles were made for artifact_scythe-0.6.0-py3-none-any.whl:
Publisher:
release.yml on elielMengue/scythe
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
artifact_scythe-0.6.0-py3-none-any.whl -
Subject digest:
148e0867b0598b2b3d89a49c7ee2802f03b75c5740fa22717e78c765c8093d88 - Sigstore transparency entry: 1429436256
- Sigstore integration time:
-
Permalink:
elielMengue/scythe@fa3629652aa30f35c9ad24be6e71230dcc32cbee -
Branch / Tag:
refs/tags/v0.6.0 - Owner: https://github.com/elielMengue
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@fa3629652aa30f35c9ad24be6e71230dcc32cbee -
Trigger Event:
push
-
Statement type: