HEDDLE

Concepts

Captures and states

The atomic units. A capture is the act of taking a snapshot; a state is what the snapshot produces. Both are content-addressed, immutable, and cheap. Most of Heddle's other concepts — threads, forks, signing, the oplog — sit on top of these two.

What a capture is

A capture takes the working tree as it currently stands, hashes its content, and writes a new state into the current thread. The work the capture does is roughly: enumerate every file in the tree, BLAKE3-hash each blob, build a tree object referencing those blobs, and append a state record to the thread that points at the tree.

Captures are deliberately cheap. Heddle expects you to capture often — every passing test, every working prototype, the moment before a refactor. There's no notion of "polishing" a capture; the thread collapses the messy middle at merge time, so you don't pay a curation cost on the way in.

A typical capture

bash$ heddle capture -m "wire datalog scope rules"Captured state hd-9a2f (b3a8…e201)

What a state is

A state is the result of a capture. It carries a content address (the hd-… ID), a pointer to the tree the capture produced, a small header (timestamp, actor, kind), and a back-pointer to the previous state on the thread.

States are immutable. Once written, they're never modified — they may be referenced by other things (threads, forks, signed merges), and they may be garbage-collected if no live reference points to them, but a state never mutates in place.

Why content addressing

Content addressing isn't a flex. It buys three things:

  • Deduplication. A refactor that moves a file across directories produces a new tree but reuses every blob. The on-disk size barely changes.
  • Integrity. Corrupting a state changes its address. heddle fsck can detect any tampering by re-hashing.
  • Replay. Two machines that walk the same sequence of captures arrive at byte-identical states. No diffs, no drift.

How captures compose into threads

A thread is an ordered sequence of states linked by their back-pointers. Each capture extends the thread by one state. Retries, aborts, and forks are also state kinds — they appear in the same sequence, carrying their own header that says "this is a retry of the previous state," or "this is an abandoned path."

The resolved view of a thread (what heddle thread show renders, what heddle review show resolves) is computed by walking the state sequence and applying its kind semantics. The underlying state record never changes; only the rendering does.

Compared to Git

GitHeddle
git commit heddle capture

A Git commit is a curated milestone. A Heddle capture is a cheap snapshot. The thread collapses the noise at merge time, so capturing is cheap.

SHA-1 commit hash BLAKE3 state ID (hd-…)

Both content-addressed, but Heddle's IDs are scoped to states (which include thread context), not just trees.

git diff heddle diff <stateA> <stateB>

Diff between any two states in the repo. Resolves through the bridge so you can also diff against a Git commit.

The commands that operate on captures and states

Next: read fork from capture for how a state can become a branching point for parallel exploration, or the oplog for how captures land in the append-only record.