Documentation
Resume anywhere
Canonical agent sessions across machines, and the cross-machine picker.
On this page
Two different things called "resume"
TDE has two independent ways to pick work back up, and conflating them causes a lot of confusion:
- Canonical agent sessions — the conversation with Claude Code or Codex on a task, owned by the Board and replicated across your devices.
- The cross-machine session picker — the Resume window, which lists the TDE desktop sessions running on every machine on your license and attaches to one over SSH.
The first half of this page covers conversations. The last section covers the picker.
The canonical session
When a My Loop task talks to an agent, the source of truth for that conversation is not the CLI's transcript file. It is a canonical session stored in the Board: a portable, provider-neutral timeline of user and assistant turns, linked to the task and replicated over encrypted sync.
A provider's own file — the Claude Code or Codex JSONL under ~/.claude or
~/.codex — is a native replica. Replicas are recorded, matched and leased, but
their bytes never cross machines. Sync carries the canonical session, its turns,
its task link and replica metadata; it never reads or copies a provider directory.
┌───────────────────────────────┐
machine A │ Board: canonical session │ machine B
│ turns · task link · replicas │
~/.claude ──┤ ├── ~/.claude
(replica) └──────── encrypted sync ───────┘ (replica)Only text turns are portable. Tool calls, approvals, provider caches and internal checkpoints are dropped on the way into the canonical timeline — they are specific to one CLI on one machine.
Resume is exact, or it forks
Before a run, TDE asks one question: can I continue the provider's own session, or must I start a fresh one seeded from the portable history? Continuing is allowed only on an exact match. Four gates, in order:
| Gate | What must line up |
|---|---|
| Worktree | The canonical session's worktree equals the worktree this run is using. |
| Replica | A recorded replica exists for this provider, this machine id, this exact working directory, in a resumable state. |
| Artifact | The provider's transcript file for that replica id actually exists locally, in that worktree. |
| Transcript | The normalized turns of the local file match the canonical timeline. |
Normalization is deliberately narrow: line endings become \n, control and
bidirectional-override characters are stripped, text is trimmed, and empty turns are
dropped on both sides. Roles and ordering must match exactly.
When all four hold, TDE resumes the provider's own session — claude --resume or
codex resume — and the conversation continues in place. If the local file has
extra turns beyond the canonical timeline, the scheduler still resumes and appends
those turns to the Board first. (The interactive "Agent Session" path in the desktop
is stricter: it requires an exact equality before it will take over a file.)
Handoffs
Anything else creates a handoff: a new child session that carries the portable context forward.
- It gets its own row with
origin = handoffand a pointer back to the parent. - The parent's turns are copied in; the parent itself is left untouched.
- The task's current session pointer moves to the child.
- A fresh provider artifact is materialized from the canonical turns only — the current prompt is passed once through the resume command and never duplicated into the seed file.
You get a handoff when you move to another machine, another worktree, when the local file was deleted, when the transcript genuinely diverged, or when another process holds the artifact. Nothing is ever overwritten; divergence always branches.
After the run, TDE re-reads the provider file and reconciles: an extension is appended to the Board, an identical transcript is kept, and a divergence becomes a handoff.
One writer per artifact
Two processes appending to the same JSONL file corrupt it. TDE prevents that with a durable lease keyed on provider + machine id + native session id — the artifact, not the conversation. The lease lives in the Board and, by design, never syncs: a file cannot move with a session.
- The lease deadline is five minutes, renewed every 60 seconds while a run is active.
- If renewal fails, the run is stopped. The child process is killed, the run is marked failed, and transcript reconciliation and fallback usage import are skipped entirely — because another writer may now own the file.
- A lease held by a different owner is never taken over, expired or not. Wall clock time cannot prove that an external CLI stopped writing.
Cost and failure accounting
Usage from a managed native session is attributed to the canonical session, the task, the stage and the agent — never to a bare local Claude or Codex id. The external-usage monitor skips replicas TDE already manages, so a run is not counted twice. On a failed or cancelled run TDE re-discovers the artifact and records the result as failed or cancelled rather than inventing tokens or cost.
The cross-machine session picker
The Resume window is a different mechanism with the same spirit: it indexes the TDE desktop sessions running on every machine registered to your license, and it is populated by sync, not by the Board.
Each row shows the machine, the session name or your alias for it, the git branch with ahead/behind counts, how long ago it was seen, and how many times it has been attached. A filled dot means the machine has heartbeated recently; a hollow one means offline.
| Key | Action |
|---|---|
↑ ↓ / k j | Move the selection |
Enter | Attach |
/ | Filter |
a | Set an alias for this session |
t | Set tags |
r | Refresh |
Filter terms are ANDed and case-insensitive. A bare word matches the machine, the
session name, the alias, the branch or a tag; machine:, tag: and branch:
prefixes scope a term.
Attaching does the obvious thing:
- Same machine — opens a terminal window running
tde session attach <name>. - Another machine — opens a terminal window running
ssh -t <machine> tde session attach <name>, using your own~/.ssh/configto resolve the machine name as a host alias. If it is not a known SSH host, TDE copies that exact command to the clipboard and tells you so. - Offline — refuses, and says which machine it last lived on.
TDE never injects SSH credentials of its own. The user, the key and the host resolution are entirely your SSH configuration's business.