# How External Agent Sessions Are Imported into Codex: A Technical Deep Dive

> Learn how Codex imports external agent sessions. Discover the migration payload, RPC process, and thread ID ledger in this technical deep dive into the openai/codex-plugin-cc repository.

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

---

**Codex imports external agent sessions by constructing a migration payload, sending it to the App Server via the `externalAgentConfig/import` RPC, and awaiting a completion notification before recording the thread ID in a local ledger.**

The `openai/codex-plugin-cc` repository implements a robust pipeline for migrating external agent conversations—specifically Claude sessions—into Codex's native thread format. Understanding how external agent sessions are imported into Codex requires examining the migration payload structure, the RPC communication protocol, and the persistent ledger system that tracks imported threads.

## Building the Migration Payload

The import process begins with constructing a structured payload that describes the external session files to transfer. In `plugins/codex/scripts/lib/codex.mjs`, the `externalAgentSessionMigration(sourcePath, cwd)` function (lines 81-98) generates a JSON object containing a `migrationItems` array.

Each migration item type is categorized as **SESSIONS**, specifying the absolute path to the Claude session file (`sourcePath`) and optionally the working directory (`cwd`) for context preservation. This payload serves as the canonical description of what data should migrate from the external agent into Codex.

```javascript
// From codex.mjs lines 81-98
const migrationPayload = externalAgentSessionMigration(
  "/path/to/claude-session.jsonl",  // The exported Claude conversation
  "/home/user/projects/demo"       // Optional working directory context
);

```

## Sending the Import Request via RPC

Once the payload is constructed, the system initiates asynchronous communication with the Codex App Server. The `requestExternalAgentSessionImport(client, params)` function (lines 101-130 in `codex.mjs`) handles this exchange using the `CodexAppServerClient` provided by `plugins/codex/scripts/lib/app-server.mjs`.

The function invokes `client.request("externalAgentConfig/import", params)` to transmit the migration payload. It simultaneously registers a temporary notification handler that listens for the `EXTERNAL_AGENT_IMPORT_COMPLETED` event (emitted as `externalAgentConfig/import/completed`). A timeout mechanism guards against hanging operations, rejecting the promise if the server fails to respond within the allocated window.

```javascript
// From codex.mjs lines 101-130
await requestExternalAgentSessionImport(codexClient, migrationPayload);

```

## Tracking Sessions in the Import Ledger

After successful import, Codex persists a mapping between the external source and the newly generated Codex thread. The ledger resides in [`external_agent_session_imports.json`](https://github.com/openai/codex-plugin-cc/blob/main/external_agent_session_imports.json) within the Codex home directory (`$CODEX_HOME` or `~/.codex`).

Each entry records the source file's absolute path and its SHA-256 hash, mapping these identifiers to the generated Codex thread ID. The `importedThreadIdForSource` function (lines 61-78 in `codex.mjs`) enables later retrieval of the thread ID using the original source file path, allowing users to resume imported sessions with `codex resume <thread-id>`.

```javascript
// From codex.mjs lines 61-78
const threadId = importedThreadIdForSource("/path/to/claude-session.jsonl");
console.log(`Resumable thread ID: ${threadId}`);

```

## Complete Import Workflow Example

The following implementation demonstrates the end-to-end flow for importing a Claude session into Codex, combining payload construction, RPC transmission, and thread retrieval:

```javascript
import { 
  externalAgentSessionMigration, 
  requestExternalAgentSessionImport, 
  importedThreadIdForSource 
} from "./plugins/codex/scripts/lib/codex.mjs";
import { CodexAppServerClient } from "./plugins/codex/scripts/lib/app-server.mjs";

// 1️⃣ Build the migration payload
const payload = externalAgentSessionMigration(
  "/exports/claude-session.jsonl",
  "/workspace/project"
);

// 2️⃣ Initialize the App Server client
const client = new CodexAppServerClient();

// 3️⃣ Send import request and await completion
await requestExternalAgentSessionImport(client, payload);

// 4️⃣ Retrieve the mapped Codex thread ID
const codexThread = importedThreadIdForSource("/exports/claude-session.jsonl");
console.log(`Import complete. Resume with: codex resume ${codexThread}`);

```

## Summary

- **Migration payloads** describe external sessions using the `SESSIONS` item type in `externalAgentSessionMigration`, specifying source paths and working directories.
- **RPC communication** utilizes the `externalAgentConfig/import` endpoint with completion signaled by the `EXTERNAL_AGENT_IMPORT_COMPLETED` notification event.
- **Timeout protection** prevents indefinite hangs during the import operation.
- **Persistent ledger** stores SHA-256 hashed source mappings in [`external_agent_session_imports.json`](https://github.com/openai/codex-plugin-cc/blob/main/external_agent_session_imports.json), enabling thread ID lookup via `importedThreadIdForSource`.
- **Integration** occurs through commands like `transfer`, which orchestrate the full pipeline from external agent export to resumable Codex thread.

## Frequently Asked Questions

### What RPC endpoint handles external agent session imports in Codex?

Codex uses the `externalAgentConfig/import` RPC endpoint to receive migration payloads. According to the source code in `plugins/codex/scripts/lib/codex.mjs`, the `requestExternalAgentSessionImport` function transmits the payload via `client.request("externalAgentConfig/import", params)` and awaits the `externalAgentConfig/import/completed` notification.

### How does Codex prevent duplicate imports of the same session?

The system tracks imported sessions using a ledger file ([`external_agent_session_imports.json`](https://github.com/openai/codex-plugin-cc/blob/main/external_agent_session_imports.json)) that stores the SHA-256 hash of the source file content alongside its absolute path. When checking for existing imports via `importedThreadIdForSource`, Codex verifies these identifiers to return the existing thread ID rather than creating duplicates.

### Where does Codex store the mapping between external sessions and Codex threads?

Codex persists the mapping in [`external_agent_session_imports.json`](https://github.com/openai/codex-plugin-cc/blob/main/external_agent_session_imports.json) located in the Codex home directory (`$CODEX_HOME` or `~/.codex`). This JSON ledger maps the external source file's path and hash to the generated Codex thread ID, enabling seamless resumption of imported conversations.

### What happens if the import request times out?

The `requestExternalAgentSessionImport` function implements a timeout guard that rejects the promise if the server fails to emit the `EXTERNAL_AGENT_IMPORT_COMPLETED` event within the expected timeframe. This prevents the client from hanging indefinitely during network interruptions or server-side failures.