weasel
Weasel is Explosion's standalone project workflow CLI, extracted as the replacement for spaCy Projects. A `project.yml` describes assets, variables, directories, commands, dependencies, outputs, sequential workflows, and remote caches. The CLI can clone templates with Git sparse checkout, download checked assets, skip unchanged commands through a lockfile, run scripts, push and pull output artifacts, generate project documentation, and emit a DVC pipeline.
Weasel is a focused fit for Explosion-style ML repositories that value readable local workflows and templates. Choose a fuller orchestrator or DVC-first stack when parallelism, scheduling, lineage, or long-term artifact management matters.
Use it if
- You are maintaining spaCy or other machine-learning project templates that already fit the Explosion project.yml convention
- You need a small repository-local workflow file for downloading data, preprocessing, training, packaging, and documenting outputs
- File checksums and command inputs are enough to decide whether sequential steps should rerun
- Your team wants to clone and adapt workflow templates from a Git repository
- You need a parallel DAG scheduler, distributed execution, retries, resource queues, or a service UI; Weasel workflows are documented as command names run in order
- You need full data and model version control; the docs direct advanced version tracking to DVC and provide a separate command to generate DVC configuration
- You want shell semantics inside project commands; the docs state commands are not executed in a shell, so environment values require explicit `env` mapping and interpolation
- You need storage lifecycle management; remote outputs are append-only by hashes and the remote-storage guide says removing obsolete files and managing storage size are left to you
- You are migrating spaCy Projects and require drop-in compatibility; the README lists removed keys, renamed environment overrides, dropped Git-version behavior, and new error codes
Setup reality
`pip install weasel` installs version 1.0.0 with Typer, Pydantic 2+, confection, wasabi, srsly, httpx, smart-open, cloudpathlib, and packaging. The executable can be `weasel` or `python -m weasel`, but every useful project needs a valid `project.yml`. Clone operations call Git and sparse checkout; private templates therefore depend on the machine's existing Git credentials. Asset downloads support HTTP, FTP, SSH, Git, local paths, S3, and Google Cloud Storage through smart-open and cloudpathlib, but cloud protocols can require extra provider packages and credentials that are not installed or configured automatically. Checksums are optional, so add them when reproducibility matters. Commands are passed as process arguments rather than through a shell, which means pipes, redirects, expansions, and environment access do not behave like a terminal command. Expose required environment variables through the top-level `env` mapping and interpolate them explicitly, while keeping secrets out of committed YAML and generated documentation. Running creates `project.lock`; Weasel uses command strings plus dependency and output checksums to skip unchanged work, so every meaningful file input must be declared. Undeclared dependencies can produce stale outputs. Remote push archives outputs and never overwrites old hashes, so storage grows until you clean it yourself. S3 or GCS permissions fail at runtime, and a pull only matches artifacts whose command and dependency context hashes agree. The `dvc` command also assumes DVC is installed and the repository has already run `dvc init`.
Patterns
Clone a project templateclone-template
python -m weasel clone pipelines/tagger_parser_ud ./tagger-projectThe default template source is Explosion's projects repository. Cloning calls Git and uses sparse checkout when supported.
Define a tracked command in project.ymldefine-command
commands:
- name: preprocess
help: Convert raw records
script:
- 'python scripts/preprocess.py assets/raw.json corpus/train.json'
deps:
- 'scripts/preprocess.py'
- 'assets/raw.json'
outputs:
- 'corpus/train.json'Declare every file that affects output. Undeclared inputs do not participate in lockfile checks and can leave stale results.
Download an asset with a checksumfetch-checked-asset
assets:
- dest: 'assets/training.json'
url: 'https://data.example.com/training.json'
checksum: '63373dd656daa1fd3043ce166a59474c'
# Then run:
# python -m weasel assetsThe checksum verifies content and lets an existing matching file skip download. Keep the real source checksum in project.yml.
Keep a large optional asset out of default setupmark-extra-asset
assets:
- dest: 'assets/embeddings.bin'
url: 's3://example-data/embeddings.bin'
checksum: '5113dc04e03f079525edd8df3f4f39e3'
extra: true
# Fetch extras explicitly:
# python -m weasel assets --extraCloud URLs can require provider extras and credentials. Assets marked extra are skipped by the ordinary assets command.
Define and run a sequential workflowrun-workflow
workflows:
all:
- preprocess
- train
- package
# Run the named workflow:
# python -m weasel run allCommands run in listed order. This is not a parallel DAG scheduler, even when dependencies could theoretically run concurrently.
Preview work without executing scriptspreview-command
python -m weasel run train . --dryDry run shows what Weasel would execute. It cannot predict side effects hidden inside scripts or undeclared inputs.
Force a command to run againforce-command
python -m weasel run train . --forceForce bypasses the unchanged dependency and output decision. It does not remove prior outputs or remote artifacts first.
Override a nested project variableoverride-variable
vars:
training:
dropout: 0.2
commands:
- name: train
script:
- 'python train.py --dropout ${vars.training.dropout}'
# Override from the CLI:
# python -m weasel run train . --vars.training.dropout 0.3When passing overrides without another project directory, keep `.` as the documented project-directory placeholder.
Expose an environment variable to a commandmap-environment-variable
env:
MODEL_BUCKET: MODEL_BUCKET
commands:
- name: show-bucket
script:
- 'python scripts/show_bucket.py ${env.MODEL_BUCKET}'Commands do not run through a shell. Environment variables must be mapped and interpolated; never place secret values directly in committed YAML.
Push outputs to named remote storagepush-output
remotes:
default: 's3://my-weasel-bucket'
local: '/mnt/shared/weasel-cache'
# Upload declared outputs:
# python -m weasel push defaultPush archives declared outputs under path, command-context, and content hashes. Old remote objects are not deleted automatically.
Restore outputs matching current inputspull-output
python -m weasel pull default .Pull only restores a remote output whose command string and dependency hashes match the current project context.
Generate DVC configuration from a workflowgenerate-dvc-pipeline
git init
dvc init
python -m weasel dvc . allDVC must already be installed and initialized. A DVC project accepts one generated pipeline, so choose the workflow explicitly.
Alternatives
| Package | Registry | Pick it when |
|---|---|---|
| dvc | PyPI | You need first-class data and model versioning plus reproducible pipelines and remote storage |
| kedro | PyPI | You want a structured Python data-pipeline framework with datasets, catalogues, hooks, and modular pipelines |
| doit | PyPI | You want a general Python task runner with dependency-aware incremental execution outside an ML-specific convention |