[BUG] Desktop + Remote Control: forked session cannot reconnect after disconnect; `/teleport` inside a `--resume`d session writes a root entry (parentUuid: null) and severs the transcript chain
Version: Claude Code 2.1.284, Desktop app (macOS, Darwin 24.6.0), Remote Control to phone
Model in session: claude-sonnet-4-5-20250929
Summary
Two related problems observed on one session (a fork created from the web UI while the parent ran locally under Remote Control):
- Forked session is unrecoverable from the Desktop app after a disconnect. The fork got its own bridge ID. When the connection dropped overnight, the Desktop app showed the fork as "Remote Control disconnected" and never spawned a new local CLI process for it. The parent session and all other sessions reconnected fine. The fork's local transcript (
~/.claude/projects/<proj>/<fork-id>.jsonl) was complete the whole time.claude --resume <fork-id>in a terminal worked, but the app then lists it as a new session (new bridge ID) while the old entry stays dead forever.
/teleportinside a--resumed session destroys the conversation context. Afterclaude --resume <fork-id>and/remote-control(both fine), running/teleportin that session printed "Session resumed successfully" and appended asystem/local_commandrow withparentUuid: nullto the same JSONL. Because--resumereconstructs context by walkingparentUuidfrom the last row, every subsequent turn only saw the rows after that new root. The model's context dropped from ~117k tokens to ~40k (system prompt only). The terminal still rendered the whole file, so the UI looked fine while the model had amnesia.
Likely related: #95873 (Remote Control sessions have 0 teleport-events, so --teleport yields an empty session), #94836 (--teleport restores only first turn), #96628 (a parentUuid pointing at a never-written row makes --resume lose everything before it), #95925 / #97981 (dead entries in session lists).
Steps to reproduce
- Start a local session in the Desktop app with Remote Control enabled. Chat for a while.
- From claude.ai/code on the phone, fork the session. Continue chatting in the fork (it runs locally; a second JSONL appears).
- Let the connection drop (sleep / network). Reopen the Desktop app.
→ Fork entry shows "Remote Control getrennt" and never recovers. Parent recovers.
- In a terminal:
claude --resume <fork-id>→ session loads, context intact. - In that session:
/remote-control→ works, new bridge ID. - In that session:
/teleport→ "Session resumed successfully". - Send a message and ask the model what it remembers.
→ Only the messages after step 6. Everything before is invisible to the model but still visible in the terminal transcript.
Evidence (from the JSONL)
row 314 system/bridge_status parentUuid: 316eb440… "/remote-control is active"
row 315 system/local_command parentUuid: null "<command-name>/teleport</command-name>" ← new root
row 316 system/local_command parentUuid: ea98fff8… "<local-command-stdout>Session resumed successfully</local-command-stdout>"
row 320 user parentUuid: 83aeb767… (first message after teleport)
API usage on the assistant turns (from message.usage):
| turn | cache_read | cache_creation | total context |
|---|---|---|---|
| last turn before disconnect | 116,671 | 1,078 | ~117k |
| first turn after /teleport | 0 | 40,412 | ~40k |
| first turn after manual fix (below) | 28,690 | 102,371 | ~131k |
Workaround that restored the context
Exit the session, set parentUuid of the /teleport row to the uuid of the preceding row (the bridge_status row), claude --resume again. One field. Full context returned (131k tokens). The model then still claimed it saw nothing, because its own pre-fix answers ("I only see two messages") were the most recent turns in its context; asking it to quote the first message of the session made it look and confirm it had everything.
Expected
- A forked session should be resumable from the Desktop app after a disconnect, same as its parent (or at least the dead entry should be reconciled with the resumed one, since both point at the same local JSONL).
/teleportinside a live session should either refuse when the session already has local history, or link its marker row to the previous leaf instead of writing a new root. Writing aparentUuid: nullrow into an existing transcript silently orphans everything before it.- If a transcript contains orphaned rows before the current root,
--resumeshould warn.