Skip to main content

Hunch

A zero-config experiment journal for ML research. Every run keeps its code, config, environment, metrics and the reason you ran it, as plain files in your project. Each run also knows which run it came from, so your experiments form a history you can read back, like git log for results.

$ hunch log
*    a7f3  Nov 14  warmup + cosine decay  val_loss 2.303                  █▅▃▂▁▁▁▁  keep  "cosine helps a bit"
| x  c21e  Nov 13  warmup 2k, lr 6e-4     crashed, exit 1; val_loss 7.42  ▃▂▂▁▁▄▆█  drop
|/
*    9b40  Nov 12  warmup 1k steps        val_loss 2.323                  █▅▃▂▁▁▁▁  keep
*    3d1c  Nov 10  baseline               val_loss 2.462                  █▅▃▂▁▁▁▁  (no conclusion yet)

No server, no account, no network calls, no telemetry, no dependencies. Hunch is the first standalone piece of Sigmoid IDE, an open-source ML research IDE.

Install

pip install sigmoid-hunch

Python 3.11 or newer. The command is hunch and the import is import hunch.

Record a run

Put hunch run in front of the command you already use:

hunch run -m "warmup to fix loss spikes" -- python train.py --lr 3e-4

Leave out -m in an interactive terminal and Hunch asks why (Enter skips). It never asks when input is not a terminal, as in cluster jobs, background jobs and piped scripts. Pass -m in shell scripts that launch many runs.

Or record from inside your code. One line records every run, however it is launched:

import hunch

run = hunch.init(config={"lr": 3e-4}, why="warmup to fix loss spikes")
for step in range(steps):
    ...
    hunch.log({"train_loss": loss, "val_loss": val_loss}, step=step)

Use both: inside hunch run, hunch.init() joins the wrapper's run instead of starting a second one. The names follow W&B, so import hunch as wandb works for init, log, config, summary and finish. config can be a dict or an argparse.Namespace. Tensors are turned into numbers. In distributed training only rank 0 records: Hunch reads RANK, OMPI_COMM_WORLD_RANK and PMI_RANK, and inside hunch run also SLURM_PROCID.

Read it back

hunch ls                 recent runs, newest first
hunch log                the tree of runs
hunch show a7f3          everything about one run
hunch diff 9b40 a7f3     what changed: code, config, environment and metrics
hunch diff 9b40 a7f3 --code     the full code diff
$ hunch diff 9b40 a7f3
9b40  Nov 12 14:12  warmup 1k steps
a7f3  Nov 14 09:30  warmup + cosine decay

code     train.py  +6 -1   (--code for the full diff)
config   schedule: const -> cosine
env      no changes
metrics  val_loss 2.323 -> 2.303 (-0.02)

Runs are named by the end of their id, usually 4 characters. Runs that ended in under 30 seconds (typos, quick crashes) are hidden; --all shows them.

Close the loop

hunch note a7f3 "cosine helps a bit" --keep     a conclusion and a verdict
hunch note c21e --drop                          a dead end
hunch note a7f3 --why "warmup + cosine decay"   a better why
hunch link a7f3 --from 9b40                     fix the run it came from
hunch set main-metric val/acc                   the metric shown for each run

Notes are added, never overwritten, so a run's history stays visible in hunch show.

What a run records

  • The command, arguments and working directory
  • The git commit and branch, the uncommitted changes to tracked files, and copies of small untracked text files, so the exact code can be rebuilt
  • The config passed to hunch.init()
  • Python version and path, installed packages, torch and CUDA versions, GPU model and driver, host, and the SLURM job id
  • Metrics, final values, output (with hunch run), exit status and duration
  • The why, your conclusion and your verdict

Lineage

Each run's parent is picked for you: the run on the same git branch that ended most recently, skipping runs still in progress, runs under 30 seconds and runs you dropped. Branch per idea and you get a tree; stay on one branch and you get a straight history. Use hunch run --from <run> to choose the parent yourself, and hunch link to fix it later.

Where it lives

Everything is in .hunch/ at the root of your git repository (outside git, in the current folder), one folder per run. The folder ignores itself in git, so your repository is never touched. Runs never change after they end and have unique ids, so copying them between machines is a plain rsync of folders. The format is documented in docs/format.md, for anyone who wants to read it without Hunch.

Privacy

Nothing leaves your machine. Only these environment variables are recorded: CUDA_VISIBLE_DEVICES, CONDA_DEFAULT_ENV, VIRTUAL_ENV and SLURM_*. Credentials are removed from git remote URLs. Command arguments are recorded as typed, so do not pass secrets as arguments.

Known limits in this first version

  • hunch run pipes the command's output to save it, so programs that check for a terminal may turn off colors. It sets PYTHONUNBUFFERED=1 to keep output live.
  • hunch run passes SIGTERM on to the command. It survives SIGHUP, SIGUSR1 and SIGUSR2 without passing them on, because SLURM and terminals send those to the whole process group, so the command already gets them.
  • Without hunch run, a script that ends with sys.exit(n) is recorded as finished, and one killed outright shows as lost after 5 minutes. Use hunch run for exact exit codes.
  • No plots beyond sparklines, no sweeps, no checkpoint storage, no importers from other trackers yet.

License

Apache-2.0. See CONTRIBUTING.md to contribute.

Metadata

Release files for sigmoid-hunch 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for sigmoid-hunch 0.1.0
File Size Uploaded Provenance Actions
sigmoid_hunch-0.1.0.tar.gz 29.7 kB Without provenance Details for sigmoid_hunch-0.1.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for sigmoid-hunch 0.1.0
File Interpreter ABI Platform Actions
sigmoid_hunch-0.1.0-py3-none-any.whl Python 3 none any Details for sigmoid_hunch-0.1.0-py3-none-any.whl

Total release size: 64.0 kB

Release files / sigmoid_hunch-0.1.0.tar.gz

Download URL sigmoid_hunch-0.1.0.tar.gz
Size 29.7 kB
Tags Source
SHA-256 checksum
How to use checksums
f33bd3de1050525f6f06a15a092aef50a0ccb9135e190e8ee5abbf4c3df2ecdd
BLAKE2b-256 checksum
How to use checksums
6583b3a371e48c91adf720881cb2e260807751132f6130b53c300a4d3883c653
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.13.7 {"installer":{"name":"uv","version":"0.13.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"26.04","id":"resolute","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / sigmoid_hunch-0.1.0-py3-none-any.whl

Download URL sigmoid_hunch-0.1.0-py3-none-any.whl
Size 34.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
df8b33e7aba24d44c20b5b471f5fd78a2fd74a2dcb445cb4bbfc4dcdab23e082
BLAKE2b-256 checksum
How to use checksums
c25a1ce23a84755f3de13fa5de06d36fbdda7983099d541f833d5eaba359ba97
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.13.7 {"installer":{"name":"uv","version":"0.13.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"26.04","id":"resolute","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Security for sigmoid-hunch 0.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page