# Warm Reattach vs Cold Restore in Nodeterm Tmux Sessions: A Technical Deep Dive

> Understand the difference between warm reattach and cold restore for Nodeterm Tmux sessions. Learn how each method handles existing and new sessions for efficient workflow management.

- Repository: [eneskirca/nodeterm](https://github.com/eneskirca/nodeterm)
- Tags: deep-dive
- Published: 2026-08-23

---

**Warm reattach connects to an existing tmux session without replaying data, while cold restore recreates the tmux session and replays persisted scrollback after a host reboot.**

Nodeterm persists every terminal inside a named tmux session (`nt-<nodeId>`) to survive application restarts and system crashes. When the Electron renderer reconnects, it must determine whether the underlying tmux server survived or was killed by a reboot, choosing between a **warm reattach** or a **cold restore** strategy.

## How Nodeterm Manages Tmux Session Persistence

Nodeterm wraps every terminal node in a persistent tmux session identified by the pattern `nt-<nodeId>`. This architecture ensures that terminal processes survive even when the Electron application is closed. However, when the renderer restarts, the code must detect whether the tmux session is still alive or was destroyed by a system reboot.

## Warm Reattach: Attaching to Live Tmux Sessions

A **warm reattach** occurs when the tmux session survived the application restart and remains active on the host. In this scenario, the new xterm client simply attaches to the existing session, and tmux immediately redraws the pane using its internal scrollback buffer.

According to the source code in [`src/renderer/terminal/terminal-config.ts`](https://github.com/eneskirca/nodeterm/blob/main/src/renderer/terminal/terminal-config.ts), the `attachReplay` function returns **`warm-attach`** when the session exists (lines 555-557). Subsequently, `seedPaint` resolves to **`none`** (lines 80-94), meaning the renderer writes no initial data into the xterm because tmux handles all drawing independently.

## Cold Restore: Recovering After System Reboots

A **cold restore** happens when the tmux server was killed—typically after a machine reboot—and the session no longer exists. Nodeterm must create a fresh tmux session and manually **replay the persisted scrollback** that was saved before the shutdown, including a "session restored" separator.

In [`src/renderer/terminal/terminal-config.ts`](https://github.com/eneskirca/nodeterm/blob/main/src/renderer/terminal/terminal-config.ts), the `attachReplay` function returns **`cold-snapshot`** when the node is not a parked terminal and has no `initialCommand`. The `seedPaint` helper then selects **`snapshot`** (lines 90-92), writing the saved scrollback data directly into the xterm buffer so users see their previous output.

## The Decision Logic: Code Implementation

The distinction between warm and cold recovery is implemented in the terminal spawn continuation. The system uses two key helper functions to classify the attachment type and determine the seeding strategy.

```typescript
// Decide which seeding strategy to use when a terminal node is (re)created.
const replay = attachReplay({
  parked: false,            // not a parked terminal – we need a fresh buffer
  fresh:  !sessionExists,   // true if tmux died (e.g. after a reboot)
  hasInitialCommand: false // no one‑shot launch command
});
// → 'warm-attach'  (tmux still alive)  or  'cold‑snapshot' (tmux died)

// Choose what to actually write into the xterm.
const paint = seedPaint({
  replay,                     // result from above
  superseded: false,          // no `pty:resync` arrived while we were waiting
  snapshot: savedScrollback,  // string from `<userData>/terminal-scrollback/…`
  screen: undefined           // only used for co‑attach joiners
});
// → 'none' (warm‑attach) or 'snapshot' (cold‑restore)

```

These helpers are invoked in [`src/renderer/nodes/TerminalNode.tsx`](https://github.com/eneskirca/nodeterm/blob/main/src/renderer/nodes/TerminalNode.tsx) during the PTY creation flow. The `fresh` boolean originates in [`src/core/pty-manager.ts`](https://github.com/eneskirca/nodeterm/blob/main/src/core/pty-manager.ts) via `PtyCreateResult.fresh`, documented in [`docs/ios-protocol-migration.md`](https://github.com/eneskirca/nodeterm/blob/main/docs/ios-protocol-migration.md) as indicating a cold start (`true`) versus a warm reattach (`false`).

## Summary

- **Warm reattach** leverages existing tmux sessions where `fresh` is false, requiring no scrollback replay because tmux redraws the interface automatically.
- **Cold restore** handles post-reboot scenarios where tmux died, requiring session recreation and replay of persisted scrollback via the `snapshot` seeding strategy.
- The classification logic resides in [`src/renderer/terminal/terminal-config.ts`](https://github.com/eneskirca/nodeterm/blob/main/src/renderer/terminal/terminal-config.ts), specifically within the `attachReplay` and `seedPaint` functions.
- Unit tests in [`src/core/pty-single-user.test.ts`](https://github.com/eneskirca/nodeterm/blob/main/src/core/pty-single-user.test.ts) validate both scenarios using the `fresh` flag.

## Frequently Asked Questions

### What triggers a cold restore instead of a warm reattach?

A cold restore is triggered when the tmux server no longer exists, typically after a system reboot. The `fresh` flag in `PtyCreateResult` evaluates to `true`, causing `attachReplay` to return `cold-snapshot` and prompting Nodeterm to replay saved scrollback into the new terminal session.

### Where is the scrollback data stored during a cold restore?

Nodeterm persists scrollback data to the user's local storage at `<userData>/terminal-scrollback/` before the application closes. During a cold restore, this snapshot is retrieved and written into the xterm buffer via the `seedPaint` function with the `snapshot` strategy.

### Does warm reattach preserve scrollback history?

Yes. During a warm reattach, the tmux session remains alive and retains its internal scrollback buffer. The `seedPaint` function returns `none`, meaning Nodeterm injects no external data, and users continue scrolling through tmux's native history using the mouse wheel or keyboard shortcuts.

### How does the code differentiate between parked terminals and regular sessions?

The `attachReplay` function checks the `parked` parameter to distinguish between parked terminals (which have special handling) and active sessions. Non-parked terminals with no `initialCommand` and a `fresh` state of `true` are classified as `cold-snapshot`, while existing sessions attach via `warm-attach`.