# How to Save and Resume Copilot SDK Session State

> Learn how to save and resume Copilot SDK session state effortlessly. The SDK automatically persists and restores conversation history, plans, and workspace files for seamless continuity.

- Repository: [GitHub/copilot-sdk](https://github.com/github/copilot-sdk)
- Tags: how-to-guide
- Published: 2026-06-05

---

**The Copilot SDK automatically persists a session's conversational history, plan, and workspace files when `session.disconnect()` is called, and restores that exact state later through `client.resumeSession(sessionId, config)` using the original session ID.**

The GitHub Copilot SDK is designed with built-in durability that lets your agent pick up conversations across process restarts, crashes, or scaled deployments. When you need to save and resume Copilot SDK session state, the runtime manages the persistence layer for you—flushing in-memory data to disk and rehydrating it on demand. Below is a source-level breakdown of the mechanism, configuration options, and production-ready code patterns found in the SDK.

## How Session Persistence Works

The persistence mechanism operates in two distinct layers implemented in the TypeScript SDK.

- **SDK-managed shutdown** — Calling `session.disconnect()` triggers the runtime to write the session's in-memory data to an on-disk store. This implementation lives in [`nodejs/src/session.ts`](https://github.com/github/copilot-sdk/blob/main/nodejs/src/session.ts), where the `disconnect` method executes the flush operation. The resulting workspace is accessible through the `workspacePath` getter exposed by the same file.

- **SDK-managed restart** — Calling `client.resumeSession(sessionId, config)` reads the stored state from disk, re-instantiates a `CopilotSession`, and re-attaches all handlers including tools, permission hooks, and UI callbacks. This logic is implemented in [`nodejs/src/client.ts`](https://github.com/github/copilot-sdk/blob/main/nodejs/src/client.ts). The method registers the session before sending the resume RPC so that runtime events such as `session.start` are not missed.

## Where Session State Is Stored

By default, the runtime uses `COPILOT_HOME`, which resolves to `~/.copilot` unless overridden.

You can redirect storage to a custom path in two ways:

- **`baseDirectory`** — Passed directly to the `CopilotClient` constructor. This makes the runtime write all session files under a single root you control.
- **`sessionFs`** — A `SessionFsConfig` object that registers a custom filesystem provider via the `sessionFs.setProvider` call in [`nodejs/src/client.ts`](https://github.com/github/copilot-sdk/blob/main/nodejs/src/client.ts). This gives you fine-grained control over every session-scoped read and write operation.

## Step-by-Step: Save and Resume a Session

Follow these steps to reliably persist a session and restore it later.

### 1. Create a Client With Persistent Storage

Configure the client with an optional custom base directory or a full `SessionFsConfig`:

```typescript
import { CopilotClient } from "@github/copilot-sdk";

const client = new CopilotClient({
  // Optional: redirect the default ~/.copilot root
  baseDirectory: "/data/copilot-home",
  // Optional: full provider config for fine-grained control
  sessionFs: {
    initialCwd: process.cwd(),
    sessionStatePath: "/data/copilot-home/session-state",
    conventions: "posix",
  },
});

```

Setting `baseDirectory` redirects the default runtime store. Providing `sessionFs` registers a custom filesystem provider that the runtime invokes for all session I/O.

### 2. Create a Session and Interact

Spawn a new session and run your conversation as usual:

```typescript
const session = await client.createSession({
  model: "gpt-4",
  onPermissionRequest: approveAll,
});

await session.sendAndWait({ prompt: "Explain the design of the SDK." });

```

### 3. Disconnect to Flush State to Disk

Call `disconnect()` to trigger the persistence layer:

```typescript
await session.disconnect();

```

After this call returns, the session’s workspace and conversation state exist on disk at the path exposed by `session.workspacePath`.

### 4. Resume the Session by ID

Store the `sessionId` value in a database, environment variable, or cache. Later, re-attach to the same conversation:

```typescript
const resumed = await client.resumeSession(session.sessionId, {
  onPermissionRequest: approveAll,
});

await resumed.sendAndWait({ prompt: "Continue where we left off." });

```

You may supply new handlers, tools, or callbacks during resume; they replace the originals attached at creation time.

### Complete Example

Here is a full, runnable script that ties the steps together using a custom storage path and infinite session mode:

```typescript
import { CopilotClient, approveAll } from "@github/copilot-sdk";

async function main() {
  const client = new CopilotClient({
    baseDirectory: "/var/copilot-data",
    sessionFs: {
      initialCwd: process.cwd(),
      sessionStatePath: "/var/copilot-data/sessions",
      conventions: "posix",
    },
  });

  const session = await client.createSession({
    model: "gpt-4",
    onPermissionRequest: approveAll,
    infiniteSessions: { enabled: true },
  });

  await session.sendAndWait({ prompt: "Write a TypeScript utility that parses CSV." });

  await session.disconnect();

  console.log("Session saved, ID:", session.sessionId);
  console.log("Workspace on disk:", session.workspacePath);

  const resumed = await client.resumeSession(session.sessionId, {
    onPermissionRequest: approveAll,
  });

  await resumed.sendAndWait({ prompt: "Add unit tests for the CSV utility." });
}

main().catch(console.error);

```

This creates a workspace under `/var/copilot-data/sessions/<sessionId>/`, safely stores all files and the conversation log on `disconnect`, and restores the exact session when `resumeSession` is called.

## Enable Crash-Resistant Sessions With Infinite Session Mode

If you enable **infinite sessions** by passing `infiniteSessions: { enabled: true }` in the `SessionConfig`, the runtime continuously writes checkpoint data to `workspacePath/checkpoints/`. This provides automatic crash recovery without requiring an explicit call to `disconnect`. You still resume the session later using `client.resumeSession(...)`.

## Implement a Custom Session Filesystem for Advanced Workloads

When you need a non-standard directory layout—such as per-tenant isolation on a shared server—implement the `SessionFsProvider` interface and pass it via the `sessionFs` option or a `createSessionFsProvider` callback.

The SDK bridges your provider to the runtime by calling `createSessionFsAdapter` in [`nodejs/src/sessionFsProvider.ts`](https://github.com/github/copilot-sdk/blob/main/nodejs/src/sessionFsProvider.ts). Once registered, the runtime calls your `readFile`, `writeFile`, and other methods for all session-scoped I/O. Because the runtime uses your provider for both writing and reading, the exact same files are available when you later resume.

## Summary

- Call `session.disconnect()` to flush a session's in-memory history, plan, and workspace files to disk, as implemented in [`nodejs/src/session.ts`](https://github.com/github/copilot-sdk/blob/main/nodejs/src/session.ts).
- Reconnect later with `client.resumeSession(sessionId, config)`, defined in [`nodejs/src/client.ts`](https://github.com/github/copilot-sdk/blob/main/nodejs/src/client.ts), which restores the full state and re-attaches handlers.
- Default storage lives under `~/.copilot` (`COPILOT_HOME`), but you can override it with `baseDirectory` or a custom `SessionFsConfig`.
- Use **infinite session mode** for continuous checkpointing and crash resilience.
- For server or multi-tenant scenarios, implement `SessionFsProvider` to control exactly where session files live.

## Frequently Asked Questions

### Does the Copilot SDK auto-save session state when my process exits?

Not automatically on exit alone. The SDK writes state when `session.disconnect()` is called or when the session is disposed via `await using`. For crash protection without manual calls, enable `infiniteSessions: { enabled: true }` so the runtime continuously checkpoints to disk.

### Can I resume a session from a different machine or container?

Yes, as long as the new process can access the same on-disk store. Use the same `baseDirectory` or `sessionFs` configuration when constructing `CopilotClient`, then call `resumeSession(sessionId)` with the original ID. The runtime rehydrates the conversation from the shared path.

### What is the difference between `baseDirectory` and `sessionFs`?

`baseDirectory` is a convenience option that redirects the default `~/.copilot` root to another path. `sessionFs` is a full `SessionFsConfig` that lets you register a custom filesystem provider, giving you programmatic control over every file operation the runtime performs during the session lifecycle.

### Where can I find the on-disk workspace path for a specific session?

After creating or resuming a session, read the `workspacePath` getter on the `CopilotSession` object. This property is defined in [`nodejs/src/session.ts`](https://github.com/github/copilot-sdk/blob/main/nodejs/src/session.ts) and returns the absolute path to the session's files on disk.