Skip to content

Cross-machine thread handoff: continue a thread from another computer with full history #48

Description

@badcuban

Motivation

Common workflow: start a thread on one machine (slow Windows work laptop), then want to continue it on another (fast MacBook at home). Today the only option is starting a fresh thread and manually re-explaining context ("check the latest commits, here's what I was doing…"), which is lossy and error-prone.

Wanted: a way to hand off a thread — full chat history, provider session continuity where possible, and the associated code state — from one Threadlines instance to another, e.g. over the same LAN.

What a thread actually is on disk

Handoff has to move three layers of state:

  1. Threadlines event log (state.sqlite: orchestration events + checkpoint diff blobs + projections). Event-sourced, so exporting a thread's event slice and replaying it through the projector on the receiving machine is cheap by design. This gives pixel-perfect chat history in the UI.
  2. Provider-native session state — what the model resumes from, not just what we render. Codex resumes via thread/resume against a rollout file under CODEX_HOME; Claude sessions are JSONL under ~/.claude/projects/<cwd-derived-slug>/. These exist only on the origin machine and embed machine-specific cwds (C:\Users\… is meaningless on macOS). The resumeCursor in ProviderSessionDirectory points at state the target machine doesn't have.
  3. Git/working-tree state — the actual code changes. Git solves transport; uncommitted work is the wrinkle.

Difficulty ranking

  • Networking/discovery/transport: easy. The server already speaks HTTP+WS with auth access management (migration 020). mDNS/Bonjour for LAN discovery; Tailscale gives off-LAN for free since it's just IP reachability.
  • Event history: easy. Export event slice + blobs, replay projector, remap project identity.
  • Git state: moderate. Auto-commit to a handoff/<thread> branch and push; bundle records branch + head SHA, receiver verifies it has the commit. Uncommitted changes travel as a patch.
  • Provider session resume: hard, provider-specific. Transplanting rollout/JSONL files across OSes means rewriting embedded cwds in undocumented formats that can break under provider updates. CodexSessionRuntime already falls back gracefully to a fresh start when resume fails, which points at the degraded mode below.

Proposed phasing

v1 — export/import handoff bundle. "Send to another machine" packages the thread's event slice + git state. Receiver imports events, remaps the project by git-remote identity rather than filesystem path, and starts a fresh provider session seeded with a synthesized context brief built from our own event log (full transcript, files touched, decisions made). No native model-memory continuity yet, but already far better than manual re-explaining. Transport can be dumb at first (file transfer / one-shot HTTP).

v2 — native session transplant. Per-provider exportSession/importSession driver capability that copies and path-rewrites the provider's native session files, with a fidelity level per provider and fallback to the v1 seeded-fresh-session path when transplant fails. The existing multi-provider driver abstraction is the right seam.

v3 — LAN server-to-server sync. mDNS advertisement, device pairing on top of existing auth, authenticated thread-export endpoint. UX: open Threadlines on the second machine → "Continue thread from WILL-WORK-LAPTOP" → click.

Non-goals / alternatives considered

  • Thin-client mode (point the second machine's browser at the first machine's server) works today with zero changes, but keeps execution on the slow machine — doesn't address the use case, though worth documenting.

Open questions

  • Project identity mapping: git remote URL as canonical key? What about repos with no remote?
  • Should handoff be one-shot (move) or sync (thread lives on both)? One-shot move is much simpler and matches the use case; concurrent two-machine editing of one thread is explicitly out of scope.
  • Windows origin specifics: path rewriting (backslashes, drive letters) in provider session files; CRLF in patches.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementRequested improvement or new capability.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions