Skip to content

[feat] Auto-resume all agent sessions after app/machine restart #3496

Open

Description

@nlatuan187

Describe the feature

When Superset is closed abruptly (machine restart, crash, power loss, app quit), all open terminal tabs running agent sessions (Claude Code, Codex, etc.) are lost. The user has to manually find each session ID and run claude --resume <id> (or prox --resume) to get back.

Since every agent CLI already persists its session to a .jsonl file on disk, and each CLI exposes a resume command, Superset has everything it needs to restore tabs automatically on the next launch.

Proposed behavior

On Superset startup, for every terminal tab that was open in the previous session:

  1. Remember which agent CLI was running (claude, codex, prox, etc.) and its session ID / cwd.
  2. Re-open the tab in the same workspace/pane layout.
  3. Auto-invoke the CLI's resume command (claude --resume <id>, codex resume, …) instead of a fresh prompt.

If an auto-resume fails (e.g. session file corrupted, Invalid signature in thinking block), fall back to showing the resume command pre-filled in the prompt so the user can tweak flags (e.g. swap claude --resume for prox --resume).

Why this matters

Losing a long agent conversation after an unexpected restart is painful — context, plan state, and in-progress tool output vanish even though the .jsonl is still on disk. For users running many agents in parallel (the core use case of Superset), this happens often enough to erode trust in the tool.

Addressing the obvious objection

"What if the user had 20 tabs open? Auto-resuming all of them is noisy."

That's fine — users can close tabs they don't need, just like any other window-restore behavior (browsers, IDEs, VS Code). Making the user manually resume every session to avoid occasional over-restoration is the wrong trade-off: the cost of losing a conversation is much higher than the cost of closing an extra tab.

Optional: a setting to toggle "auto-resume on startup" (default on) + "max tabs to auto-resume" cap for power users.

Environment

  • Superset desktop (macOS)
  • Agent CLIs affected: Claude Code (claude --resume), and any other CLI with a resume command
  • Session files: ~/.claude/projects/<project-slug>/<session-id>.jsonl

Activity

  1. github-actions commented on Apr 16, 2026

    @github-actions
    Contributor

    Triage Summary

    This is a feature request, not a bug — there is no broken behavior to reproduce with a test.

    Current Architecture

    The desktop app already has a cold restore system that partially addresses this:

    • HistoryWriter/HistoryReader (src/main/lib/terminal-history.ts) persist terminal scrollback to ~/.superset/terminal-history/{workspaceId}/{paneId}/scrollback.bin with metadata in meta.json.
    • Cold restore detection: If meta.json exists without endedAt, the app knows the previous session ended uncleanly (crash/restart).
    • Tab persistence: The Zustand tabs store uses persist middleware, so tab layout survives restarts.
    • On restart, users see their scrollback history and a "Start Shell" button that spawns a fresh shell — it does not resume the agent session.

    The Gap

    The metadata currently stored (SessionMetadata in terminal-history.ts) tracks:

    interface SessionMetadata {
      cwd: string;
      cols: number;
      rows: number;
      startedAt: string;
      endedAt?: string;
      exitCode?: number;
    }

    Similarly, SessionInfo and ColdRestoreInfo in daemon/types.ts have no command field.

    Neither stores which command was running (e.g., claude, codex) or the agent's session ID. Without this, the cold restore flow has no way to construct a resume command like claude --resume <id>.

    What Would Need to Change

    1. Extend SessionMetadata with an optional command?: string field (the original CLI command that was running)
    2. Capture the command at session creation time in the daemon manager and pass it to HistoryWriter
    3. Extend ColdRestoreInfo with the command, so the renderer knows what was running
    4. Update the cold restore UI to offer "Resume Session" (auto-invoking the agent's resume command) instead of just "Start Shell" when an agent CLI is detected
    5. Add agent-specific resume logic — map detected CLI (claude, codex, etc.) to its resume command format

    Why a Reproduction Test Isn't Feasible

    There is no bug to reproduce. The existing cold restore system works correctly for its designed purpose (showing scrollback + offering a fresh shell). The requested feature is new functionality that requires extending multiple interfaces and adding new behavior.

  2. nlatuan187 commented on Apr 16, 2026

    @nlatuan187
    Author

    Did a read of main to see what already exists so this issue has concrete pointers instead of just being a wishlist. TL;DR: Superset has ~80% of the plumbing; the missing piece is specifically auto-running a resume command in the restored PTY on cold restore.

    What already works

    • Tab / pane layout persists across restarts via zustand persist + trpcTabsStorage — apps/desktop/src/renderer/stores/tabs/store.ts:17
    • Warm reattach (daemon still alive, e.g. release-quit + relaunch): manifest adoption reconnects PTYs, buffered output replays — see HOST_SERVICE_LIFECYCLE.md and packages/host-service/src/terminal/terminal.ts:444 (WS onOpen → replayBuffer)
    • Cold restore (daemon gone, e.g. after reboot): scrollback + cwd read from disk and shown — apps/desktop/src/main/lib/terminal/daemon/daemon-manager.ts:565 attemptColdRestore()
    • initialCommand / command is already plumbed end-to-end:
      • host-service tRPC accepts it — packages/host-service/src/trpc/router/terminal/terminal.ts:15
      • host-service PTY queues it behind shellReadyPromise — packages/host-service/src/terminal/terminal.ts:373
      • desktop daemon-manager forwards command to the daemon — apps/desktop/src/main/lib/terminal/daemon/daemon-manager.ts:374,483
      • callers today: only new-workspace bootstrap (useCreateWorkspace, useCreateFromPr, bootstrap-open-worktree). Not cold restore.

    What's missing (the actual gap)

    1. Cold restore doesn't auto-resume — it stops at "show scrollback + wait". apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/hooks/useTerminalColdRestore.ts:168 handleStartShell() calls createOrAttach({ ..., skipColdRestore: true }) with preserved cwd but never passes an initialCommand → fresh bare shell, agent state lost even though the .jsonl is still on disk.
    2. No knowledge of which agent CLI was in the pane. grep -r "claude --resume\|resumeSession\|\\.jsonl" across apps/desktop/src and packages/ returns one hit total (a codex-wrapper template) — nothing tracks "this pane was running claude with session X".
    3. Design doc confirms this is the current intent, not an oversight: apps/desktop/plans/20260107-1107-terminal-persistence-dx-hardening.md explicitly says "The UI should show the saved scrollback and let the user explicitly start a new shell." — this issue proposes raising that ceiling.

    Minimum-viable integration path

    The initialCommand pipe already exists; the feature is "populate it on cold restore" + "know what to populate it with."

    1. Detect agent CLI per pane. Cheapest option: on each write to the PTY, sniff the first token of the current command line (already partially done for cwd via updateCwdFromData). Store { cli: "claude" | "codex" | ..., sessionId } alongside cwd in the history metadata (terminal-history.ts). sessionId can be scraped from the CLI's own .jsonl path (~/.claude/projects/<slug>/<uuid>.jsonl) matched by cwd + most-recent mtime as a fallback.
    2. Wire it into cold restore. In daemon-manager.ts:597 coldRestoreInfo.set(...) include the resume command. In useTerminalColdRestore.ts:168 handleStartShell() pass it as command to createOrAttach. Everything downstream already executes initialCommand after shellReadyPromise.
    3. Auto-trigger vs. manual button. Either auto-fire handleStartShell() on cold-restore mount when a resume command is known, or keep the button but prefill the label ("Resume Claude session abc1234" instead of "Start Shell"). Auto-fire is the win for the restart-recovery use case; the button is fine as a fallback if detection is uncertain.
    4. Fallback on resume failure. CLIs sometimes refuse to resume (e.g. Claude Code's Invalid signature in thinking block). In that case, print the resume command into the PTY without executing it so the user can edit flags (e.g. swap claude --resume for prox --resume) and hit enter.

    Scope boundaries

    • Doesn't require changes to host-service/terminal.ts — initialCommand is already there.
    • Doesn't require changes to packages/panes or tab persistence — those already survive.
    • Biggest new surface: CLI/session detection (new utility + history schema bump) and the cold-restore wiring.

    Happy to scope this down further or open a PR against a specific slice if maintainers point me at the preferred approach.

  3. kunaldhongade commented on Jun 12, 2026

    @kunaldhongade

    Opened draft PR #5246 to implement this for desktop Claude/Codex cold restore. The PR links the durable session-location groundwork from #5126 and adds actual auto-resume on restart.

  4. JasonLandbridge commented on Jul 7, 2026

    @JasonLandbridge

    Yes please!

  5. 2solarmax commented on Jul 11, 2026

    @2solarmax

    For anyone hitting this before the native fix (#5246) lands — a small userland stopgap: a zsh hook that resumes each restored Superset pane from host.db after a Mac restart. Opt-in, staggered, workspace- and transcript-existence-checked, and it auto-stands-down when #5246 merges (detects the native terminal_sessions column + skips if an agent is already running, so no double-resume):

    https://github.com/2solarmax/superset-session-resume

    It uses the same host.db → terminal_agent_bindings mechanism #5246 uses. To be clear it's a stopgap, not a replacement — the native PR is the real fix; this just works today while that's in review.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions