Files
NetMesh/docs/session-restore.md
zhaolei 3c72efcb7f
Some checks failed
build-packages / resolve bundled mosh-client (push) Has been cancelled
build-packages / resolve bundled et-client (push) Has been cancelled
build-packages / build-macos (push) Has been cancelled
build-packages / build-windows (push) Has been cancelled
build-packages / build-linux-x64 (push) Has been cancelled
build-packages / build-linux-arm64 (push) Has been cancelled
build-packages / release (push) Has been cancelled
build-packages / update Nix release metadata (push) Has been cancelled
build-packages / bump homebrew tap (push) Has been cancelled
test / lint-and-test (push) Has been cancelled
AI automation / Route event (push) Has been cancelled
AI automation / Hand reopened issue to maintainers (push) Has been cancelled
AI automation / Clean source issue state (push) Has been cancelled
AI automation / Reconcile handoffs (push) Has been cancelled
AI automation / Classify issue (push) Has been cancelled
AI automation / Claude Code smoke (push) Has been cancelled
AI automation / Review issue follow-up (push) Has been cancelled
AI automation / Publish issue follow-up (push) Has been cancelled
AI automation / Implement with Claude Code (push) Has been cancelled
AI automation / Publish implement PR (push) Has been cancelled
AI automation / Continue queued issue comments (push) Has been cancelled
AI automation / Codex review loop (push) Has been cancelled
AI automation / Publish Codex fix (push) Has been cancelled
AI automation / Clear Codex dispatch marker (push) Has been cancelled
AI automation / Own PR re-request Codex (push) Has been cancelled
AI automation / External PR re-request Codex (push) Has been cancelled
AI automation / Poll Codex reaction / retry (push) Has been cancelled
build-et-binaries / build-linux-x64 (push) Has been cancelled
build-et-binaries / build-linux-arm64 (push) Has been cancelled
build-et-binaries / build-macos-universal (push) Has been cancelled
build-et-binaries / build-windows-x64 (push) Has been cancelled
build-et-binaries / release (push) Has been cancelled
[Init] Initial commit - NetMesh terminal manager
2026-09-13 18:24:01 +08:00

7.5 KiB

Session Restore

Session restore brings Netcatty back to the user's previous workspace shape on startup without reviving terminal processes or replaying terminal content.

Current Scope

Implemented behavior:

  • Restores terminal tabs, tab order, active tab, workspace split layout, and pane focus metadata.
  • Restores terminal sessions and reconnects them automatically.
  • Allows the user to manually reconnect if the automatic reconnect fails.
  • Optionally restores the last known working directory when a restored terminal reconnects.
  • Flushes the lightweight restore payload on page hide / unload using the same sanitizer as normal persistence.

Out of scope:

  • Restoring terminal output, scrollback, command history, logs, snapshots, or process state.
  • Persisting passwords, passphrases, private keys, or other secret material.
  • Restoring mosh / ET / telnet / serial / network-device working directories.
  • Probing remote filesystems during startup.

User-Visible Behavior

Startup Restore

When "Restore previous terminal tabs and workspace layout" is enabled, Netcatty restores the prior terminal workspace on launch. Restored terminals are marked with restoreState: "restored-disconnected" while they reconnect.

After a restored terminal reconnects, it runs the startup command currently configured on its host. Per-session startup commands are not persisted or replayed by session restore.

Manual Reconnect

If an automatic reconnect fails, the user can reconnect the restored terminal manually through the normal connection flow.

If "Restore terminal working directory on reconnect" is enabled and the restored session has an eligible lastCwd, Netcatty sends an automated cd -- ... after backend attach. The command is shell-quoted, is not added to application command history, and is attempted at most once for that reconnect.

If the directory is missing, inaccessible, or rejected by the shell, the connection remains open. Netcatty does not clear lastCwd, does not retry in a loop, and only shows a non-blocking progress note.

Settings

Setting Default Effect
Restore previous terminal tabs and workspace layout On Enables startup restore for tabs, workspaces, layout, and lightweight session metadata.
Restore terminal working directory on reconnect Off Attempts a one-shot cwd restore when an eligible restored terminal reconnects.

The cwd setting is intentionally separate because it sends a command after reconnect. Keeping it off by default avoids surprising remote-side behavior.

Architecture

The implementation follows the project layering from AGENTS.md.

Domain

domain/sessionRestore.ts owns pure restore logic:

  • Payload sanitization.
  • Restore payload construction.
  • Workspace tree pruning and allowlisting.
  • Session allowlisting.
  • Cwd restore eligibility.
  • Shell-safe cwd command formatting.

Domain helpers do not read or write storage and do not start terminal runtime work.

Application State

application/state/sessionRestoreState.ts and application/state/sessionRestoreStorage.ts own restore state lifecycle and localStorage persistence boundaries.

application/state/sessionRestoreSettings.ts and the settings sync modules own restore-related settings defaults, storage, and cross-window sync.

application/state/useSessionState.ts wires restore initialization, debounced persistence, pagehide / beforeunload flush, and restored-session reconnect transitions.

UI And Runtime Glue

UI components display reconnect progress and manual reconnect actions after failures. Terminal runtime helpers start restored sessions through the normal connection flow.

Runtime code may consume a one-shot cwd restore intent after backend attach. A restored connection may run the startup command currently configured on its host, but it must never replay a per-session startup command from persisted restore data.

Restore Payload Allowlist

The persisted payload is a single allowlisted JSON object. Invalid or stale payloads are sanitized or cleared on read.

Payload Fields

Field Purpose
version Restore schema version.
savedAt Timestamp used for diagnostics and future expiry decisions.
sessions Lightweight restored terminal session records.
activeTabId Startup tab to select after restore, sanitized against restored tabs.
tabOrder Restored top-level tab order.
workspaces Restored workspace split layout metadata.

Session Fields

Allowed session metadata includes identifiers, display metadata, safe connection descriptors, terminal type, status placeholder state, lastCwd, and other lightweight fields needed to render and manually reconnect a session.

The session allowlist may include non-secret metadata such as serialConfig, localShellArgs, and localShellIcon when those fields are needed to rebuild the reconnect entry point. Nested objects must be rebuilt field-by-field. For serialConfig, only path, baudRate, dataBits, stopBits, parity, flowControl, localEcho, and lineMode are restorable.

Enum-like fields such as protocol and shellType are restored only when they match known supported values.

Always forbidden:

  • Terminal output or scrollback.
  • Command history.
  • SFTP as the active startup tab.
  • Startup command payloads copied from live runtime state.
  • Process ids, bridge handles, reuse pointers, subscriptions, timers, or runtime object references.
  • Passwords, passphrases, private key contents, tokens, or secret environment values.

Workspace Fields

Workspace restoration allowlists only structural UI metadata:

  • Workspace id and label metadata.
  • View mode.
  • Focused session id.
  • Focus session order.
  • Snippet id.
  • Root split / pane tree fields required to reconstruct layout.

Workspace panes are pruned if they reference sessions outside the same workspace or sessions missing from the restored payload.

Cwd Restore Eligibility

Eligible by default:

  • Local terminal sessions.
  • SSH sessions to Unix-like hosts that are not classified as network devices.

Skipped by default:

  • Missing or empty lastCwd.
  • Disabled cwd restore setting.
  • Non-restored or already-live sessions.
  • Network devices.
  • Mosh and Eternal Terminal.
  • Telnet and serial sessions.
  • Windows-like paths.
  • Paths outside the accepted /..., ~, and ~/... forms.
  • ~user/... paths.

The path check is best-effort. The remote filesystem may have changed, so reconnect must continue even when cd fails.

Safety Boundaries

Startup restore is side-effect free with respect to terminal backends. It may create React UI and visible xterm surfaces for mounted components, but it must not start hidden backend work, network connections, polling loops, or cwd probes.

Persistence uses the same sanitizer for debounced writes and unload flushes. New restore fields must be added through the domain allowlist and covered by tests.

Automatic reconnect remains a separate product decision and requires a new risk review. It would introduce startup-side network activity, authentication prompts, server audit events, connection storms, and retry behavior that this implementation intentionally avoids.

Verification

The implementation was verified with:

  • npm run lint
  • npm run build
  • Broad affected test runs covering application/state, domain, settings components, terminal components, terminal runtime, and terminal layer tests.

Important review finding already fixed:

  • Workspace node allowlisting now reconstructs allowed pane / split fields instead of spreading arbitrary node data into the restore payload.