Concepts
Fork from capture
The primitive nothing else has. At any capture, you can branch the working state into a second thread. The original keeps running. The fork is fully attributed and addressable. Both paths persist. The abandoned one stays browseable from the same repo it came from. This is the operation that replaces stash, duplicate worktrees, and restart-the-agent in one move.
The wound
Halfway through a refactor you hit a fork in the road. Two approaches are defensible; you don't know which will pay off until you try one. Today, in Git, you have bad options:
- Stash the working tree, try approach B, hope you can come back to A. Stash drops on a typo. Stash forgets which agent was driving. Stash has no notion of attribution.
- Duplicate the worktree with
git worktree add, run a second agent against it. Now you have two directories, two terminals, two sets of.envfiles, two index states. Context cost: high. - Restart the agent from scratch in a fresh session. Lose every minute of warmup, every cached embedding, every piece of working context the model built up.
All three options leak context. Most engineers stash + worktree + pray, and roughly half of the abandoned paths are lost within a week because the stash got dropped, the worktree got nuked, or the agent session timed out.
What fork does
heddle start <thread> --from <state> creates a second thread that starts from the chosen capture
(defaulting to HEAD if --from is omitted). Both
threads now exist as first-class objects. The original keeps
its name, its agent identity, its event log. The fork gets
its own name, its own agent identity, and its own event log
starting from the fork point.
Fork a thread at the audit-middleware-scopes capture
bash# the team is unsure whether to keep a JWT compat layer$ heddle start task/biscuit-authz.shim --from hd-5xtkhq8m2pfStarted task/biscuit-authz.shim from hd-5xtkhq8m2pf · attached to gpt · 5.4 parent task/biscuit-authz continues with claude · opus 4.7 The forked thread inherits the working tree at the fork capture: every file, every uncommitted change up to that point. Both agents now operate from a known shared state and diverge from there.
Both paths persist
If the fork doesn't pay off, the abandoned thread doesn't vanish. Its captures stay browseable, its event log stays intact, the abandonment itself is recorded as an event:
An abandoned fork is still browseable
bash$ heddle thread show task/biscuit-authz.shimtask/biscuit-authz.shim · gpt · 5.4 · started from hd-5xtkhq8m2pf 3 captures · 1 abort (cost outweighs migration) state: abandoned · still addressable This matters for two reasons. First, you can come back to an abandoned path months later when conditions change. The capture record is the closest thing to a working time machine for code. Second, the abandoned path's attribution survives: the agent that tried it, the captures it produced, the reason given for abandoning are all part of the audit trail.
Recovery
heddle switch <state> lands you back at any
capture in any thread, including abandoned forks. The working
tree resolves to that capture's snapshot; the current thread
pointer moves to the chosen state. From there you can fork
again, continue the abandoned thread, or just inspect the
working tree to remember what was there.
When to fork, when not
Fork when the next step is genuinely uncertain: when two approaches are both defensible and you don't know which will pay off until you've tried. Fork when a second agent will explore in parallel. Fork when you want to keep the not-yet-resolved path as evidence of what was considered.
Don't fork for every disagreement in the model. Threads can hold retries, aborts, and conflicts inline. Those don't warrant a fork. Fork is for paths that meaningfully diverge, not for "I changed my mind about a variable name."
Compared to Git
git stash heddle start (then heddle switch) Stash is volatile. A forked thread is durable. The abandoned path stays attributed and addressable forever.
git worktree add heddle start Worktrees give you a second directory; starting a thread gives you a second thread that the worktree concept doesn't even need to exist for. Both can coexist.
git branch (for experimentation) heddle start Branches forget. Forked threads remember the moment of divergence, the agent that took each path, and the reason for abandoning if one is abandoned.
The commands
heddle start: make a new thread from a capture (--from <state>).heddle thread: list, switch, and inspect threads (including forks).heddle capture: every capture is a potential fork point.
Next: annotation that survives refactor (the other primitive nothing else has), or captures and states if you want the foundational layer first.