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 fsckcan 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
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
heddle capture— take a snapshot.heddle thread— the family that walks captures (show, list, switch).heddle fsck— verify content integrity by re-hashing.
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.