# API Reference


The Python API. `Repo` is the entry point; everything the CLI does is a thin wrapper over it. Backend-specific behavior (locators, config, state, handles) is described in the backends guide.


## Repository


The engine and the results it returns.


[Repo](Repo.md#tether.Repo)  
A tether dataset: manifests in a VCS working tree plus the systems they name.

[StatusReport](StatusReport.md#tether.StatusReport)  
Result of `Repo.status`.

[ObjectStatus](ObjectStatus.md#tether.ObjectStatus)  
One object's classification in a `StatusReport`.

[VcsDrift](VcsDrift.md#tether.VcsDrift)  
A dataset commit that is gone from VCS history without tether knowing.

[CommitResult](CommitResult.md#tether.CommitResult)  
Result of `Repo.commit`.

[GcReport](GcReport.md#tether.GcReport)  
Result of `Repo.gc`.

[AbandonReport](AbandonReport.md#tether.AbandonReport)  
What `Repo.abandon` did.

[DropReport](DropReport.md#tether.DropReport)  
What `Repo.drop` did: a bookmark, its commits, and its store leftovers,

[ForgetWorkspaceReport](ForgetWorkspaceReport.md#tether.ForgetWorkspaceReport)  
What `Repo.apply_forget_workspace` did.

[PullReport](PullReport.md#tether.PullReport)  
What `pull` did: the fetched heads of a bookmark's branches, committed.

[SetReport](SetReport.md#tether.SetReport)  
What `set` changed per object.

[PromoteReport](PromoteReport.md#tether.PromoteReport)  
Result of `Repo.apply_promote`.

[UndoReport](UndoReport.md#tether.UndoReport)  
What `Repo.undo` reversed, could not reverse, and left alone.

[RepairReport](RepairReport.md#tether.RepairReport)  
What `Repo.repair` rebuilt.

[RecoverReport](RecoverReport.md#tether.RecoverReport)  
What `Repo.recover_report` found: tether's refs in each object's store,

[RecoverStep](RecoverStep.md#tether.RecoverStep)  
One step of a `RecoverReport`: a command to run, or none, and a note.

[RecoveredObject](RecoveredObject.md#tether.RecoveredObject)  
One object's row in a `RecoverReport`.

[RecoveredRefs](RecoveredRefs.md#tether.RecoveredRefs)  
The refs a store holds under one dataset id (see `RecoverReport`).

[upgrade.UpgradeReport](upgrade.UpgradeReport.md#tether.upgrade.UpgradeReport)  
What `Repo.apply_upgrade` did.

[DiffEntry](DiffEntry.md#tether.DiffEntry)  
One object's row in `Repo.diff`.

[TETHER_REV_ENV](TETHER_REV_ENV.md#tether.TETHER_REV_ENV)  
Environment variable `Repo.open` reads for its default revision.


## Operation log


What tether did to the stores, per workspace; what undo works from.


[OpEntry](OpEntry.md#tether.OpEntry)  
One applied operation.

[oplog.OpEntry](oplog.OpEntry.md#tether.oplog.OpEntry)  
One applied operation.

[oplog.TouchedStore](oplog.TouchedStore.md#tether.oplog.TouchedStore)  
One store this clone forked or pinned in (`gc` releases its own dead

[oplog.tether_path()](oplog.tether_path.md#tether.oplog.tether_path)  

[oplog.new_op_id()](oplog.new_op_id.md#tether.oplog.new_op_id)  
A fresh 12-hex operation id.

[oplog.ops_path()](oplog.ops_path.md#tether.oplog.ops_path)  

[oplog.report_dict()](oplog.report_dict.md#tether.oplog.report_dict)  
A report dataclass as plain data for the op log (without its plan).

[oplog.read_ops()](oplog.read_ops.md#tether.oplog.read_ops)  
Every entry, oldest first, with undo marks applied (missing log: empty).

[oplog.read_jsonl()](oplog.read_jsonl.md#tether.oplog.read_jsonl)  
Every decodable record of a jsonl index, oldest first. A line an

[oplog.append_index_entry()](oplog.append_index_entry.md#tether.oplog.append_index_entry)  
Append one record and sync it (one `write` of one line, O_APPEND).

[oplog.remove_index_entry()](oplog.remove_index_entry.md#tether.oplog.remove_index_entry)  

[oplog.touched_path()](oplog.touched_path.md#tether.oplog.touched_path)  

[oplog.append_touched()](oplog.append_touched.md#tether.oplog.append_touched)  
Record a store this clone just wrote a ref into; a set, so an identity

[oplog.read_touched()](oplog.read_touched.md#tether.oplog.read_touched)  
Every touched store on record (optionally one dataset's), oldest first.

[oplog.remove_touched()](oplog.remove_touched.md#tether.oplog.remove_touched)  
Forget a store (nothing of this dataset's is left in it).

[oplog.pinned_path()](oplog.pinned_path.md#tether.oplog.pinned_path)  

[oplog.read_pinned()](oplog.read_pinned.md#tether.oplog.read_pinned)  
The pin ids on record for `dataset_id`.

[oplog.append_pinned()](oplog.append_pinned.md#tether.oplog.append_pinned)  
Record `(pin id, kind, key)` triples this clone just created; a set, so

[oplog.remove_pinned()](oplog.remove_pinned.md#tether.oplog.remove_pinned)  
Forget pins this clone released.

[oplog.mark_progress()](oplog.mark_progress.md#tether.oplog.mark_progress)  
Record that one action of a running operation completed.

[oplog.append_op()](oplog.append_op.md#tether.oplog.append_op)  

[oplog.mark_done()](oplog.mark_done.md#tether.oplog.mark_done)  
Complete a started entry: what happened, and anything `undo` learnt

[oplog.mark_undone()](oplog.mark_undone.md#tether.oplog.mark_undone)  
Record that `op_id` was reversed by the undo entry `by` (an appended mark).

[oplog.OPS_FILENAME](oplog.OPS_FILENAME.md#tether.oplog.OPS_FILENAME)  
The log file inside `.tether/` (untracked).

[oplog.TOUCHED_FILENAME](oplog.TOUCHED_FILENAME.md#tether.oplog.TOUCHED_FILENAME)  
Repository-wide index of stores this clone has *written refs into* - forked

[oplog.PINNED_FILENAME](oplog.PINNED_FILENAME.md#tether.oplog.PINNED_FILENAME)  
Repository-wide index of the pins this clone *created*, beside


## OpEntry Methods


Methods for the OpEntry class


[OpEntry.now()](OpEntry.now.md#tether.OpEntry.now)  

[OpEntry.incomplete](OpEntry.incomplete.md#tether.OpEntry.incomplete)  
The operation began but no completion mark followed.

[OpEntry.to_dict()](OpEntry.to_dict.md#tether.OpEntry.to_dict)  

[OpEntry.from_dict()](OpEntry.from_dict.md#tether.OpEntry.from_dict)  

[OpEntry.undoable](OpEntry.undoable.md#tether.OpEntry.undoable)  
Not itself an undo, not already undone, complete, not a step of

[OpEntry.summary()](OpEntry.summary.md#tether.OpEntry.summary)  
One line for `tether ops`.


## Migrations


The one composed migration behind `tether upgrade`, from any 0.1.0 alpha format to the current one. Ships with the betas and is removed at 0.1.0.


[upgrade.Repo](upgrade.Repo.md#tether.upgrade.Repo)  
A tether dataset: manifests in a VCS working tree plus the systems they name.

[upgrade.Plan](upgrade.Plan.md#tether.upgrade.Plan)  
The actions a command would perform, plus the inputs they depend on.

[upgrade.Migration](upgrade.Migration.md#tether.upgrade.Migration)  
A step of `tether upgrade`: bring a dataset to `version`.

[upgrade.UpgradeReport](upgrade.UpgradeReport.md#tether.upgrade.UpgradeReport)  
What `Repo.apply_upgrade` did.

[upgrade.TetherError](upgrade.TetherError.md#tether.upgrade.TetherError)  
Base class for all tether errors.

[upgrade.ensure_ignored()](upgrade.ensure_ignored.md#tether.upgrade.ensure_ignored)  
Make sure `.tether/.gitignore` lists every per-workspace file.

[upgrade.write_config()](upgrade.write_config.md#tether.upgrade.write_config)  

[upgrade.report_dict()](upgrade.report_dict.md#tether.upgrade.report_dict)  
A report dataclass as plain data for the op log (without its plan).

[upgrade.pending()](upgrade.pending.md#tether.upgrade.pending)  
Migrations a dataset at `version` still needs, oldest first.

[upgrade.outdated_message()](upgrade.outdated_message.md#tether.upgrade.outdated_message)  
Why a dataset at `version` cannot be opened, and what to do.

[upgrade.plan_upgrade()](upgrade.plan_upgrade.md#tether.upgrade.plan_upgrade)  
Compute what bringing this dataset to the current version would do.

[upgrade.apply_upgrade()](upgrade.apply_upgrade.md#tether.upgrade.apply_upgrade)  
Execute a plan from `plan_upgrade`.

[upgrade.upgrade()](upgrade.upgrade.md#tether.upgrade.upgrade)  
Bring the dataset to this tether's version.

[upgrade.CONFIG_VERSION](upgrade.CONFIG_VERSION.md#tether.upgrade.CONFIG_VERSION)  
The `[tether] version` this code writes and expects. `tether upgrade` brings

[upgrade.MIGRATIONS](upgrade.MIGRATIONS.md#tether.upgrade.MIGRATIONS)  
Every migration, oldest first. One step covers every alpha and beta

[upgrade.LAST_BETA_WITH_UPGRADE](upgrade.LAST_BETA_WITH_UPGRADE.md#tether.upgrade.LAST_BETA_WITH_UPGRADE)  
The newest release that can upgrade alpha datasets; bump with each beta


## Plans


What a store-writing command would do, as data. `Repo.plan_*` returns a `Plan`; `Repo.apply_*` executes one after re-checking the world matches.


[Plan](Plan.md#tether.Plan)  
The actions a command would perform, plus the inputs they depend on.

[Precondition](Precondition.md#tether.Precondition)  
One thing that must still hold when a plan is applied.

[Action](Action.md#tether.Action)  
One store-writing step in a `Plan`.


## Plan Methods


Methods for the Plan class


[Plan.writes](Plan.writes.md#tether.Plan.writes)  
Actions that touch an external system or the working tree.

[Plan.is_empty](Plan.is_empty.md#tether.Plan.is_empty)  

[Plan.require()](Plan.require.md#tether.Plan.require)  
Append a precondition (see `Precondition`).

[Plan.digest()](Plan.digest.md#tether.Plan.digest)  
SHA-256 of everything else in the saved plan, as JSON reads it back

[Plan.to_dict()](Plan.to_dict.md#tether.Plan.to_dict)  

[Plan.to_json()](Plan.to_json.md#tether.Plan.to_json)  

[Plan.from_dict()](Plan.from_dict.md#tether.Plan.from_dict)  
Load a saved plan.

[Plan.edited()](Plan.edited.md#tether.Plan.edited)  
Whether this plan was loaded and its content no longer matches the

[Plan.from_json()](Plan.from_json.md#tether.Plan.from_json)  

[Plan.missing_preconditions()](Plan.missing_preconditions.md#tether.Plan.missing_preconditions)  
What this plan lacks of `REQUIRED_PRECONDITIONS` and

[Plan.render()](Plan.render.md#tether.Plan.render)  
Human-readable lines, one per action, then notes.


## Manifest model


What is committed to the VCS (`tether.toml`, `.tether/objects/*.toml`) and kept untracked (`.tether/workspace.toml`), plus the hashing and naming helpers behind pin ids and refs.


[RepoConfig](RepoConfig.md#tether.RepoConfig)  
Committed repository configuration.

[Policy](Policy.md#tether.Policy)  
Per-object behavioral knobs.

[Pin](Pin.md#tether.Pin)  
A durable native reference created for a committed state.

[ObjectManifest](ObjectManifest.md#tether.ObjectManifest)  
The committed record for one object.

[WorkspaceState](WorkspaceState.md#tether.WorkspaceState)  
Untracked per-workspace working state.

[compute_pin_id()](compute_pin_id.md#tether.compute_pin_id)  
Content-address a pin: `<dataset8>.<hash16>`.

[ref_for_pin()](ref_for_pin.md#tether.ref_for_pin)  
Native reference name for a pin id (dot-delimited; no `/`).

[working_ref_name()](working_ref_name.md#tether.working_ref_name)  
The store branch that stands for a dataset bookmark.

[working_ref_bookmark()](working_ref_bookmark.md#tether.working_ref_bookmark)  
The bookmark slug a working ref stands for; `None` for legacy

[working_ref_workspace()](working_ref_workspace.md#tether.working_ref_workspace)  
The 8-char workspace id in a *legacy* working ref name (before

[listing_name()](listing_name.md#tether.listing_name)  
Content-addressed file name for a state's listing.

[manifest_hash()](manifest_hash.md#tether.manifest_hash)  
Hash the full committed object set (order-independent).


## Handles


Typed native handles returned by `Repo.open`.


[handles.Handle](handles.Handle.md#tether.handles.Handle)  
Base class for all native handles.

[handles.FileHandle](handles.FileHandle.md#tether.handles.FileHandle)  
A plain file or object-store artifact (always read-only).

[handles.IcechunkHandle](handles.IcechunkHandle.md#tether.handles.IcechunkHandle)  
An Icechunk repository positioned at a branch (write) or tag (read).

[handles.NeonHandle](handles.NeonHandle.md#tether.handles.NeonHandle)  
A Neon Postgres connection URL for a branch or a pinned point in time.

[handles.GitHandle](handles.GitHandle.md#tether.handles.GitHandle)  
A git/jj repository positioned at a sha (and optional worktree path).

[handles.IcebergHandle](handles.IcebergHandle.md#tether.handles.IcebergHandle)  
A pyiceberg table positioned at a branch (write) or tag (read).

[handles.DeltaHandle](handles.DeltaHandle.md#tether.handles.DeltaHandle)  
A Delta Lake table loaded at a specific version (always read-only).

[handles.LanceHandle](handles.LanceHandle.md#tether.handles.LanceHandle)  
A Lance dataset checked out at a branch (write) or tag/version (read).

[handles.DuckLakeHandle](handles.DuckLakeHandle.md#tether.handles.DuckLakeHandle)  
A DuckLake catalog attached (read-only) in a DuckDB connection.

[handles.DoltHandle](handles.DoltHandle.md#tether.handles.DoltHandle)  
A Dolt revision database: `mysql://user@host:port/db/<ref>`.

[handles.MemoryHandle](handles.MemoryHandle.md#tether.handles.MemoryHandle)  
In-memory reference handle used by the conformance suite and tests.

[handles.redact_url()](handles.redact_url.md#tether.handles.redact_url)  
`url` with any password replaced by `***`.


## Backend protocol


Implement `ObjectBackend` and register it to add a system; capability flags decide which commands apply.


[backends.ChangeEntry](backends.ChangeEntry.md#tether.backends.ChangeEntry)  
One changed thing inside an object: a file, table, array, key, …

[backends.HistoryEntry](backends.HistoryEntry.md#tether.backends.HistoryEntry)  
One native commit / snapshot / version, as listed by `ObjectBackend.history`.

[backends.ObjectDiff](backends.ObjectDiff.md#tether.backends.ObjectDiff)  
What changed inside one object between two recorded states.

[backends.VerifyReport](backends.VerifyReport.md#tether.backends.VerifyReport)  
Result of `ObjectBackend.verify` for one object.

[backends.ObjectBackend](backends.ObjectBackend.md#tether.backends.ObjectBackend)  
The operations tether needs from one class of system.

[backends.Capability](backends.Capability.md#tether.backends.Capability)  
What a backend can do.

[backends.Tier](backends.Tier.md#tether.backends.Tier)  
The cumulative capability tier of a backend (or of one object).

[backends.VerifyStatus](backends.VerifyStatus.md#tether.backends.VerifyStatus)  
Outcome of `ObjectBackend.verify`.

[backends.base_at()](backends.base_at.md#tether.backends.base_at)  
The locator's `at` field (a detached base state), if any.

[backends.build_backend()](backends.build_backend.md#tether.backends.build_backend)  

[backends.content_state()](backends.content_state.md#tether.backends.content_state)  
The part of a state that identifies the data: the state minus

[backends.effective_capabilities()](backends.effective_capabilities.md#tether.backends.effective_capabilities)  
Capabilities for a specific object.

[backends.known_kinds()](backends.known_kinds.md#tether.backends.known_kinds)  

[backends.register_backend()](backends.register_backend.md#tether.backends.register_backend)  

[backends.tier_of()](backends.tier_of.md#tether.backends.tier_of)  

[backends.MAX_DIFF_ENTRIES](backends.MAX_DIFF_ENTRIES.md#tether.backends.MAX_DIFF_ENTRIES)  

[backends.Listings](backends.Listings.md#tether.backends.Listings)  


## Conformance suite


Capability-parametrized checks for backend authors.


[testing.BackendError](testing.BackendError.md#tether.testing.BackendError)  
A backend operation failed.

[testing.RefMovedError](testing.RefMovedError.md#tether.testing.RefMovedError)  
A conditional ref move found the ref elsewhere than `expected`.

[testing.ObjectDiff](testing.ObjectDiff.md#tether.testing.ObjectDiff)  
What changed inside one object between two recorded states.

[testing.Handle](testing.Handle.md#tether.testing.Handle)  
Base class for all native handles.

[testing.Pin](testing.Pin.md#tether.testing.Pin)  
A durable native reference created for a committed state.

[testing.Policy](testing.Policy.md#tether.testing.Policy)  
Per-object behavioral knobs.

[testing.ObjectBackend](testing.ObjectBackend.md#tether.testing.ObjectBackend)  
The operations tether needs from one class of system.

[testing.BackendHarness](testing.BackendHarness.md#tether.testing.BackendHarness)  
Test fixture a backend author provides to drive the suite.

[testing.Capability](testing.Capability.md#tether.testing.Capability)  
What a backend can do.

[testing.VerifyStatus](testing.VerifyStatus.md#tether.testing.VerifyStatus)  
Outcome of `ObjectBackend.verify`.

[testing.accepts_expected()](testing.accepts_expected.md#tether.testing.accepts_expected)  
Whether a backend's `fork`, `promote` or `merge` takes the `expected`

[testing.content_state()](testing.content_state.md#tether.testing.content_state)  
The part of a state that identifies the data: the state minus

[testing.effective_capabilities()](testing.effective_capabilities.md#tether.testing.effective_capabilities)  
Capabilities for a specific object.

[testing.compute_pin_id()](testing.compute_pin_id.md#tether.testing.compute_pin_id)  
Content-address a pin: `<dataset8>.<hash16>`.

[testing.ref_for_pin()](testing.ref_for_pin.md#tether.testing.ref_for_pin)  
Native reference name for a pin id (dot-delimited; no `/`).

[testing.working_ref_name()](testing.working_ref_name.md#tether.testing.working_ref_name)  
The store branch that stands for a dataset bookmark.

[testing.run_conformance()](testing.run_conformance.md#tether.testing.run_conformance)  
Run all capability-appropriate checks; raise `AssertionError` on fail.

[testing.ABSENT](testing.ABSENT.md#tether.testing.ABSENT)  
`expected` for a conditional `ObjectBackend.fork()`: the branch must

[testing.Locator](testing.Locator.md#tether.testing.Locator)  

[testing.CONFORMANCE_DATASET](testing.CONFORMANCE_DATASET.md#tether.testing.CONFORMANCE_DATASET)  
Dataset id the conformance suite pins under (any 8 hex chars would do).

[testing.RACERS](testing.RACERS.md#tether.testing.RACERS)  
Threads the `CONDITIONAL_REF` race checks start at once.


## Registries (experimental)


Export tables (`ExportBundle`, `TABLES`), Postgres publishing, and the canonical import columns / sources for `import`. Lives under `tether.experimental.registry`; import the public names from `tether`.


[experimental.registry](experimental.registry.md#tether.experimental.registry)  
The registry layer: `export`, `publish`, and `import` of dataset metadata.

[experimental.registry.ImportReport](experimental.registry.ImportReport.md#tether.experimental.registry.ImportReport)  
Result of `apply_import()` (`Repo.apply_import`).


## Store lifecycle (experimental)


`add --create` / `Repo.create` make a store tether owns; `gc --delete-stores` removes it once nothing references it. The created- and touched-store indexes, the planning rules, and the graduation criteria live in `tether.experimental.lifecycle`.


[experimental.lifecycle](experimental.lifecycle.md#tether.experimental.lifecycle)  
Store lifecycle: create a store tether then owns, and reclaim it.


## VCS adapters


How tether reads and writes history through jj or git.


[vcs.VcsError](vcs.VcsError.md#tether.vcs.VcsError)  
A version-control operation failed.

[vcs.GitObjectReader](vcs.GitObjectReader.md#tether.vcs.GitObjectReader)  
Read many objects through one `git cat-file --batch` process.

[vcs.JjAdapter](vcs.JjAdapter.md#tether.vcs.JjAdapter)  

[vcs.GitAdapter](vcs.GitAdapter.md#tether.vcs.GitAdapter)  

[vcs.CommitInfo](vcs.CommitInfo.md#tether.vcs.CommitInfo)  
Metadata of one VCS commit, as exported to registries.

[vcs.RefInfo](vcs.RefInfo.md#tether.vcs.RefInfo)  
A named pointer into history: a jj bookmark, git branch, tag, or the head.

[vcs.VcsAdapter](vcs.VcsAdapter.md#tether.vcs.VcsAdapter)  
The VCS surface tether relies on. Paths are relative to `root`.

[vcs.git_env()](vcs.git_env.md#tether.vcs.git_env)  
The environment for a git (or jj) subprocess: this process's, without

[vcs.require_git_version()](vcs.require_git_version.md#tether.vcs.require_git_version)  
Refuse a git older than `MIN_GIT_VERSION`; an unparseable banner (a

[vcs.detect_vcs()](vcs.detect_vcs.md#tether.vcs.detect_vcs)  
Discover the enclosing VCS, preferring jj when repos are colocated.

[vcs.MIN_JJ_VERSION](vcs.MIN_JJ_VERSION.md#tether.vcs.MIN_JJ_VERSION)  
The oldest jj tether runs on; the adapter checks once and refuses an older

[vcs.MIN_GIT_VERSION](vcs.MIN_GIT_VERSION.md#tether.vcs.MIN_GIT_VERSION)  
The oldest git tether runs on: `safe.bareRepository`, which keeps the git


## Errors


[TetherError](TetherError.md#tether.TetherError)  
Base class for all tether errors.

[ConfigError](ConfigError.md#tether.ConfigError)  
The repository configuration or manifest layout is invalid.

[VcsError](VcsError.md#tether.VcsError)  
A version-control operation failed.

[BackendError](BackendError.md#tether.BackendError)  
A backend operation failed.

[CapabilityError](CapabilityError.md#tether.CapabilityError)  
An operation was requested that the backend does not support.

[ImmutableObjectModified](ImmutableObjectModified.md#tether.ImmutableObjectModified)  
An object registered as immutable changed on disk / in storage.

[UnpinnedStateError](UnpinnedStateError.md#tether.UnpinnedStateError)  
A pinnable object has working state that was never pinned.

[PinDriftError](PinDriftError.md#tether.PinDriftError)  
A pin no longer resolves to the state recorded in the manifest.

[StaleWorkingCopyError](StaleWorkingCopyError.md#tether.StaleWorkingCopyError)  
The workspace was forked from a manifest that no longer matches HEAD.

[StalePlanError](StalePlanError.md#tether.StalePlanError)  
A saved plan no longer matches the world it was computed from.

[MergeConflict](MergeConflict.md#tether.MergeConflict)  
A native merge stopped on conflicts; nothing was written.

[errors.RefMovedError](errors.RefMovedError.md#tether.errors.RefMovedError)  
A conditional ref move found the ref elsewhere than `expected`.

[MultiObjectError](MultiObjectError.md#tether.MultiObjectError)  
Aggregates per-object failures from a fan-out operation.
