Skip to content

feat(desktop): auto-resume Claude and Codex cold restores - #5246

Closed
kunaldhongade wants to merge 26 commits into
ParadevAI:mainfrom
kunaldhongade:codex/desktop-agent-session-autoresume
Closed

kunaldhongade wants to merge 26 commits into
ParadevAI:mainfrom
kunaldhongade:codex/desktop-agent-session-autoresume

Conversation

@kunaldhongade

@kunaldhongade kunaldhongade commented Jun 12, 2026 •

Copy link
Copy Markdown

Summary

  • persist desktop terminal restore metadata directly on the existing per-organization host-service SQLite DB (host.db) by extending the existing terminal_sessions table, instead of keeping a separate session-locations.json store
  • record Superset preset launch commands for agent tabs so cold restore can reuse the same command/options the user started with
  • preserve and harden Claude/Codex agent identity from the local desktop hook server so background or partial updates do not clobber the real restore target
  • recover and auto-run Claude/Codex resume commands from ~/.claude/projects and ~/.codex/sessions during cold restore, including full app relaunch and machine restart flows
  • preserve restored tabs and stream activation during reconnect/cold-restore so resumed sessions stay visible while the shell is recreated
  • migrate any legacy/intermediate restore state forward into terminal_sessions, so users do not lose restore continuity after updating

Linked Issue

Closes #3496
Also addresses #5126

Why

Desktop cold restore already preserved scrollback and cwd, but it stopped short of restoring the active Claude/Codex session. After an app quit, crash, or machine restart, users had to manually rediscover session IDs, and some restore paths could lose the tab or agent identity before the resume command completed.

User Impact

  • Claude and Codex terminal panes can resume the prior session after app restart or machine restart when the transcript store still exists.
  • Superset-started agent tabs restore using the saved Superset launch command/preset options where applicable.
  • Restored tabs stay visible while the shell/session reconnects.
  • Existing non-agent terminal behavior remains unchanged.
  • CLI agents can discover pane/workspace/session metadata from the durable host DB-backed session store via env vars.
  • Users upgrading from earlier JSON/intermediate-table implementations keep their restore state through forward migrations.

Implementation Notes

  • Session restore metadata now lives in the existing terminal_sessions table in host.db: tab/workspace identity, cwd/root paths, launch command, pid, agent id, agent session id, status, exit reason, and location key.
  • Migration 0006 imports the first DB-backed shape, 0007 folds restore metadata into terminal_sessions, and 0008 removes the workspace FK that blocked desktop pane writes.
  • session-location-log now uses terminal_sessions through the host-service DB adapter and only reads legacy session-locations.json for one-time import/archive.
  • Cold restore resolves a structured Claude/Codex target from persisted identity plus local transcript metadata, validates session IDs, and avoids injecting resume commands into panes without established agent identity.
  • Preset launches are recorded before writing into the pane, so restore can rebuild from the original Superset command instead of falling back to a generic command.

Validation

  • bun run lint
  • bun run typecheck
  • bun run test
  • bun run --cwd apps/desktop test
  • bun run build
  • targeted terminal/session-location/resume tests
  • local desktop smoke test: current branch launched successfully, host-service health.check returned 200, host.db migrated through 0008, and active Claude/Codex rows persisted expected commands/session IDs in terminal_sessions

Notes

This includes the durable session-location work tracked in #5126 and extends it with actual Claude/Codex cold-resume behavior plus the follow-up restore hardening discovered during local restart/sleep testing.

GitHub Actions required checks may still require maintainer approval because this is a fork PR, but local validation above is green on the current branch work.

Summary by CodeRabbit

  • New Features

    • Added enhanced terminal session tracking and persistence, improving session restoration across app restarts.
    • Implemented agent resume support for Claude and Codex, enabling faster recovery of previous agent sessions.
    • Added graceful handling for cold-restored terminal sessions with a 10-second preservation window to prevent accidental closure.
  • Bug Fixes

    • Improved session state migration from legacy storage to database, ensuring no loss of session metadata during startup.

@coderabbitai

coderabbitai Bot commented Jun 12, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Implements end-to-end auto-resume of Claude and Codex agent sessions across app or machine restarts. Changes span: notify hook v4 with agentId propagation, a new host-db module for organization-scoped DB access, three SQLite migrations merging session-location data into terminal_sessions, a session-location-log module persisting pane identity and exit state, transcript-backed resolveAgentResumeTarget for Claude/Codex, daemon cold-restore orchestration that resolves and threads resumeCommand, renderer-side reinjection with a clean-exit grace window, a new recordLaunchCommand TRPC mutation, and a printf-based fix to askpass token quoting.

Changes

Agent Session Auto-Resume

Layer / File(s) Summary
Notify hook v4 marker and agentId propagation
apps/desktop/src/main/lib/agent-setup/notify-hook.ts, apps/desktop/src/main/lib/agent-setup/templates/notify-hook.template.sh, apps/desktop/src/main/lib/agent-setup/notify-hook.test.ts, apps/desktop/src/main/lib/agent-setup/agent-wrappers.test.ts
NOTIFY_SCRIPT_MARKER bumped to v4; both curl dispatch branches in the shell template now pass agentId=$SUPERSET_AGENT_ID; tests updated for v4 marker and new agentId assertion.
Host DB resolution, caching, and test stub
apps/desktop/src/main/lib/host-db.ts, apps/desktop/test-setup.ts
New module resolves active organization via localDb or filesystem manifest scan, probes migrations directory across three candidate paths, caches HostDb keyed by org+path; test setup stubs getActiveHostDb to null and getActiveHostDbPath to a fixed tmp path.
Terminal session DB schema migrations and snapshots
packages/host-service/drizzle/0006_add_terminal_session_locations.sql, packages/host-service/drizzle/0007_merge_terminal_session_locations_into_terminal_sessions.sql, packages/host-service/drizzle/0008_drop_terminal_sessions_workspace_fk.sql, packages/host-service/drizzle/meta/*, packages/host-service/drizzle/meta/_journal.json, packages/host-service/src/db/schema.ts, packages/host-service/src/db/schema.test.ts
Migration 0006 adds terminal_session_locations; 0007 merges it into terminal_sessions with backfill and drops the old table; 0008 recreates terminal_sessions without the workspace FK; terminalSessions Drizzle schema gains 12 new columns; schema test validates migration artifacts.
Session-location persistence APIs with legacy migration
apps/desktop/src/main/lib/terminal/session-location-log.ts, apps/desktop/src/main/lib/terminal/session-location-log.test.ts
New module exports SessionLocationEntry, SessionLocationStoreAdapter, Drizzle-backed adapter, one-time session-locations.json import+archive, and APIs: upsertSessionLocation, updateSessionLocationAgentIdentity, recordSessionLocationLaunchCommand, markSessionLocationExited, getSessionLocation, buildSessionLocationKey; full test suite covers identity/status/pid/exit transitions and all legacy-import edge cases.
Terminal environment session-location metadata
apps/desktop/src/main/lib/terminal/env.ts, apps/desktop/src/main/lib/terminal/env.test.ts
buildTerminalEnv now sets SUPERSET_TERMINAL_ID, SUPERSET_SESSION_LOCATIONS_PATH, and SUPERSET_SESSION_LOCATION_KEY; env tests assert new vars with host-db stub wired in beforeEach.
Notification hook agent identity persistence
apps/desktop/src/main/lib/notifications/server.ts
/hook/complete handler becomes async, accepts agentId, loads session-location state, conditionally persists agent identity using Claude-transcript gating and no-agentId skip logic, includes agentId in debug log payload.
Transcript-backed agent resume target resolution
apps/desktop/src/main/lib/terminal/agent-resume.ts, apps/desktop/src/main/lib/terminal/agent-resume.test.ts
New module exports resolveAgentResumeTarget for Claude and Codex: validates session IDs, checks stored transcripts, falls back to bounded recent-file scan with cwd scoring, builds agent-specific resume commands preserving original launch command env assignments; 585-line test suite covers all resolution, fallback, validation, and cwd-ancestor paths.
Daemon cold-restore and session-location lifecycle
apps/desktop/src/main/lib/terminal/daemon/daemon-manager.ts, apps/desktop/src/main/lib/terminal/daemon/types.ts, apps/desktop/src/main/lib/terminal/daemon/daemon-manager.test.ts, apps/desktop/src/main/lib/terminal/types.ts
Daemon marks session-location exited on exit/error/kill events; after successful attach it upserts session-location and resolves a resume target via agent-id inference; cold-restore path reads prior location, computes known command, resolves resume target, upserts with null pid, and threads resumeCommand into SessionResult/ColdRestoreInfo; 657-line test expansion covers all paths.
Terminal stream exit policy and cached-stream activation
apps/desktop/src/renderer/screens/main/.../Terminal/hooks/terminal-exit-policy.ts, ...terminal-stream-activation.ts, ...useTerminalStream.ts, ...useTerminalLifecycle.ts, ...useTerminalLifecycle.test.ts, ...terminal-exit-policy.test.ts
shouldAutoCloseTerminalOnCleanExit gates auto-close on exitCode, non-run-pane, and preserveUntilMs grace window (10s); shouldActivateCachedTerminalStream guards stream activation for non-cold-restore sessions; stream and lifecycle hooks consume both predicates; tests validate all gate conditions.
Renderer resume-command capture and reinjection
apps/desktop/src/renderer/.../Terminal.tsx, ...types.ts, ...useTerminalColdRestore.ts, ...useTerminalColdRestore.test.ts, ...useTerminalLifecycle.ts, ...useTerminalLifecycle.test.ts, ...state.ts, ...v1-terminal-cache.ts
Terminal threads preserveCleanExitUntilRef and setRestoredResumeCommand through hooks; cold-restore hook captures resumeCommand from reattach, applies grace window, and reinjects via writeCommandInPane after shell-start; lifecycle hook persists/restores resumeCommand and conditionally activates cached stream; renderer types add resumeCommand to CreateOrAttachResult and ColdRestoreState; v1-cache adds onResize callback and syncDimensions(); state module adds consumeColdRestoreScrollback(); 305-line cold-restore test suite covers all lifecycle paths.
Preset launch recording via TRPC
apps/desktop/src/lib/trpc/routers/terminal/terminal.ts, apps/desktop/src/renderer/stores/tabs/useTabsWithPresets.ts
createOrAttach response gains resumeCommand; new recordLaunchCommand TRPC mutation records pane/workspace/cwd/command before execution; preset launch flows call recordPresetLaunch before writing commands to terminal.
Git askpass shell-safe token quoting
packages/host-service/src/providers/git/askpass.ts, packages/host-service/src/providers/git/askpass.test.ts
Script generation switches from echo to printf '%s\n' with shellSingleQuote() helper; test executes the generated script and verifies verbatim output for shell-special-character tokens.

Sequence Diagram(s)

sequenceDiagram
  participant Terminal as Terminal (renderer)
  participant TRPC as TRPC terminal router
  participant DaemonManager
  participant AgentResume as agent-resume
  participant SessionLog as session-location-log
  participant HostDb as terminalSessions DB

  rect rgba(100, 150, 220, 0.5)
    note over Terminal,HostDb: Cold Restore Path
    Terminal->>TRPC: createOrAttach (cold restore)
    TRPC->>DaemonManager: createOrAttach
    DaemonManager->>SessionLog: getSessionLocation(paneId)
    SessionLog->>HostDb: SELECT WHERE id=paneId
    DaemonManager->>AgentResume: resolveAgentResumeTarget(agentId, cwd, sessionId)
    AgentResume-->>DaemonManager: AgentResumeTarget { resumeCommand, sessionId }
    DaemonManager->>SessionLog: upsertSessionLocation(paneId, pid=null)
    DaemonManager->>SessionLog: updateSessionLocationAgentIdentity(paneId, agentId)
    DaemonManager-->>TRPC: SessionResult { resumeCommand }
    TRPC-->>Terminal: { resumeCommand }
    Terminal->>Terminal: store resumeCommand + set grace window
  end

  rect rgba(100, 200, 150, 0.5)
    note over Terminal,HostDb: Shell Start → Resume Injection
    Terminal->>TRPC: startShell (from cold-restored CWD)
    Terminal->>Terminal: writeCommandInPane(resumeCommand)
    Terminal->>Terminal: preserveCleanExitUntilRef = now + 10s
  end

  rect rgba(220, 130, 100, 0.5)
    note over Terminal,HostDb: Session Exit
    DaemonManager->>SessionLog: markSessionLocationExited(paneId, exitReason)
    SessionLog->>HostDb: UPDATE SET status=exited, ended_at, exit_reason
  end
Loading

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120 minutes

Possibly related PRs

  • superset-sh/superset#4703: Modifies the same notify hook flow (notify-hook.ts, notify-hook.template.sh, notifications/server.ts) to carry terminal identity parameters through /hook/complete, directly preceding this PR's agentId extension.
  • superset-sh/superset#4535: Updates the renderer v1 terminal cache's CachedTerminal interface in v1-terminal-cache.ts with field additions/removals, overlapping with this PR's onResize callback and syncDimensions() additions.

Poem

🐇 A bunny once lost all her sessions one night,
The machine crashed hard and shut off every light.
But now transcripts whisper what agents were there—
Claude resumes smoothly, Codex beyond compare!
With grace windows set and a hook bumped to v4,
No session shall vanish in darkness no more! 🌟

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

@ghost

ghost commented Jun 12, 2026 •

Copy link
Copy Markdown

@kunaldhongade kunaldhongade changed the title [codex] feat(desktop): auto-resume Claude and Codex cold restores feat(desktop): auto-resume Claude and Codex cold restores Jun 12, 2026
@kunaldhongade
kunaldhongade force-pushed the codex/desktop-agent-session-autoresume branch from ef47abf to e319c6a Compare June 12, 2026 02:43
@kunaldhongade

Copy link
Copy Markdown
Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 12, 2026 •

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@kunaldhongade

Copy link
Copy Markdown
Author

GitHub Actions CI is currently blocked at action_required because this is a fork PR and the workflow run needs upstream maintainer approval before jobs can start. The blocked run is CI run 27391106067 on commit e319c6abe7cda7960f43b34cefdef85ae72a59f9.

Local validation completed on this branch:

  • bunx sherif
  • bun run lint
  • bun run typecheck
  • bun run test
  • bun run build
  • local CLI dist build + smoke test for darwin-arm64

Also triggered a manual @coderabbitai review run since the PR is still draft.

@coderabbitai

coderabbitai Bot commented Jun 12, 2026 •

Copy link
Copy Markdown
Contributor

@kunaldhongade: Thanks for the context. The fork PR CI approval requirement is a standard GitHub security gate for first-time contributors — a repository maintainer will need to click "Approve and run" on the blocked workflow to allow CI to execute on the fork's commits.

In the meantime, your local validation coverage looks solid:

Check Status
bunx sherif ✅
bun run lint ✅
bun run typecheck ✅
bun run test ✅
bun run build ✅
CLI dist build + smoke test (darwin-arm64) ✅

A few things that may help move this forward:

  1. Ping a maintainer on the PR to approve the CI run — they can do so directly from the Actions tab on the blocked run (27391106067).
  2. Promote from draft when ready, as that typically prompts maintainer attention and may trigger auto-review workflows.
  3. The incremental CodeRabbit review that was triggered earlier should be processing the diff regardless of CI status.
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@kunaldhongade
kunaldhongade marked this pull request as ready for review June 12, 2026 02:59

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/hooks/useTerminalLifecycle.ts (1)

854-863: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Add setRestoredResumeCommand to the effect dependency array for consistency.

The dependency array includes setRestoredCwd (line 862) but not setRestoredResumeCommand. While React useState setters are typically stable, the inconsistency suggests either both should be included or both omitted (with an ESLint disable comment if intentional).

🔧 Suggested fix
 }, [
   paneId,
   workspaceId,
   maybeApplyInitialState,
   flushPendingEvents,
   setConnectionError,
   resetModes,
   setIsRestoredMode,
   setRestoredCwd,
+  setRestoredResumeCommand,
 ]);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/hooks/useTerminalLifecycle.ts`
around lines 854 - 863, The effect dependency array in useTerminalLifecycle (the
useEffect that currently lists paneId, workspaceId, maybeApplyInitialState,
flushPendingEvents, setConnectionError, resetModes, setIsRestoredMode,
setRestoredCwd) is inconsistent because it omits setRestoredResumeCommand;
update that dependency array to include setRestoredResumeCommand so both
restoration state setters are present (or alternatively remove both setters and
add an ESLint disable comment if that was the intent) — locate the useEffect in
useTerminalLifecycle.ts and add setRestoredResumeCommand to the dependencies to
maintain consistency.
🧹 Nitpick comments (1)
apps/desktop/src/main/lib/notifications/server.ts (1)

112-120: 💤 Low value

Consider normalizing empty query parameter strings to undefined.

When SUPERSET_AGENT_ID is unset in the shell environment, the v1 hook sends agentId= (empty string). The server receives this as "" rather than undefined. While updateSessionLocationAgentIdentity likely handles empty strings gracefully, explicitly normalizing empty strings to undefined would make the intent clearer and ensure consistent handling across the codebase.

♻️ Optional normalization
 const locationPaneId =
   (terminalId as string | undefined) || resolvedPaneId || undefined;
 if (locationPaneId) {
+  const normalizedAgentId = agentId && agentId !== "" ? (agentId as string) : undefined;
+  const normalizedSessionId = sessionId && sessionId !== "" ? (sessionId as string) : undefined;
   updateSessionLocationAgentIdentity({
     paneId: locationPaneId,
-    agentId: agentId as string | undefined,
-    agentSessionId: sessionId as string | undefined,
+    agentId: normalizedAgentId,
+    agentSessionId: normalizedSessionId,
   });
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/desktop/src/main/lib/notifications/server.ts` around lines 112 - 120,
Normalize empty-string query params to undefined before calling
updateSessionLocationAgentIdentity: detect if agentId or sessionId are "" and
convert them to undefined (e.g., const normalizedAgentId = agentId === "" ?
undefined : agentId), then pass normalizedAgentId and normalizedSessionId into
updateSessionLocationAgentIdentity alongside the already-resolved locationPaneId
(derived from terminalId/resolvedPaneId). This ensures terminalId,
resolvedPaneId, agentId, and sessionId are handled consistently and empty query
strings don't get propagated.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/hooks/useTerminalLifecycle.ts`:
- Around line 615-617: The tRPC handler for terminal.createOrAttach is not
returning the SessionResult.resumeCommand, so result.resumeCommand is undefined;
update the terminal.createOrAttach router response to include resumeCommand from
the DaemonTerminalManager's SessionResult (the same value populated by
DaemonTerminalManager) so that cold-restore code (useTerminalLifecycle.ts using
storedColdRestore.resumeCommand) receives it; locate the createOrAttach handler
in the terminal router (terminal.createOrAttach) and add resumeCommand to the
returned object alongside the existing session/other fields.

---

Outside diff comments:
In
`@apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/hooks/useTerminalLifecycle.ts`:
- Around line 854-863: The effect dependency array in useTerminalLifecycle (the
useEffect that currently lists paneId, workspaceId, maybeApplyInitialState,
flushPendingEvents, setConnectionError, resetModes, setIsRestoredMode,
setRestoredCwd) is inconsistent because it omits setRestoredResumeCommand;
update that dependency array to include setRestoredResumeCommand so both
restoration state setters are present (or alternatively remove both setters and
add an ESLint disable comment if that was the intent) — locate the useEffect in
useTerminalLifecycle.ts and add setRestoredResumeCommand to the dependencies to
maintain consistency.

---

Nitpick comments:
In `@apps/desktop/src/main/lib/notifications/server.ts`:
- Around line 112-120: Normalize empty-string query params to undefined before
calling updateSessionLocationAgentIdentity: detect if agentId or sessionId are
"" and convert them to undefined (e.g., const normalizedAgentId = agentId === ""
? undefined : agentId), then pass normalizedAgentId and normalizedSessionId into
updateSessionLocationAgentIdentity alongside the already-resolved locationPaneId
(derived from terminalId/resolvedPaneId). This ensures terminalId,
resolvedPaneId, agentId, and sessionId are handled consistently and empty query
strings don't get propagated.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 6e4ce44f-11bd-47a3-87aa-983bceeab729

📥 Commits

Reviewing files that changed from the base of the PR and between 74d31a3 and e319c6a.

📒 Files selected for processing (18)
  • apps/desktop/src/main/lib/agent-setup/agent-wrappers.test.ts
  • apps/desktop/src/main/lib/agent-setup/notify-hook.test.ts
  • apps/desktop/src/main/lib/agent-setup/notify-hook.ts
  • apps/desktop/src/main/lib/agent-setup/templates/notify-hook.template.sh
  • apps/desktop/src/main/lib/notifications/server.ts
  • apps/desktop/src/main/lib/terminal/agent-resume.test.ts
  • apps/desktop/src/main/lib/terminal/agent-resume.ts
  • apps/desktop/src/main/lib/terminal/daemon/daemon-manager.test.ts
  • apps/desktop/src/main/lib/terminal/daemon/daemon-manager.ts
  • apps/desktop/src/main/lib/terminal/daemon/types.ts
  • apps/desktop/src/main/lib/terminal/env.test.ts
  • apps/desktop/src/main/lib/terminal/env.ts
  • apps/desktop/src/main/lib/terminal/session-location-log.ts
  • apps/desktop/src/main/lib/terminal/types.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/Terminal.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/hooks/useTerminalColdRestore.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/hooks/useTerminalLifecycle.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/types.ts

@greptile-apps

greptile-apps Bot commented Jun 12, 2026 •

Copy link
Copy Markdown
Contributor

Greptile Summary

This follow-up commit hardens Claude/Codex cold-restore resumption: scrollback is now consumed once per pane (deduplicated across StrictMode remounts), brand-new agent panes no longer scan transcripts before the hook reports the real session ID, stream activation is deferred until a real daemon-backed session exists, and a 10-second grace window prevents auto-close during resume command injection.

  • Session restore metadata (tab/workspace identity, cwd, launch command, agent ID, agent session ID, exit reason) is migrated from session-locations.json into terminal_sessions in host.db via migrations 0006–0008; the workspace FK blocking desktop pane writes is removed.
  • resolveAgentResumeTarget now validates transcript existence for both Claude and Codex before issuing a resume command, with a SESSION_ID_PATTERN allowlist enforced before any shell-command construction.
  • The hook server gains agentId-aware identity persistence: Claude session ID overwrites are gated on transcript existence (via an in-memory cache + filesystem check); preset launch commands are recorded to the DB before pane injection so cold restore can rebuild the original Superset command.

Confidence Score: 5/5

This PR is safe to merge. The core cold-restore and resume paths are well-guarded, transcript validation is enforced before any shell-command construction, and the DB migration strategy is correct.

The follow-up commit addresses the most significant concerns from prior review rounds: transcript existence is now validated for both Claude and Codex in resolveAgentResumeTarget, scrollback deduplication across StrictMode remounts is handled atomically, live stream activation is correctly deferred to avoid showing a blank terminal during the cold-restore UI phase, and the backfill scan in the live-attach path is guarded behind an established agent identity. The sole remaining observation is the module-level knownTopLevelTranscripts Set in server.ts, which has no eviction and could retain entries for deleted transcripts across a long session, but the consequence is limited to a slower fallback CWD scan rather than incorrect behavior.

apps/desktop/src/main/lib/notifications/server.ts — the knownTopLevelTranscripts cache has no size bound or eviction strategy.

Important Files Changed

Filename Overview
apps/desktop/src/main/lib/terminal/agent-resume.ts New file: resolves agent resume targets by validating transcript existence for both Claude and Codex, uses SESSION_ID_PATTERN allowlist before building any shell commands, and performs a bounded CWD-scored transcript scan as fallback.
apps/desktop/src/main/lib/notifications/server.ts Adds agentId/sessionId persistence to the hook handler; correctly guards Claude identity overwrites with transcript verification but uses a module-level unbounded Set cache for known transcript IDs that never evicts stale entries.
apps/desktop/src/main/lib/terminal/session-location-log.ts New file: replaces the JSON-file session-location store with a DB-backed adapter over terminal_sessions; handles legacy import with a one-shot flag that is correctly set before re-throwing parse errors to prevent repeated retries.
apps/desktop/src/main/lib/terminal/daemon/daemon-manager.ts Adds cold-restore resume command resolution and session-location upserts; guards transcript backfill in the live-attach path behind existingLocation?.agentId but cold-restore path still infers agent ID from tab title as fallback when no stored identity exists.
apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/hooks/useTerminalColdRestore.ts Adds resumeCommand state and writes it via writeCommandInPane after Start Shell; preserves cold-restore state on writeCommandInPane failure (for retry) but correctly clears it on success; sets RESTORED_SESSION_CLEAN_EXIT_GRACE_MS protection.
apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/hooks/useTerminalLifecycle.ts Defers live stream activation until a real daemon session exists; uses consumeColdRestoreScrollback to deduplicate scrollback writes across StrictMode remounts; correctly gates stream activation on shouldActivateCachedTerminalStream.
apps/desktop/src/main/lib/host-db.ts New file: singleton host DB accessor with correct cache-invalidation on org switch; falls back to filesystem scanning for org ID when local-db settings are unavailable; migrations directory lookup tries packaged path first then monorepo.
packages/host-service/drizzle/0007_merge_terminal_session_locations_into_terminal_sessions.sql Migrates terminal_session_locations data into terminal_sessions via COALESCE-based UPDATE; correctly handles NULL originWorkspaceId, status mapping, and all restore-metadata columns without data loss.
packages/host-service/drizzle/0008_drop_terminal_sessions_workspace_fk.sql Drops workspace FK from terminal_sessions via table recreation; uses the correct SQLite pattern of rename + recreate rather than ALTER TABLE DROP CONSTRAINT.
apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/state.ts Adds consumeColdRestoreScrollback that marks scrollback as applied on first read, preventing duplicate writes across StrictMode remounts; atomic update pattern is correct.
apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/hooks/terminal-exit-policy.ts Adds shouldAutoCloseTerminalOnCleanExit with a 10-second grace window to prevent restored sessions from being auto-closed during the resume command injection window.

Sequence Diagram

sequenceDiagram
    participant UI as Terminal (Renderer)
    participant DM as DaemonManager (Main)
    participant SL as SessionLocationLog
    participant AR as AgentResume
    participant DB as host.db

    Note over UI,DB: Cold Restore Path (app restart / machine restart)
    UI->>DM: createOrAttach(paneId)
    DM->>SL: getSessionLocation(paneId)
    SL->>DB: "SELECT terminal_sessions WHERE id=paneId"
    DB-->>SL: agentId, agentSessionId, command, cwd
    SL-->>DM: sessionLocation
    DM->>AR: resolveAgentResumeTarget(agentId, sessionId, cwd)
    AR->>AR: hasClaudeTopLevelTranscript / hasCodexTranscript
    AR-->>DM: resumeTarget with resumeCommand
    DM->>SL: upsertSessionLocation + updateAgentIdentity
    SL->>DB: UPDATE terminal_sessions
    DM-->>UI: "isColdRestore=true, scrollback, resumeCommand"
    UI->>UI: consumeColdRestoreScrollback (mark applied)
    UI->>UI: Show scrollback + Start Shell button
    Note over UI,DB: User clicks Start Shell
    UI->>DM: "createOrAttach(paneId, cwd=restoredCwd)"
    DM-->>UI: "new session (isColdRestore=false)"
    UI->>UI: ensureCachedStreamActive
    UI->>DM: terminal.write(resumeCommand)
    UI->>UI: clearRestoreResumeState
Loading

Reviews (14): Last reviewed commit: "fix(desktop): harden agent session autor..." | Re-trigger Greptile

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

8 issues found across 18 files

Architecture diagram
sequenceDiagram
    participant UI as Terminal UI (React)
    participant LC as useTerminalColdRestore
    participant LL as useTerminalLifecycle
    participant DTM as DaemonTerminalManager
    participant SL as SessionLocationLog
    participant AR as AgentResumeResolver
    participant TS as Transcript Store (~/.claude/projects or ~/.codex/sessions)
    participant ENV as Terminal Env Builder
    
    Note over UI,ENV: Cold Restore Flow (app restart / crash recovery)
    
    LL->>DTM: createOrAttach(paneId, tabId, workspaceId)
    DTM->>SL: getSessionLocation(paneId)
    SL-->>DTM: SessionLocationEntry (with agentId, agentSessionId, workspacePath, rootPath)
    DTM->>AR: resolveAgentResumeTarget(agentId, sessionId, cwd, workspacePath, rootPath)
    
    alt Known sessionId from session location log
        AR-->>AR: Build resume command from known identity
        AR-->>DTM: AgentResumeTarget (sourcePath: "session-location-log")
    else Unknown identity - scan transcript stores
        AR->>TS: Read ~/.claude/projects/*.jsonl (max 200 recent)
        AR->>TS: Read ~/.codex/sessions/rollout-*.jsonl
        TS-->>AR: Transcript snippets (with sessionId, cwd)
        AR-->>AR: Score candidates by cwd match, pick most recent
        AR-->>DTM: AgentResumeTarget (best match)
    end
    
    alt Resume target found
        DTM->>SL: updateSessionLocationAgentIdentity(paneId, agentId, agentSessionId)
        DTM-->>LL: SessionResult (isColdRestore=true, resumeCommand="claude --resume <id>")
    else No resume target
        DTM-->>LL: SessionResult (isColdRestore=true, resumeCommand=undefined)
    end
    
    DTM->>SL: upsertSessionLocation(paneId, tabId, workspaceId, cwd, pid)
    LL->>LC: Pending initial state with resumeCommand
    
    Note over LC,UI: Shell Start and Auto-Resume
    
    LC->>LC: handleStartShell()
    LC->>UI: Start shell session
    UI-->>LC: Shell ready
    
    opt resumeCommand is set
        LC->>LC: writeCommandInPane(paneId, resumeCommand)
        LC->>UI: Write resume command to terminal input
        UI-->>LC: Command executed in shell
        alt Success
            Note over UI: Agent session resumes automatically
        else Write failure
            UI-->>LC: Error
            LC->>UI: setConnectionError("Failed to resume")
        end
    end
    
    Note over ENV: Terminal Environment Variables
    
    ENV->>ENV: buildTerminalEnv(paneId, tabId, workspaceId)
    ENV->>ENV: Set SUPERSET_TERMINAL_ID (=paneId)
    ENV->>SL: SESSION_LOCATION_LOG_PATH
    ENV->>SL: buildSessionLocationKey(workspaceId, tabId, paneId)
    ENV-->>Terminal: SUPERSET_SESSION_LOCATIONS_PATH, SUPERSET_SESSION_LOCATION_KEY
    
    Note over UI,SL: Agent Identity Persistence (via hook server)
    
    participant HS as Hook Server (/hook/complete)
    participant AgentScript as Agent Notification Script (v4)
    
    AgentScript->>HS: POST agentId=$SUPERSET_AGENT_ID, sessionId, terminalId
    HS->>SL: updateSessionLocationAgentIdentity(paneId, agentId, agentSessionId)
    
    Note over SL: Session lifecycle tracking
    
    DTM-->>DTM: Terminal pane exits
    DTM->>SL: markSessionLocationExited(paneId, exitReason)
    SL->>SL: Set status: "exited", clear pid, record exit timestamp
    
    Note over UI,SL: Renderer-side cold restore state
    
    LL->>LL: Check coldRestoreState(paneId)
    alt State exists (from previous lifecycle)
        LL->>LC: setRestoredResumeCommand(state.resumeCommand)
        LL->>UI: Write scrollback
    end
Loading

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

@kunaldhongade

Copy link
Copy Markdown
Author

Pushed follow-up commit eaa42d730a880b3397b7c6fbdec9ec54cc95b6c8 to address the valid review findings on the previous head:

  • forward resumeCommand through terminal.createOrAttach
  • normalize empty hook query params before persisting agent identity
  • validate transcript/session-log session ids before building any resume command
  • stop transcript-store guessing for panes that never established an agent identity
  • preserve root-directory path matching and clear stale pane agent identity on reuse
  • add focused resolver coverage for invalid ids, known-agent fallback, unknown-agent guard, and root-path matching

Local validation on this head:

  • bunx sherif
  • bun run lint
  • bun run typecheck
  • bun run test
  • bun run build

GitHub Actions still needs upstream maintainer approval to run on this fork PR.

@kunaldhongade

Copy link
Copy Markdown
Author

@nlatuan187 @aronchick local follow-up fixes are pushed on eaa42d730a880b3397b7c6fbdec9ec54cc95b6c8, full local validation is green, and the remaining GitHub Actions runs are blocked on upstream workflow approval for this fork PR. When you have a moment, could you review the updated head and approve the workflow run so the required CI checks can start?

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
apps/desktop/src/main/lib/terminal/agent-resume.ts (1)

367-386: 💤 Low value

Consider simplifying the single-element array pattern.

Since normalizedAgentId is a single value (not an array of agents to scan), wrapping it in Promise.all([...].map(...)) followed by filter/sort is unnecessarily complex. A direct call would be clearer:

-	const candidates = await Promise.all(
-		[normalizedAgentId].map((agentId) =>
-			resolveCandidateFromTranscripts({
-				agentId,
-				searchPaths,
-			}),
-		),
-	);
-
-	return (
-		candidates
-			.filter(
-				(candidate): candidate is TranscriptCandidate => candidate !== null,
-			)
-			.sort((a, b) =>
-				b.matchScore !== a.matchScore
-					? b.matchScore - a.matchScore
-					: b.mtimeMs - a.mtimeMs,
-			)[0] ?? null
-	);
+	return resolveCandidateFromTranscripts({
+		agentId: normalizedAgentId,
+		searchPaths,
+	});
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/desktop/src/main/lib/terminal/agent-resume.ts` around lines 367 - 386,
The code currently wraps normalizedAgentId in an array and uses
Promise.all(...).map(...) then filter/sort to pick the best TranscriptCandidate;
simplify by calling resolveCandidateFromTranscripts directly for the single
normalizedAgentId (await resolveCandidateFromTranscripts({ agentId:
normalizedAgentId, searchPaths })), assign its result to a variable (e.g.,
candidate) and return that candidate or null, removing the unnecessary
Promise.all, array mapping, filter and sort logic; keep references to
resolveCandidateFromTranscripts, normalizedAgentId, candidates (or new candidate
variable) and the final return value so the change is easy to locate.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@apps/desktop/src/main/lib/terminal/agent-resume.ts`:
- Around line 367-386: The code currently wraps normalizedAgentId in an array
and uses Promise.all(...).map(...) then filter/sort to pick the best
TranscriptCandidate; simplify by calling resolveCandidateFromTranscripts
directly for the single normalizedAgentId (await
resolveCandidateFromTranscripts({ agentId: normalizedAgentId, searchPaths })),
assign its result to a variable (e.g., candidate) and return that candidate or
null, removing the unnecessary Promise.all, array mapping, filter and sort
logic; keep references to resolveCandidateFromTranscripts, normalizedAgentId,
candidates (or new candidate variable) and the final return value so the change
is easy to locate.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 7310b2fa-e33a-4f60-a276-bea2214da7e4

📥 Commits

Reviewing files that changed from the base of the PR and between e319c6a and eaa42d7.

📒 Files selected for processing (6)
  • apps/desktop/src/lib/trpc/routers/terminal/terminal.ts
  • apps/desktop/src/main/lib/notifications/server.ts
  • apps/desktop/src/main/lib/terminal/agent-resume.test.ts
  • apps/desktop/src/main/lib/terminal/agent-resume.ts
  • apps/desktop/src/main/lib/terminal/session-location-log.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/hooks/useTerminalLifecycle.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • apps/desktop/src/main/lib/notifications/server.ts
  • apps/desktop/src/main/lib/terminal/session-location-log.ts

@kunaldhongade

Copy link
Copy Markdown
Author

@saddlepaddle @Kitenite @AviPeltz current head is locally validated and the remaining blocker is upstream approval of the fork Actions run. When one of you has a moment, could you review the updated head and click "Approve and run" so the required checks can start?

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/hooks/useTerminalColdRestore.ts (1)

258-263: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Clear the clean-exit grace window on canceled start-shell attempts.

When createOrAttach is canceled here, the callback returns before resetting preserveCleanExitUntilRef.current. That leaves the restored-session grace window armed even though no replacement shell was started, so the next clean exit can be preserved incorrectly instead of auto-closing.

Suggested fix
 				onError: (error: { message?: string }) => {
 					if (isTerminalAttachCanceledMessage(error.message)) {
+						preserveCleanExitUntilRef.current = 0;
 						return;
 					}
 					preserveCleanExitUntilRef.current = 0;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/hooks/useTerminalColdRestore.ts`
around lines 258 - 263, In useTerminalColdRestore's onError callback for
createOrAttach, ensure the restore grace window is cleared even when the attach
is canceled: call preserveCleanExitUntilRef.current = 0 before returning from
the isTerminalAttachCanceledMessage(error.message) branch so the canceled
start-shell attempt doesn't leave the grace window armed; update the onError
handler (referencing onError, isTerminalAttachCanceledMessage,
preserveCleanExitUntilRef.current, and createOrAttach) to clear the ref prior to
returning.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In
`@apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/hooks/useTerminalColdRestore.ts`:
- Around line 258-263: In useTerminalColdRestore's onError callback for
createOrAttach, ensure the restore grace window is cleared even when the attach
is canceled: call preserveCleanExitUntilRef.current = 0 before returning from
the isTerminalAttachCanceledMessage(error.message) branch so the canceled
start-shell attempt doesn't leave the grace window armed; update the onError
handler (referencing onError, isTerminalAttachCanceledMessage,
preserveCleanExitUntilRef.current, and createOrAttach) to clear the ref prior to
returning.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 97cfa244-5b87-4daf-899c-489d35c0422d

📥 Commits

Reviewing files that changed from the base of the PR and between 031e1e6 and 5789635.

📒 Files selected for processing (5)
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/Terminal.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/hooks/terminal-exit-policy.test.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/hooks/terminal-exit-policy.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/hooks/useTerminalColdRestore.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/hooks/useTerminalStream.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/Terminal.tsx

@kunaldhongade
kunaldhongade marked this pull request as draft June 12, 2026 12:06
@kunaldhongade
kunaldhongade marked this pull request as ready for review June 12, 2026 13:28
@kunaldhongade

Copy link
Copy Markdown
Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 12, 2026 •

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@cubic-dev-ai

cubic-dev-ai Bot commented Jun 14, 2026

Copy link
Copy Markdown
Contributor

You're iterating quickly on this pull request. To help protect your rate limits, cubic has paused automatic reviews on new pushes for now—when you're ready for another review, comment @cubic-dev-ai review.

@kunaldhongade

Copy link
Copy Markdown
Author

Pushed commit 54e09395b with the follow-up fixes.

What changed:

  • Persist preset launch commands before writing them into terminal panes.
  • Rebuild cold-restore resume commands from the saved Claude/Codex launch command, including env-prefixed and cd ... && active-terminal launches.
  • Fall back to the original launch command for non-agent cold restores when no resume target exists.
  • Added tests for command persistence, resume-command rebuilding, and daemon inference.

Validation:

  • bun run lint ✅
  • bun run typecheck ✅
  • Targeted terminal tests ✅: bun test apps/desktop/src/main/lib/terminal/agent-resume.test.ts apps/desktop/src/main/lib/terminal/session-location-log.test.ts apps/desktop/src/main/lib/terminal/daemon/daemon-manager.test.ts apps/desktop/src/renderer/lib/terminal/launch-command.test.ts apps/desktop/src/renderer/stores/tabs/preset-launch.test.ts
  • bun run build ✅ (desktop build completed; existing CSS/optional dependency warnings only)
  • bun test ⚠️ still fails in existing packages/pty-daemon tests (handoff.test.ts and control-plane.test.ts) and then Bun crashes; reproduced twice and appears unrelated to these desktop terminal autoresume changes.
  • PR checks currently show CodeRabbit passing.

@kunaldhongade

Copy link
Copy Markdown
Author

@coderabbitai review
@greptile-apps review
@cubic-dev-ai review

Please re-run review on the latest commit c43c5602c. This update fixes the stale commandless-agent restore case by falling back to Superset’s built-in preset command for known Claude/Codex rows, with regression coverage for Codex rows that have agentId/agentSessionId but no stored launch command.

Local validation after the latest fix:

  • ./scripts/lint.sh apps/desktop/src/main/lib/terminal/daemon/daemon-manager.ts apps/desktop/src/main/lib/terminal/daemon/daemon-manager.test.ts
  • bun test apps/desktop/src/main/lib/terminal/daemon/daemon-manager.test.ts apps/desktop/src/main/lib/terminal/agent-resume.test.ts apps/desktop/src/main/lib/terminal/session-location-log.test.ts
  • bunx turbo typecheck --filter=@superset/desktop

@cubic-dev-ai

cubic-dev-ai Bot commented Jun 14, 2026

Copy link
Copy Markdown
Contributor

@coderabbitai review
@greptile-apps review
@cubic-dev-ai review

Please re-run review on the latest commit c43c5602c. This update fixes the stale commandless-agent restore case by falling back to Superset’s built-in preset command for known Claude/Codex rows, with regression coverage for Codex rows that have agentId/agentSessionId but no stored launch command.
...

@kunaldhongade I have started the AI code review. It will take a few minutes to complete.

@coderabbitai

coderabbitai Bot commented Jun 14, 2026 •

Copy link
Copy Markdown
Contributor

@kunaldhongade: Acknowledged — triggering a fresh incremental review on head c43c5602c.

The fallback to Superset's built-in preset command for commandless known Claude/Codex rows is a good hardening step, and the Codex regression coverage for agentId/agentSessionId-present-but-no-command rows closes a realistic gap. Results will be posted once the diff analysis completes.

✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

0 issues found across 2 files (changes from recent commits).

You've manually re-run cubic several times on this PR. Each manual re-review checks the full PR again and counts toward your usage quota. To preserve your usage limits, we recommend letting cubic automatically review new commits.

Re-trigger cubic

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
apps/desktop/src/main/lib/host-db.ts (1)

115-141: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Close stale cached DB when no active organization is resolved.

At Line 117, returning null before the close/reset block means an existing cachedDb can stay open indefinitely when org resolution fails. Move cleanup before this early return.

Suggested fix
 export function getActiveHostDb(): HostDb | null {
 	const organizationId = getActiveOrganizationId();
 	if (!organizationId) {
+		if (cachedDb) {
+			try {
+				(
+					cachedDb as unknown as { $client?: { close: () => void } }
+				).$client?.close();
+			} catch (error) {
+				console.warn("[host-db] Failed to close previous host db", error);
+			}
+			cachedDb = null;
+			cachedOrganizationId = null;
+			cachedDbPath = null;
+		}
 		return null;
 	}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/desktop/src/main/lib/host-db.ts` around lines 115 - 141, The
getActiveHostDb() function returns null when no active organization is resolved
(when !organizationId is true), but this early return happens before the cached
database cleanup block. This leaves any previously cached database open
indefinitely. Move the cleanup logic that closes cachedDb and resets
cachedOrganizationId and cachedDbPath (the block containing the try-catch that
calls $client?.close()) to execute before the early return when organizationId
is null, ensuring stale databases are properly closed when organization
resolution fails.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/desktop/src/lib/trpc/routers/terminal/terminal.ts`:
- Around line 264-279: The mutation in the terminal router always returns
success without checking whether the persistence operation actually succeeded.
Modify recordSessionLocationLaunchCommand in session-location-log.ts to return a
boolean (true on successful write/update, false on failure) instead of catching
and swallowing errors internally. Then update the mutation to capture the return
value from recordSessionLocationLaunchCommand and only return { success: true }
if the function actually returned true, allowing callers to know when recording
has failed rather than silently dropping metadata.

---

Outside diff comments:
In `@apps/desktop/src/main/lib/host-db.ts`:
- Around line 115-141: The getActiveHostDb() function returns null when no
active organization is resolved (when !organizationId is true), but this early
return happens before the cached database cleanup block. This leaves any
previously cached database open indefinitely. Move the cleanup logic that closes
cachedDb and resets cachedOrganizationId and cachedDbPath (the block containing
the try-catch that calls $client?.close()) to execute before the early return
when organizationId is null, ensuring stale databases are properly closed when
organization resolution fails.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b29eb6fa-cf5e-43db-9eaa-201239d12f53

📥 Commits

Reviewing files that changed from the base of the PR and between f56f319 and c43c560.

📒 Files selected for processing (18)
  • apps/desktop/src/lib/trpc/routers/terminal/terminal.ts
  • apps/desktop/src/main/lib/host-db-selection.test.ts
  • apps/desktop/src/main/lib/host-db.ts
  • apps/desktop/src/main/lib/terminal/agent-resume.test.ts
  • apps/desktop/src/main/lib/terminal/agent-resume.ts
  • apps/desktop/src/main/lib/terminal/daemon/daemon-manager.test.ts
  • apps/desktop/src/main/lib/terminal/daemon/daemon-manager.ts
  • apps/desktop/src/main/lib/terminal/daemon/types.ts
  • apps/desktop/src/main/lib/terminal/session-location-log.test.ts
  • apps/desktop/src/main/lib/terminal/session-location-log.ts
  • apps/desktop/src/main/lib/terminal/types.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/types.ts
  • apps/desktop/src/renderer/stores/tabs/useTabsWithPresets.ts
  • packages/host-service/drizzle/0008_drop_terminal_sessions_workspace_fk.sql
  • packages/host-service/drizzle/meta/0008_snapshot.json
  • packages/host-service/drizzle/meta/_journal.json
  • packages/host-service/src/db/schema.test.ts
  • packages/host-service/src/db/schema.ts
✅ Files skipped from review due to trivial changes (3)
  • packages/host-service/drizzle/0008_drop_terminal_sessions_workspace_fk.sql
  • packages/host-service/drizzle/meta/0008_snapshot.json
  • packages/host-service/drizzle/meta/_journal.json
🚧 Files skipped from review as they are similar to previous changes (4)
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/types.ts
  • apps/desktop/src/main/lib/terminal/types.ts
  • apps/desktop/src/main/lib/terminal/daemon/types.ts
  • apps/desktop/src/main/lib/terminal/session-location-log.ts

@kunaldhongade

Copy link
Copy Markdown
Author

Pushed ac6bd5c8e addressing the latest CodeRabbit feedback.

Changes:

  • getActiveHostDb() now closes and resets the cached host DB when no active organization can be resolved, avoiding stale DB handles.
  • recordSessionLocationLaunchCommand() and related session-location helpers now return real persistence status instead of swallowing failures.
  • terminal.recordLaunchCommand now returns that actual persistence result instead of always reporting { success: true }.
  • Added coverage for successful preset launch-command recording and unavailable-store failure.
  • Removed the PR-only host-db-selection.test.ts because it was brittle under Bun package-cwd module mocking; the production host DB cleanup fix remains covered by the implementation and the full desktop suite is clean.

Validation on ac6bd5c8e:

  • bun run lint ✅
  • bun run typecheck ✅
  • targeted terminal/session-location tests ✅
  • bun run --cwd apps/desktop test ✅
  • bun run test ✅
  • bun run build ✅

No unresolved, non-outdated inline review threads remain from the current bot feedback.

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 14, 2026 •

Copy link
Copy Markdown
Contributor

@kunaldhongade: Acknowledged — triggering a fresh incremental review on head ac6bd5c8e.

The changes look well-reasoned:

  • Closing/resetting the cached host DB when no active organization resolves is a good resource hygiene fix.
  • Surfacing real persistence status through recordSessionLocationLaunchCommand and terminal.recordLaunchCommand (instead of swallowing failures with a hardcoded { success: true }) makes error propagation more honest.
  • The removal of the brittle host-db-selection.test.ts is pragmatic given Bun's module-cwd mocking constraints — the production fix is still covered by the implementation.

Results will be posted once the diff analysis completes.

✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
apps/desktop/src/main/lib/terminal/agent-resume.ts (1)

665-699: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Don't silently switch to a different session when the stored sessionId no longer resolves.

Once the stored transcript lookup fails, this falls back to cwd-only transcript matching and can return a different sessionId. Downstream, daemon-manager writes that new identity back to storage and auto-injects its resumeCommand, so a missing transcript can reopen the wrong conversation instead of falling back to the manual-retry path described in the PR objective.

A safer contract here is: if params.sessionId was supplied, only accept an exact transcript match for that same session, otherwise return null/knownCommand and let the user recover manually.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/desktop/src/main/lib/terminal/agent-resume.ts` around lines 665 - 699,
When a stored sessionId is provided in params but its transcript lookup fails
(hasStoredTranscript is false), the code should not fall back to searching
transcripts by agent ID alone, as this can match a different sessionId and cause
the wrong session to be reopened. Modify the logic to return null immediately
after the transcript lookup failure when normalizedSessionId was explicitly
provided, instead of continuing to call resolveCandidateFromTranscripts. Only
allow the fallback transcript scan to occur when no specific sessionId was
supplied in params.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/desktop/src/main/lib/terminal/agent-resume.ts`:
- Around line 341-346: The code appends a resume clause to the command arguments
without checking if one already exists, which causes invalid duplicate resume
invocations when the original command is already something like "claude --resume
<id>" or "codex resume <id>". Before appending the resume clause (either
"--resume" for claude or "resume" for other agents), check whether parsed.args
already contains "resume" or parsed.command already includes a resume
invocation. Only construct the args with the appended resume parameters if no
resume clause is already present; otherwise, return the parsed command as-is
with its original args.

---

Outside diff comments:
In `@apps/desktop/src/main/lib/terminal/agent-resume.ts`:
- Around line 665-699: When a stored sessionId is provided in params but its
transcript lookup fails (hasStoredTranscript is false), the code should not fall
back to searching transcripts by agent ID alone, as this can match a different
sessionId and cause the wrong session to be reopened. Modify the logic to return
null immediately after the transcript lookup failure when normalizedSessionId
was explicitly provided, instead of continuing to call
resolveCandidateFromTranscripts. Only allow the fallback transcript scan to
occur when no specific sessionId was supplied in params.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 1e87514a-e90a-435b-815a-90948e0ddabc

📥 Commits

Reviewing files that changed from the base of the PR and between f56f319 and ac6bd5c.

📒 Files selected for processing (17)
  • apps/desktop/src/lib/trpc/routers/terminal/terminal.ts
  • apps/desktop/src/main/lib/host-db.ts
  • apps/desktop/src/main/lib/terminal/agent-resume.test.ts
  • apps/desktop/src/main/lib/terminal/agent-resume.ts
  • apps/desktop/src/main/lib/terminal/daemon/daemon-manager.test.ts
  • apps/desktop/src/main/lib/terminal/daemon/daemon-manager.ts
  • apps/desktop/src/main/lib/terminal/daemon/types.ts
  • apps/desktop/src/main/lib/terminal/session-location-log.test.ts
  • apps/desktop/src/main/lib/terminal/session-location-log.ts
  • apps/desktop/src/main/lib/terminal/types.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/types.ts
  • apps/desktop/src/renderer/stores/tabs/useTabsWithPresets.ts
  • packages/host-service/drizzle/0008_drop_terminal_sessions_workspace_fk.sql
  • packages/host-service/drizzle/meta/0008_snapshot.json
  • packages/host-service/drizzle/meta/_journal.json
  • packages/host-service/src/db/schema.test.ts
  • packages/host-service/src/db/schema.ts
✅ Files skipped from review due to trivial changes (2)
  • packages/host-service/drizzle/0008_drop_terminal_sessions_workspace_fk.sql
  • packages/host-service/drizzle/meta/0008_snapshot.json
🚧 Files skipped from review as they are similar to previous changes (14)
  • apps/desktop/src/main/lib/terminal/types.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/types.ts
  • apps/desktop/src/main/lib/terminal/daemon/types.ts
  • apps/desktop/src/lib/trpc/routers/terminal/terminal.ts
  • packages/host-service/drizzle/meta/_journal.json
  • apps/desktop/src/renderer/stores/tabs/useTabsWithPresets.ts
  • packages/host-service/src/db/schema.test.ts
  • packages/host-service/src/db/schema.ts
  • apps/desktop/src/main/lib/host-db.ts
  • apps/desktop/src/main/lib/terminal/agent-resume.test.ts
  • apps/desktop/src/main/lib/terminal/daemon/daemon-manager.test.ts
  • apps/desktop/src/main/lib/terminal/daemon/daemon-manager.ts
  • apps/desktop/src/main/lib/terminal/session-location-log.test.ts
  • apps/desktop/src/main/lib/terminal/session-location-log.ts

@kunaldhongade

Copy link
Copy Markdown
Author

@Kitenite thanks for the direction here. I updated the implementation to use the existing host-service DB path instead of a standalone file.

What changed from the earlier approach:

  • restore/session-location metadata is now persisted directly on the existing per-org host.db terminal_sessions table
  • the standalone session-locations.json path is only used as a one-time legacy import/archive path
  • the intermediate terminal_session_locations state is folded forward into terminal_sessions via migration
  • Superset-started agent tabs now record their launch command/preset command, so cold restore can rebuild from the same command/options instead of only using a generic claude/codex command
  • local desktop smoke test confirms host.db migrated through 0008, host-service health is OK, and active Claude/Codex rows are persisted with the expected command/session metadata

I also updated the PR description to reflect the current DB-backed design and resolved the bot review threads. From my side this is ready for maintainer review when you have time.

@kunaldhongade

Copy link
Copy Markdown
Author

Small clarification on restore behavior: if the agent session was started from a Superset preset, the restore path uses the persisted Superset launch command/preset command as the base and appends/replaces the recovered resume clause for that agent session. So custom preset options/env/cwd-style launches are preserved instead of falling back to a generic claude or codex command.

@kunaldhongade

Copy link
Copy Markdown
Author

Pushed follow-up commit 6c7e89a84 addressing the latest restore edge cases:

  • Cold-restored scrollback is now consumed once per pane, so tab remounts before Start Shell do not duplicate restored terminal contents.
  • Brand-new Superset-launched Claude/Codex shells no longer scan old transcripts before the hook reports the real session id; transcript backfill is limited to reattaches of existing daemon sessions.
  • Restored-shell startup now marks the terminal stream ready and syncs current dimensions to the new PTY.
  • Existing resume/preset command handling remains intact, including preserving failed auto-resume metadata for retry.

Validation on this branch:

  • bunx sherif
  • bun run lint
  • bun run typecheck
  • bun run test
  • bun run build
  • focused terminal restore tests for daemon identity backfill, cold-restore scrollback consumption, and restored-shell retry behavior

@coderabbitai review
@greptile-apps review
@cubic-dev-ai review

@cubic-dev-ai

cubic-dev-ai Bot commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

Pushed follow-up commit 6c7e89a84 addressing the latest restore edge cases:

  • Cold-restored scrollback is now consumed once per pane, so tab remounts before Start Shell do not duplicate restored terminal contents.
  • Brand-new Superset-launched Claude/Codex shells no longer scan old transcripts before the hook reports the real session id; transcript backfill is limited to reattaches of existing daemon sessions.
  • Restored-shell startup now marks the terminal stream ready and syncs current dimensions to the new PTY.
    ...

@kunaldhongade I have started the AI code review. It will take a few minutes to complete.

@coderabbitai

coderabbitai Bot commented Jun 15, 2026 •

Copy link
Copy Markdown
Contributor

@kunaldhongade: Acknowledged — triggering a fresh incremental review on head 6c7e89a84.

The fixes in this commit address meaningful edge cases:

  • Single-consume scrollback: Preventing duplicate restore content on tab remounts before Start Shell is a good UX correctness fix.
  • Transcript backfill gating: Limiting transcript scanning to reattaches of existing daemon sessions (rather than firing on brand-new shells) avoids false positives where a new agent shell might accidentally pick up an unrelated prior session's transcript.
  • Stream-ready + dimension sync on restored-shell startup: Ensuring PTY dimensions are current after cold restore prevents layout glitches in the restored terminal.
  • Preserved resume/preset metadata for retry: Keeping failed auto-resume metadata intact is important for the fallback UX path.

Full local validation (bunx sherif, lint, typecheck, test, build) plus targeted restore tests look solid. Results will be posted once the diff analysis completes.

✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/hooks/useTerminalColdRestore.ts`:
- Around line 125-142: The issue is that coldRestoreState is persisted as
restored at the anchor location (lines 125-142 where coldRestoreState.set is
called), but when the writeCommandInPane operation fails in the sibling location
(lines 254-275), the stale coldRestoreState is not cleared. This causes
useTerminalLifecycle to incorrectly read storedColdRestore.isRestored on remount
and re-enter restored-mode handling instead of normal live-session flow. To fix
this: in the failure/error handling path of the writeCommandInPane call (around
lines 254-275), add logic to clear or reset the coldRestoreState entry for the
paneId that was previously set to mark it as restored. This ensures that if
command injection fails, the cold restore state is not left in an inconsistent
state for the next mount cycle.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 9e0e8eea-1126-48c4-9b4d-075169956efb

📥 Commits

Reviewing files that changed from the base of the PR and between ac6bd5c and 6c7e89a.

📒 Files selected for processing (13)
  • apps/desktop/src/main/lib/notifications/server.ts
  • apps/desktop/src/main/lib/terminal/agent-resume.test.ts
  • apps/desktop/src/main/lib/terminal/agent-resume.ts
  • apps/desktop/src/main/lib/terminal/daemon/daemon-manager.test.ts
  • apps/desktop/src/main/lib/terminal/daemon/daemon-manager.ts
  • apps/desktop/src/main/lib/terminal/env.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/hooks/useTerminalColdRestore.test.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/hooks/useTerminalColdRestore.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/hooks/useTerminalLifecycle.test.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/hooks/useTerminalLifecycle.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/state.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/types.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/v1-terminal-cache.ts
🚧 Files skipped from review as they are similar to previous changes (7)
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/types.ts
  • apps/desktop/src/main/lib/terminal/env.ts
  • apps/desktop/src/main/lib/terminal/daemon/daemon-manager.test.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/hooks/useTerminalLifecycle.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/hooks/useTerminalColdRestore.test.ts
  • apps/desktop/src/main/lib/terminal/daemon/daemon-manager.ts
  • apps/desktop/src/main/lib/terminal/agent-resume.ts

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 12 files (changes from recent commits).

You've manually re-run cubic several times on this PR. Each manual re-review checks the full PR again and counts toward your usage quota. To preserve your usage limits, we recommend letting cubic automatically review new commits.
Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

If session-locations.json is malformed on first boot after upgrade,
the previous code set legacyImportEnsured=true before re-throwing,
permanently blocking the migration. Removing the inner try/catch lets
the outer catch log the error while leaving the flag false so the next
boot retries after the corrupt file is repaired or cleared.
…ilure

When writeCommandInPane fails after handleStartShell creates the new
shell, the coldRestoreState entry still had isRestored:true. On any
subsequent remount useTerminalLifecycle would read that flag and
re-enter the cold-restore overlay even though a live session was
already running.

Add clearRestoreResumeState() to the .catch() handler and update the
test to assert the state is cleared on failure instead of retained.
@kunaldhongade

Copy link
Copy Markdown
Author

@Kitenite thanks again for the earlier direction on using the DB here instead of a standalone file. The current head follows that design: restore/session metadata now lives on the existing host-service terminal_sessions path, and the later follow-ups closed the restore edge cases we found during local testing.

What changed on the final path:

  • cold-restored scrollback is consumed once, so tab remounts do not duplicate terminal contents
  • transcript backfill is limited to reattaches, so brand-new Superset-launched agent shells do not pick up stale prior sessions
  • restored shells now sync stream readiness and dimensions correctly
  • Superset-started preset sessions restore from their original preset/launch command base instead of falling back to generic claude / codex commands

Current state from my side:

  • 0 unresolved, non-outdated review threads remain
  • local validation passed: bunx sherif, bun run lint, bun run typecheck, bun run test, bun run build

If the scope looks right to you, I'd really appreciate a final review and fork-CI approval. If nothing else stands out on your side, I believe this is ready to merge.

@kunaldhongade

Copy link
Copy Markdown
Author

@Kitenite ping

@2solarmax

Copy link
Copy Markdown

Really nice work, @kunaldhongade — I read through the branch closely and it's well-factored. Coming at this from a different angle: over the last few days we independently built a small userland auto-resume tool for the same problem (a zsh hook that resumes each restored pane from host.db) before we found this PR, and landed on the same core mechanism — which I hope is useful as independent validation of the approach.

A few notes from reading it:

  • Thundering-herd is handled cleanly. CREATE_OR_ATTACH_CONCURRENCY = 3 + the PrioritySemaphore gating createOrAttach (daemon-manager.ts, acquire() before attemptColdRestore) bounds cold-restore to 3 concurrent, so a 40-pane restart doesn't spike. We used time-staggering for the same reason; a hard cap is cleaner.
  • Transcript existence is genuinely gated — not a blind resume. resolveAgentResumeTarget checks hasClaudeTopLevelTranscript for the stored session and, if it's gone, falls back to the cwd-scoped resolveCandidateFromTranscripts scan, which returns null when nothing matches. So a pruned worktree / rolled-off transcript yields no target rather than a --resume into a fresh session. Good call — that was the subtle failure mode.
  • One thing worth flagging (pre-existing, but this PR makes it load-bearing): cold-restore reads host.db through createDb() (host-db.ts:154 → packages/host-service/src/db/db.ts), which sets journal_mode=WAL + busy_timeout + foreign_keys and lets a failed migrate() throw — but there's no PRAGMA quick_check/integrity_check on open. host-db.ts wraps its reads in try/catch and logs a warning, so a host.db truncated or corrupted by the same panic that triggered the restart would be swallowed as a console warning — cold-restore metadata silently unavailable, no user-facing signal. [bug] Superset sqlite got corrupted and window never opened #5084 ("Superset sqlite got corrupted and window never opened") is that exact engine failing that way. Since auto-resume now depends on reading this DB right after an unclean shutdown, a quick_check on open plus a surfaced warning would make that failure visible instead of silent. Not a blocker for this PR — more a companion hardening.

Two things we verified empirically that support the design here: paneId / terminal_id / SUPERSET_TERMINAL_ID is stable across a real cold restart and the terminal_agent_bindings row survives it (tested on a live 40+ pane, 4-workspace session); and launch-command reuse really matters — our first cut dropped the user's wrapper + flags, so your buildResumeCommandFromOriginalLaunch rebuild-from-original is the right instinct.

Since this is waiting on review, we published our version as a works-today stopgap for people hitting this now — it auto-detects the native column and stands down when this merges, so no double-resume during the transition: https://github.com/2solarmax/superset-session-resume . Happy to help however's useful — and glad to see the native fix moving.

@Kitenite

Copy link
Copy Markdown
Member

Closing: main already ships this. 2f0fb70 (#6572) idempotent auto-resume. Thanks for the PR; if you think the shipped version misses a case, open an issue and link this.

@Kitenite Kitenite closed this Aug 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

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

3 participants