work that outlives the session
Work that outlives
the session that started it.
Run many coding-agent sessions at once and the files survive when one ends. They're still on disk. What dies is what you were about to do next, what you already ruled out and why, and what you're still waiting on. threadline keeps that on disk instead of in a context window.
❯cargo install --path . && ./hooks/install.sh
Merges 3 hooks into ~/.claude/settings.json, backs it up first. Read it here.
5 open threads
▸ orders-api-upgrade 6h verify LIVE login collisions
sideproject-balance 2d overnight run finishes ~03:00
solar-srec-check 9d SREC block availability
threadline show <id> · threadline board --all
what gets lost
Killing ten terminals should cost nothing.
Sessions attach to a thread and detach. A thread persists until you close it, so ending the terminal that happened to be open on it loses nothing.
A session finds its way back to a thread by worktree root + branch, the weakest key that actually works. A bare directory identifies nothing (every session launches from ~/Projects), and a repository alone would merge every open ticket on it into one thread. Parallel git worktrees separate for free.
Both views below are injected automatically when a session starts. You don't ask for them, and you don't have to remember to save anything.
a thread
A unit of work. Not a conversation.
Resuming an existing thread briefs you warm instead of cold, right down to the reason a fix got held.
"Get Ruby 2.2 to production without a weekend outage" is a thread.
The four terminal sessions spent on it are not.
▸ orders-api-upgrade active · 6h · work-mbp
next Verify LIVE login collisions before shipping the held login fix
⚠ block 23 live collisions seen; unclear if the fix worsens them
⧗ wait reply from the client (human, 4d)
↳ last held the login fix: staging audit was stale
git wip/shutdown-07-31 · dirty · 2 unpushed
4 other threads open · threadline board
three fields that matter
Everything else can be reconstructed from git.
These three can't, because they only ever existed in a context window.
decide
What got ruled out, and why. The most expensive thing lost when a session dies, because the next one otherwise re-explores a dead end already paid for.
threadline decide "held the login fix" "staging audit was stale"
next_action
The literal next thing to do. Not a summary of the goal, a command or a step. If a cold session couldn't act on it, rewrite it.
threadline set next_action "verify LIVE login collisions"
wait
Anything blocking on someone or something outside this machine. Paired with block for what's blocking inside it.
threadline wait human "reply from the client"
design
The file format is the product.
An agent with only Read and Write can maintain the store correctly with no binary installed.
The log is truth, the projection is a cache
Every change is one appended line. thread.json is a replay of that log and is safe to delete at any moment. Nothing ever trusts it as input.
The exit path is a stamp, not a flush
A Claude Code SessionEnd hook gets killed mid-execution after roughly 1.5 seconds, measured across 11 runs and three signals. So threadline writes continuously while you work and does one append on the way out.
anything slower would simply not happen
Separation is by root, never by filter
Work threads live in a different store than personal ones, and the sync tool is never handed the work root's path. A filter that fails open leaks; a path that was never handed over cannot.
93 tests: unit, projection properties, and the real binary. One exists only because adversarial validation found a bug no test covered: a single stray byte that could silently erase a whole thread. A gate you haven't watched fail is not a gate.
dashboard
Zero changes to tend, for free.
threadline writes each live session's next action to ~/.claude/tend-note/<session-id>, which is tend's existing note convention. If you already run tend, its cards grow a thread line with no changes to tend at all.
The note refreshes on session start and on the heartbeat, so it can lag up to a minute behind a set next_action. Set THREADLINE_NO_DASHBOARD=1 to turn it off.
install
Build it, wire the hooks, check the doctor.
Requires a Rust toolchain. install.sh is idempotent, never removes an existing hook, and prints the exact command to undo itself.
❯cargo install --path .
❯./hooks/install.sh
❯threadline doctor
- 1Clone the repo and run
cargo install --path .. - 2Run
./hooks/install.shto merge the 3 hooks into~/.claude/settings.json. - 3Run
threadline doctorto confirm the wiring, then just work. The board or a warm brief shows up on its own.
The first set next_action or decide with no thread starts one, named after what you wrote.