A lightweight CLI for tracking ML experiments. Run your training scripts and ledger automatically captures output logs, code snapshots, and metrics — then lets you browse, diff, and restore them.
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/stphnma/ledger/releases/latest/download/ledger-installer.sh | shOr build from source (requires Rust):
cargo install --path .# Run an experiment
ledger run --name "lr sweep" --desc "testing learning rates" train.py --lr 0.001 --epochs 10
# List experiments
ledger ls
# Interactive TUI for browsing experiments and output logs
ledger show
# Diff a snapshot against your current working tree
ledger diff <id>
# Diff two snapshots against each other
ledger diff <id-a> <id-b>
# Restore code from a previous experiment
ledger checkout <id>
# Attach a note to an experiment
ledger log <id> "bumped learning rate, loss improved"
# Log metrics manually
ledger log-metric <id> loss=0.042 accuracy=0.98
ledger log-metric last loss=0.042 # "last" targets the most recent experimentIDs can be shortened to any unique prefix — you don't need the full UUID.
Install Ledger using the instructions above, then install the included skill for your coding agent.
codex plugin marketplace add stphnma/ledger
codex plugin add ledger-autoresearch@ledgerStart a new Codex thread in the project containing your experiment script, then ask:
Use Ledger to run an autoresearch loop for
train.py. Maximizeval_accuracy, run at most 10 experiments, and only editmodel.pyandconfig.yaml.
git clone https://github.com/stphnma/ledger.git
mkdir -p ~/.claude/skills
cp -R ledger/plugins/ledger-autoresearch/skills/ledger-autoresearch ~/.claude/skills/Start Claude Code in the project containing your experiment script, then run:
/ledger-autoresearch Run
train.py, maximizeval_accuracy, stop after 10 experiments, and only editmodel.pyandconfig.yaml.
The skill will:
- Read
autoresearch.mdnext to the script, if present, for goals and constraints - Inspect prior Ledger experiments
- Make one focused change and run the script through
ledger run - Record metrics and notes, compare the result with previous runs, and repeat
- Report the best experiment and its improvement over the baseline
Each run preserves its output, metrics, and a snapshot of the code and local
artifacts. You can audit what the agent tried with ledger show, compare
experiments with ledger diff, and restore a prior state with ledger checkout—without temporary Git commits or worktrees.
- Auto-detects your Python environment (respects
$VIRTUAL_ENV) - Runs your script, streaming output to the terminal and capturing it
- Snapshots your code into a content-addressable object store (respects
.gitignore) - Saves everything to
.ledger/
Ledger uses a content-addressable store (CAS) under .ledger/objects/. Each unique file is stored exactly once by its blake3 hash — files that haven't changed between experiments are shared, not duplicated. A typical project with 25 experiments uses the same disk space as a single snapshot.
Each experiment directory contains:
| File | Contents |
|---|---|
metadata.json |
name, description, timestamp, script, args, exit code |
output.log |
full stdout/stderr from the run |
manifest.json |
maps file paths to their content hashes |
metrics.json |
metrics logged via ledger log-metric |
ledger show opens an interactive table of all experiments with their metrics. Press enter to view the full output log for a run. Output lines are color-coded by log level (ERROR, WARN, DEBUG).
Keybindings:
| Key | Action |
|---|---|
j / k or ↓ / ↑ |
move up/down |
enter |
view output log |
q / esc |
quit / back |
g / G |
jump to top / bottom of log |
d / u |
page down / up |
ledger diff <id> shows what changed between a saved snapshot and your current working tree, colored like git. Text files are diffed inline; binary files (model weights, pickles, etc.) are noted as changed but not diffed.
diff --ledger a/train.py b/train.py
--- a/train.py
+++ b/train.py
@@ -12,7 +12,7 @@
-learning_rate = 0.001
+learning_rate = 0.01