Skip to content

Session persistence Phase 1: local sessions survive app restart (tmux-backed) - #9

Open
HAN-oQo wants to merge 14 commits into
mainfrom
feat/session-persistence
Open

HAN-oQo wants to merge 14 commits into
mainfrom
feat/session-persistence

Conversation

@HAN-oQo

@HAN-oQo HAN-oQo commented Jul 15, 2026

Copy link
Copy Markdown
Owner

Session persistence — Phase 1 (local, tmux-backed)

Local Switchboard sessions now keep running in the background when the app is closed, and the app reattaches to the live process on reopen. Closing the app no longer kills your in-flight builds / long-running commands / Claude conversations.

How it works

Each local session runs inside its own tmux server (tmux -S <per-session socket> new-session -A -s sb_<handle> …). The tmux server is a detached daemon, so it (and the session's process) survive app quit. On startup the app probes each stored session and reattaches to the ones that were open; other still-alive sessions show a ● bg badge. Env is passed via the tmux client's environ (no -e), so secrets never appear in process argv, and each session's env is isolated.

Fully gated + graceful fallback: if tmux isn't installed or the new persistSessions setting is off, behavior is identical to today (kill on quit; --resume on reopen). A one-time notice suggests brew install tmux when it's missing.

Lifecycle

  • App quit → detach only (tmux server + process survive)
  • Close tab → keep running in background (shows as a badge next launch)
  • End sessiontmux kill-server (actually stops it)

Scope

Phase 1 = local sessions only (Claude + plain terminal). Deferred: Phase 2 remote (SSH) persistence via remote-host tmux; Phase 3 full scrollback capture on reattach, background-session management UI + reattach cap, no-tmux-notice toast, socket-file cleanup on abnormal exit.

Quality

Built with subagent-driven development: each of the 7 tasks got an independent spec+quality review, plus a final whole-branch review on the most capable model. Findings fixed before merge:

  • Critical: reattach was keying on the random handle instead of the Claude session id → risked a second concurrent claude --resume on the same transcript. Fixed by recording claudeSessionId at session creation.
  • Important: wasted/dead MCP server on reattach (now skipped + documented); before-quit overwriting wasOpen for tab-closed sessions (now mirrors rendererAttached).
  • Minors: list IPC now gated on persistEnabled(); no empty-store write in pure fallback.

Verification

  • 97 unit tests pass (tmux-session.js, session-store.js pure logic; existing suite).
  • Runtime smoke test passed against real tmux 3.4 (isolated temp dir): session spawns in its per-session server; survives client death; reattach binds the same live pid; End-session kills it; env (incl. CLAUDE_CODE_SSE_PORT) inherited by the pane; no secret in argv.
  • Not yet done — needs a manual GUI pass before shipping: open a session → quit the app → relaunch → confirm the tab auto-reattaches to the still-running process and background sessions show the badge; and the no-tmux fallback in the real app.

Files

tmux-session.js (new), session-store.js (new), main.js, preload.js, public/{app,sidebar,settings-panel}.js, public/style.css, session-transitions.js, + tests. Design spec & plan under docs/superpowers/.

🤖 Generated with Claude Code

HAN-oQo and others added 14 commits July 15, 2026 14:27
…arts

Sessions keep running in the background (local tmux / remote-host tmux) when
the app closes; app reattaches to the live process with scrollback on reopen.
Covers session handle model, persistence store, spawn flow (local + remote),
dedicated tmux config, lifecycle (quit=detach, tab-close=background,
end-session=kill), startup auto-reattach + badge, tmux-absent fallback, risks,
and 3-phase rollout.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…sistence

Bite-sized TDD tasks: pure tmux-session.js helpers + tests, tmux detection +
isolated conf, persistentSessions store transforms, spawn-in-tmux for local
Claude/terminal sessions, detach-on-quit / kill-on-end lifecycle, startup
auto-reattach + background-session listing, sidebar badge + setting + no-tmux
notice. Remote (Phase 2) and scrollback/mgmt UI (Phase 3) scoped out.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… notice

Task 7 (final): surface tmux-backed persistence to the user.
- sidebar: muted-green "bg" badge for sessions in window.__backgroundSessions,
  mirroring the existing remote-badge insertion/styling.
- settings: global "Keep sessions running in the background (tmux)" toggle
  bound to persistSessions (default on), mirroring the remoteIde toggle.
- main.js: one-time terminal-notification when tmux is missing but
  persistence is desired, local sessions only.
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.

1 participant