Local experiment orchestration. Queue jobs, track metrics, wake up to results.
Project description
whirr
Local experiment orchestration. Queue jobs, track metrics, wake up to results.
whirr is a lightweight, self-hosted alternative to experiment tracking tools. No cloud, no accounts, no external dependencies - just SQLite and your filesystem.
Features
- Job Queue - Submit experiments, run them on workers
- Metric Tracking - Log metrics from Python, store as append-only JSONL
- Multi-GPU Support - One worker per GPU, automatic device assignment
- Process Safety - Orphan prevention with PDEATHSIG, graceful shutdown
- Concurrent Access - SQLite WAL mode for safe multi-process access
- Web Dashboard - Interactive UI for viewing runs and comparing metrics
- Reproducibility - Automatic capture of git commit and pip freeze
- Server Mode - Multi-machine orchestration with PostgreSQL backend
Installation
pip install whirr
Optional dependencies:
# For dashboard
pip install whirr[dashboard]
# For server mode (PostgreSQL, HTTP API)
pip install whirr[server]
# For all features
pip install whirr[all]
Or install from source:
git clone https://github.com/syntropy-systems-oss/whirr.git
cd whirr
pip install -e ".[all]"
Quick Start
Initialize a Project
cd your-ml-project
whirr init
This creates a .whirr/ directory with the database and configuration.
Submit Jobs
# Submit a training job
whirr submit --name baseline -- python train.py --lr 0.01
# With tags for organization
whirr submit --name sweep-lr-001 --tags sweep,lr -- python train.py --lr 0.001
Start Workers
# Start a worker (claims and runs jobs from the queue)
whirr worker
# For multi-GPU, start one worker per GPU
CUDA_VISIBLE_DEVICES=0 whirr worker --device 0 &
CUDA_VISIBLE_DEVICES=1 whirr worker --device 1 &
Monitor Progress
# View active jobs
whirr status
# View specific job details
whirr status 1
# Follow job logs
whirr logs 1 --follow
# List completed runs
whirr runs
Cancel Jobs
# Cancel a specific job
whirr cancel 1
# Cancel all queued jobs
whirr cancel --all-queued
Python Library
Track metrics directly from your training scripts:
import whirr
# Initialize a run
run = whirr.init(
name="my-experiment",
config={"lr": 0.01, "batch_size": 32},
tags=["baseline"]
)
# Log metrics during training
for epoch in range(100):
loss = train_epoch()
run.log({"loss": loss, "epoch": epoch}, step=epoch)
# Save summary metrics
run.summary({"best_loss": 0.1, "best_epoch": 42})
# Save artifacts
run.save_artifact("model.pt", "best_model.pt")
run.finish()
Or use as a context manager:
with whirr.init(name="my-run") as run:
run.log({"loss": 0.5})
# Automatically marked complete or failed
Direct Runs (No Queue)
You can use whirr for tracking without the job queue:
python train.py # Uses whirr.init() directly
whirr runs # Shows the run
Server Mode (Multi-Machine)
For distributed setups with multiple GPU machines. See the full setup guide for detailed instructions.
Quick Setup
1. Start the server (on head node):
# Create .env file with configuration
cat > .env << EOF
POSTGRES_PASSWORD=$(openssl rand -base64 32)
WHIRR_DATA_DIR=/srv/whirr
EOF
# Start PostgreSQL + whirr server
docker compose up -d
2. Install workers (on GPU nodes):
# Download the Rust worker (recommended - only ~2MB, ~10MB RAM)
curl -L https://github.com/syntropy-systems-oss/whirr/releases/latest/download/whirr-worker-linux-x86_64 \
-o /usr/local/bin/whirr-worker
chmod +x /usr/local/bin/whirr-worker
# Or use the Python worker
pip install whirr[server]
3. Start workers:
# Rust worker
whirr-worker --server http://head-node:8080 --data-dir /mnt/shared/whirr --gpu 0
# Or Python worker
whirr worker --server http://head-node:8080 --data-dir /mnt/shared/whirr --gpu 0
4. Submit jobs:
whirr submit --server http://head-node:8080 -- python train.py --lr 0.01
Project Structure
your-project/
├── .whirr/
│ ├── config.yaml # Project configuration
│ ├── whirr.db # SQLite database (WAL mode)
│ └── runs/
│ └── run-id/
│ ├── meta.json # Run metadata
│ ├── config.json # Run configuration
│ ├── metrics.jsonl # Logged metrics
│ ├── output.log # stdout/stderr
│ └── artifacts/ # Saved files
CLI Reference
| Command | Description |
|---|---|
whirr init |
Initialize whirr in current directory |
whirr submit -- CMD |
Submit a job to the queue |
whirr status [ID] |
Show job status |
whirr worker |
Start a worker process |
whirr logs ID |
View job output |
whirr cancel ID |
Cancel a job |
whirr runs |
List all runs |
whirr dashboard |
Launch web dashboard |
whirr compare ID1 ID2 |
Compare runs side-by-side |
whirr export ID |
Export run data |
whirr server |
Start multi-machine server |
whirr doctor |
Diagnose configuration issues |
Documentation
Full documentation is available in the docs/ directory:
- Getting Started - Installation and first steps
- CLI Reference - All commands and options
- Python API - Library reference and examples
- Architecture - How whirr works under the hood
Development
# Install with dev dependencies
pip install -e ".[dev]"
# Run tests
pytest
# Run specific test file
pytest tests/test_db.py -v
License
MIT License - see LICENSE for details.
Project details
Release history Release notifications | RSS feed
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 whirr-0.5.2.tar.gz.
File metadata
- Download URL: whirr-0.5.2.tar.gz
- Upload date:
- Size: 171.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
df05a45594498e7e1571bc28cc4939ca43e697f038fa1ab3d18f8fb45b5af5c2
|
|
| MD5 |
1b85fdc4b1b603492224d147d90da918
|
|
| BLAKE2b-256 |
150c0c59cdf3cede44ca808b500c296df9bb6ccf6a33ebf9bb31c38ca0c5d190
|
Provenance
The following attestation bundles were made for whirr-0.5.2.tar.gz:
Publisher:
publish.yml on syntropy-systems-oss/whirr
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
whirr-0.5.2.tar.gz -
Subject digest:
df05a45594498e7e1571bc28cc4939ca43e697f038fa1ab3d18f8fb45b5af5c2 - Sigstore transparency entry: 830095079
- Sigstore integration time:
-
Permalink:
syntropy-systems-oss/whirr@e6f01f718121937cb24b97c28d54c7455b7fb237 -
Branch / Tag:
refs/tags/v0.5.2 - Owner: https://github.com/syntropy-systems-oss
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@e6f01f718121937cb24b97c28d54c7455b7fb237 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file whirr-0.5.2-py3-none-any.whl.
File metadata
- Download URL: whirr-0.5.2-py3-none-any.whl
- Upload date:
- Size: 90.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
dcdf7a8cabe958d97cc2c5c3aba3e9831d6325146a33c6f921e37fe7ccdd50ba
|
|
| MD5 |
d5b6256fbddc7034abe4650ecc1a5601
|
|
| BLAKE2b-256 |
3a2296abab8d24fd4d27d062deb2130f4104b51ae83975eaa87c7e6d05ca4206
|
Provenance
The following attestation bundles were made for whirr-0.5.2-py3-none-any.whl:
Publisher:
publish.yml on syntropy-systems-oss/whirr
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
whirr-0.5.2-py3-none-any.whl -
Subject digest:
dcdf7a8cabe958d97cc2c5c3aba3e9831d6325146a33c6f921e37fe7ccdd50ba - Sigstore transparency entry: 830095118
- Sigstore integration time:
-
Permalink:
syntropy-systems-oss/whirr@e6f01f718121937cb24b97c28d54c7455b7fb237 -
Branch / Tag:
refs/tags/v0.5.2 - Owner: https://github.com/syntropy-systems-oss
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@e6f01f718121937cb24b97c28d54c7455b7fb237 -
Trigger Event:
workflow_dispatch
-
Statement type: