# How Thread Persistence and Resume Functionality Work in Codex

> Learn how Codex implements thread persistence and resume functionality. Discover how to save and restart conversational sessions with ephemeral set to false for durable state.

- Repository: [OpenAI/codex-plugin-cc](https://github.com/openai/codex-plugin-cc)
- Tags: internals
- Published: 2026-07-10

---

**Codex enables durable conversational state by storing threads on the server with the `ephemeral` flag set to `false`, allowing users to resume any session using `--resume-last` or explicit `codex resume <thread-id>` commands.**

The **openai/codex-plugin-cc** repository implements a persistent thread model that lets developers start long-running tasks, exit the CLI, and later resume exactly where they left off. This article explains the underlying mechanics of thread persistence and resume functionality in Codex, referencing the actual source implementation in the companion scripts.

## Starting a Persistent Thread

When you initiate a task that needs to survive beyond the current CLI session, the companion script invokes `runAppServerTurn` with `persistThread: true`. According to the source code in `codex-companion.mjs`, this flag determines whether the thread survives after the turn completes.

The `startThread` function in `plugins/codex/scripts/lib/codex.mjs` handles the actual creation. It sets the **ephemeral** flag to `false` when persistence is requested, ensuring the thread is stored on the Codex server rather than discarded:

```js
// plugins/codex/scripts/lib/codex.mjs
const response = await client.request("thread/start", buildThreadParams(cwd, {
  model,
  sandbox,
  // Non-ephemeral when persisting
  ephemeral: options.persistThread ? false : true,
  threadName: options.persistThread ? options.threadName : options.threadName ?? null
}));

```

A **thread ID** is generated server-side, and if a custom name is provided, the script calls `thread/name/set` to store it. This ID serves as the durable reference for all future resume operations.

## Resuming a Saved Thread

Codex provides two primary mechanisms for resuming conversations: automatic resolution of the latest thread or explicit resumption via thread ID.

### Automatic Resolution with `--resume-last`

When you pass the `--resume-last` flag (or `--resume`), the companion script calls `resolveLatestTrackedTaskThread` to locate the most recent tracked task. It extracts the `id` from that task record and passes it as `resumeThreadId` to `runAppServerTurn`.

### The Resume Request Flow

Inside `runAppServerTurn`, the presence of `options.resumeThreadId` triggers a call to `resumeThread`, which sends a `thread/resume` request built by `buildResumeParams`:

```js
// plugins/codex/scripts/lib/codex.mjs
async function resumeThread(client, threadId, cwd, options = {}) {
  return client.request("thread/resume", buildResumeParams(threadId, cwd, options));
}

```

This reattaches your CLI session to the existing server-side thread, preserving all previous context, file states, and conversation history.

## Generating Resume Commands in Output

Every task result rendered to your terminal includes a copy-pasteable resume command. The rendering helpers in `plugins/codex/scripts/lib/render.mjs` extract the `threadId` from either a stored job or the current job object, then compute the resume instruction:

```js
// plugins/codex/scripts/lib/render.mjs
const threadId = storedJob?.threadId ?? job.threadId ?? null;
const resumeCommand = threadId ? `codex resume ${threadId}` : null;
// ...
lines.push(`Codex session ID: ${threadId}`);
lines.push(`Resume in Codex: ${resumeCommand}`);

```

This ensures you can always recover your session even if you did not note the thread ID manually.

## Practical CLI Workflow

The persistence system supports three common developer workflows:

1. **Start a persistent task**: Creates a non-ephemeral thread and prints the resume command.
   
   ```bash
   codex task --write "Implement feature X"
   # Output includes:

   # Codex session ID: thr_abc123

   # Resume in Codex: codex resume thr_abc123

   ```

2. **Resume the latest task automatically**: The CLI auto-detects the most recent thread and continues the conversation.
   
   ```bash
   codex task --resume-last "Refactor to use async I/O"
   ```

3. **Manually resume a specific thread**: Use the exact command printed in step 1 to re-enter any previous session.
   
   ```bash
   codex resume thr_abc123
   ```

## Summary

- **Thread persistence** is controlled by the `ephemeral` flag in `buildThreadParams`; setting it to `false` stores the thread on Codex's servers.
- **Resume functionality** relies on `thread/resume` requests sent via `resumeThread` in `codex.mjs`, using IDs resolved either automatically (`--resume-last`) or manually.
- **Resume commands** are dynamically generated in `render.mjs` and appended to every task output, ensuring users can always recover their session.
- The implementation spans `codex-companion.mjs` (CLI handling), `codex.mjs` (core logic), and `render.mjs` (output formatting), with comprehensive test coverage in `tests/runtime.test.mjs`.

## Frequently Asked Questions

### How does Codex store thread state between CLI invocations?

Codex stores the conversation state on its servers, not locally. When `persistThread: true` is passed to `startThread`, the `ephemeral` parameter is set to `false` in the `thread/start` request. This instructs the Codex backend to retain the thread indefinitely, allowing it to be retrieved later via the `thread/resume` endpoint using the unique thread ID.

### What is the difference between `--resume-last` and a manual `codex resume` command?

The `--resume-last` flag triggers automatic resolution via `resolveLatestTrackedTaskThread`, which scans tracked tasks to find the most recent thread ID and immediately resumes it. In contrast, `codex resume <thread-id>` requires you to provide the specific thread ID manually, which is useful when you want to return to an older conversation rather than the most recent one.

### Where in the codebase is the "Resume in Codex" output generated?

The resume instruction is constructed in `plugins/codex/scripts/lib/render.mjs` within the result rendering helpers (such as `renderStoredJobResult` and `renderTaskResult`). These functions extract the `threadId` from the job object, construct the command string `` `codex resume ${threadId}` ``, and append it to the terminal output alongside the session ID.

### Can I resume a thread after completely closing my terminal?

Yes. Because persistent threads are stored server-side with `ephemeral: false`, they survive terminal closures, system restarts, and network changes. As long as you have the thread ID (from previous output or the `codex resume` command shown in your history), you can reconnect to the exact same conversation state from any new terminal session.