# How to Restore Conversation State in Earendil PI Sessions

> Easily restore Earendil PI sessions by resuming previous conversations. Learn how to rehydrate your full chat state with `--resume`, `/resume`, or the SDK switchSession method.

- Repository: [Earendil Works/pi](https://github.com/earendil-works/pi)
- Tags: how-to-guide
- Published: 2026-05-25

---

**Earendil PI persists every interaction to a JSONL session file beside your project and rehydrates the full conversation state—including pending messages and editor buffers—when you use the `--resume` flag, the `/resume` slash-command, or the SDK's `switchSession()` method.**

The Earendil PI CLI (located in the `earendil-works/pi` repository) stores your entire coding conversation in local `*.jsonl` session files, enabling you to suspend work and resume days later without losing context. Understanding how to restore conversation state in Earendil PI sessions allows you to maintain continuity across terminal sessions, external editor invocations, and system interruptions.

## Where Conversation State Is Stored

PI stores every interaction in a **session file** (`*.jsonl`) that lives beside your project's source tree. When you suspend a session—by exiting the TUI, spawning an external editor, or explicitly pausing—the CLI records the current editor buffer and pending messages to this append-only JSONL format. This design guarantees deterministic replay because the exact entries are re-executed during restoration.

## The Restoration Workflow

The resume operation follows a five-step pipeline that tightly couples the CLI argument parser, session manager, and interactive mode components.

### 1. Session Selection via CLI Arguments

When you invoke PI with the `--resume` flag, [`packages/coding-agent/src/cli/args.ts`](https://github.com/earendil-works/pi/blob/main/packages/coding-agent/src/cli/args.ts) parses the option at line 81 (`result.resume = true`) and triggers the session picker UI.

```bash
pi --resume

```

The picker interface defined in [`packages/coding-agent/src/cli/session-picker.ts`](https://github.com/earendil-works/pi/blob/main/packages/coding-agent/src/cli/session-picker.ts) displays available JSONL files and awaits your selection.

### 2. File Loading and Entry Parsing

Once you select a file, the `SessionManager` class instantiated in [`packages/coding-agent/src/core/session-manager.ts`](https://github.com/earendil-works/pi/blob/main/packages/coding-agent/src/core/session-manager.ts) calls `loadEntriesFromFile(this.sessionFile)` at line 732. This method deserializes each JSONL entry and reconstructs the in-memory conversation model, including system prompts, user messages, and any assistant partial replies.

### 3. Message Restoration and Buffer Replay

After the new `AgentSession` is created, `AgentSessionRuntime` orchestrates the switch. In [`packages/coding-agent/src/core/agent-session-runtime.ts`](https://github.com/earendil-works/pi/blob/main/packages/coding-agent/src/core/agent-session-runtime.ts) at line 128, the runtime emits `emitBeforeSwitch("resume", …)` and `teardownCurrent("resume", …)` to signal the transition.

The actual message replay occurs in [`packages/coding-agent/src/modes/interactive/interactive-mode.ts`](https://github.com/earendil-works/pi/blob/main/packages/coding-agent/src/modes/interactive/interactive-mode.ts). The method `restoreQueuedMessagesToEditor()` defined at line 3692 re-populates the editor buffer with your previously typed text. This method is invoked following the session switch at line 3428, ensuring theUI displays your exact state prior to suspension.

### 4. Event Emission for Extensions

For extensions that need to synchronize with session lifecycle changes, the runtime emits two distinct events. At lines 132–138 in [`agent-session-runtime.ts`](https://github.com/earendil-works/pi/blob/main/agent-session-runtime.ts), PI fires `session_before_switch` with `reason: "resume"` followed by `session_start` with the same reason. Listeners receive an event object containing `targetSessionFile` and can optionally cancel the resume by returning `{ cancelled: true }`.

### 5. Editor State Recovery

The restoration routine copies `options.currentText` (if supplied) or the editor's saved snapshot, then returns the count of restored messages. If you had an in-flight completion when the session paused, that message is re-queued so the UI can display it again.

## Resuming from the Command Line

### Using the --resume Flag

The simplest method to restore conversation state is launching PI with the resume flag:

```bash
pi --resume

```

This triggers the file picker, loads the selected JSONL, and automatically restores the conversation context.

### Using the /resume Slash Command

While inside the interactive TUI, type:

```text
/resume

```

This slash-command defined in [`packages/coding-agent/src/core/slash-commands.ts`](https://github.com/earendil-works/pi/blob/main/packages/coding-agent/src/core/slash-commands.ts) invokes the same runtime switch as the CLI flag. The command calls the internal resume handler which executes `AgentSessionRuntime.switchSession()` with your last active session file.

## Programmatic Session Restoration

You can resume sessions programmatically using the PI SDK. This mirrors the internal `AgentSessionRuntime.switchSession()` logic and emits the same lifecycle events.

```typescript
import { Pi } from "@earendil/pi";

const pi = await Pi.create();
await pi.sessionRuntime.switchSession("/path/to/old-session.jsonl");

```

The SDK call emits `session_before_switch` with `reason: "resume"` and restores all queued messages through the same `restoreQueuedMessagesToEditor()` pathway used by the CLI.

### Hooking into Resume Lifecycle Events

Extensions can monitor or intercept resume operations:

```typescript
pi.on("session_before_switch", async (event) => {
  if (event.reason === "resume") {
    console.log("About to resume:", event.targetSessionFile);
    // Validate file or preload resources here
  }
});

```

Returning `{ cancelled: true }` from this handler prevents the resume operation, allowing extensions to implement custom validation logic.

## Summary

- **Session files** are stored as `*.jsonl` beside your project tree, preserving every message and editor state.
- **Resume via CLI** using `pi --resume` triggers the session picker in [`packages/coding-agent/src/cli/session-picker.ts`](https://github.com/earendil-works/pi/blob/main/packages/coding-agent/src/cli/session-picker.ts).
- **Resume via TUI** by typing `/resume`, which invokes the same runtime switch defined in [`packages/coding-agent/src/core/slash-commands.ts`](https://github.com/earendil-works/pi/blob/main/packages/coding-agent/src/core/slash-commands.ts).
- **Message restoration** happens through `InteractiveMode.restoreQueuedMessagesToEditor()` at line 3692 of the interactive mode source, repopulating buffers with pending text.
- **Extension hooks** receive `session_before_switch` and `session_start` events with `reason: "resume"`, enabling synchronization with external tools.

## Frequently Asked Questions

### What file format does Earendil PI use to store session history?

PI uses **JSONL** (JSON Lines) format with a `*.jsonl` extension. Each line represents a discrete interaction event, allowing the system to append new messages efficiently and replay the conversation deterministically by reading the file sequentially.

### How do I resume a session after closing the terminal?

Run `pi --resume` from the same project directory. The CLI will present a picker interface (implemented in [`packages/coding-agent/src/cli/session-picker.ts`](https://github.com/earendil-works/pi/blob/main/packages/coding-agent/src/cli/session-picker.ts)) showing available session files. Select your previous session, and the `SessionManager` in [`packages/coding-agent/src/core/session-manager.ts`](https://github.com/earendil-works/pi/blob/main/packages/coding-agent/src/core/session-manager.ts) will rehydrate the conversation at line 732 via `loadEntriesFromFile()`.

### Can extensions intercept or cancel a session restoration?

Yes. Extensions can listen for the `session_before_switch` event emitted by `AgentSessionRuntime` at lines 132–138. If your handler returns an object with `{ cancelled: true }`, PI aborts the resume operation. This allows validation logic to prevent restoration of corrupt or incompatible session files.

### Does resuming restore my partially typed message in the editor?

Yes. The `restoreQueuedMessagesToEditor()` method in [`packages/coding-agent/src/modes/interactive/interactive-mode.ts`](https://github.com/earendil-works/pi/blob/main/packages/coding-agent/src/modes/interactive/interactive-mode.ts) (line 3692) specifically handles editor buffer restoration. It recovers `options.currentText` or the saved editor snapshot, ensuring your draft message appears exactly as you left it, even if you had unsent text or an in-flight completion request.