Skip to content

Session survival: decouple PTYs from the server process (hot-reload without killing terminals) + hardened auto-resume #1025

Description

@web3dev1337

Problem

Every live terminal is a node-pty child of the orchestrator server process. Any server restart — nodemon picking up a code change, updating to a new version, a crash — kills all running Claude/Codex sessions. Conversations survive on disk (transcripts), but live TUIs are lost and restoration is manual. Separately, after a full reboot the recovery flow works but is not as robust as it should be (stale/duplicated lastConversationId entries were observed in session-recovery data on 2026-07-19).

Direction A — survive server restarts (the "hot reload" ask)

Decouple PTY ownership from the app server:

  • tmux-backed sessions (recommended): spawn each session inside a per-session tmux session (tmux new-session -d -s <sessionId>); the server attaches via tmux control mode (tmux -CC) or pipe-pane for output. On server restart, sessions keep running under the tmux server; the orchestrator re-attaches instead of respawning. Bonus: native scrollback survives too.
  • Alternative: a minimal long-lived pty-broker daemon (owns node-pty processes, unix-socket IPC to the app server). Same effect, more code to maintain; tmux gives it for free.
  • Scope note: nodemon should restart only the app server, never the tmux server; sessionManager's spawn/write/resize/kill paths route through the broker/tmux layer.

Direction B — survive reboots (resume hardening)

Nothing survives power-off except transcripts, so resume is the mechanism — make it excellent:

  • One-click / auto "restore all": relaunch each recovered terminal in its cwd with claude --resume <lastConversationId> (fall back to --continue when the id is missing/stale).
  • Fix conversation-id capture: several sessions shared identical stale ids (visual-novels work2/7/8, kpop-idol-empire, roblox-game-kit) — the detector is attributing the wrong transcript in some flows.
  • Preload scrollback from /api/sessions/:id/log on restore (shipped in PR fix: recompute terminal layout on mobile breakpoint changes #997) so restored terminals don't come back blank.

Explicit non-goal

True process freezing (CRIU checkpoint/restore) — impractical under WSL2 and pointless for agents holding live API streams; those connections can never be thawed. Transcript + resume is the correct persistence model; A+B make it feel seamless.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions