Overview

tether is version control for datasets that live in several systems at once: an Icechunk repository, a directory of raw files, a Postgres database, the code that produced them. It keeps one small manifest per object in a git or jj repository. A commit of those manifests is a reproducible position for every object. Where the system allows it, tether pins that position with a native ref so it stays readable, and forks a writable branch off it when you want to change things safely.

The loop

tether init                          # inside a git or jj repository
tether add zarr/imaging --kind icechunk s3://bucket/imaging.icechunk
tether add raw/plate1   --kind file     s3://bucket/raw/plate1/
tether commit -m "Baseline"          # record every object; pin what can be pinned

tether new -b relabel                # a branch in every system, forked on first write
python relabel.py                    # write through repo.open("zarr/imaging")
tether commit -m "Relabel plate1"    # pin the branch heads; move the bookmark
tether promote                       # land it on main, in every system at once

Reading back is one flag: tether open zarr/imaging --rev <commit> (or TETHER_REV=<commit> for a whole job) hands you the system’s native handle at exactly the state that commit recorded.

Where to go

You want to Read
Run it in ten minutes, on local data Getting Started
Understand the model and how it maps onto jj Concepts
Record state and reproduce reads later Pinning
Change data on a branch, then land or discard it Branching and Writing
Keep the storage bill down; preview store writes as plans Reclaiming Storage
See the whole loop run, with real output Worked Examples
Look up a command’s behaviour, exit codes, JSON CLI Guide
Configure a dataset; keep credentials out of it Configuration
Check what a backend can and cannot do Backends, Caveats and Performance
Publish history as SQL, or import objects from a registry Registries and SQL
Add a system tether does not know yet Writing a Backend
Hand a dataset to a teammate, or run it in CI Sharing and CI
Read an error and find the way out; remove tether from a repository Troubleshooting

The generated Reference (top navigation) has every CLI flag and every Python symbol.

Vocabulary

Eight words carry the whole guide.

Term Meaning
object One thing tether tracks, under a key such as zarr/imaging: an Icechunk repository, a directory or object-store prefix, a Neon database, a git repository, …
dataset The git/jj repository holding one manifest per object. A dataset commit is a VCS commit of those manifests: a position for every object at once.
state An object’s fingerprint right now – a snapshot id, an LSN, a content digest. Comparing states is how drift is found.
pin A durable native ref (tether.<dataset>.<hash>: an Icechunk tag, a Neon branch, a git tag) that tether creates at commit time so a recorded state cannot be expired or garbage-collected.
bookmark A jj bookmark or git branch of the dataset. It stands for one branch per system.
trunk The main bookmark. It stands for each object’s upstream branch – the branch the object had before tether – so working on the trunk writes there.
working ref The store branch this checkout writes through: the upstream branch on the trunk, tether.ws.<dataset>.<bookmark> on any other bookmark.
fork A writable branch created off a pin, the first time a bookmark writes to an object.

Backends fall into four tiers: Observed (fingerprint only), Addressable (re-read later by id), Pinnable (a native ref holds it), and Forkable (a branch can be made from it). Backends lists every system’s tier.