How to Import External Agent Sessions into Codex: Step-by-Step Process
Codex imports external agent sessions by constructing a JSON migration payload that describes the session files and sending it to the Codex App Server via the externalAgentConfig/import RPC, then persisting the source-to-thread mapping in a local ledger file.
The openai/codex-plugin-cc repository provides the tooling necessary to migrate external agent conversations—such as Claude sessions—into Codex as first-class threads. When you import external agent sessions into Codex, the system generates a structured migration payload, communicates with the App Server through specific RPC endpoints, and maintains a persistent ledger that maps source file hashes to generated thread IDs.
Step 1: Build the Migration Payload with externalAgentSessionMigration
The import process begins in plugins/codex/scripts/lib/codex.mjs with the externalAgentSessionMigration function (lines 81–98). This helper accepts a sourcePath pointing to the external session file and an optional cwd parameter specifying the working directory.
The function returns a JSON object containing a migrationItems array. Each item specifies:
type: Set toSESSIONSto indicate a session migrationsourcePath: Absolute path to the external agent session file (e.g., a Claude export)cwd: Optional working directory context
import { externalAgentSessionMigration } from './plugins/codex/scripts/lib/codex.mjs';
const payload = externalAgentSessionMigration(
"/path/to/claude-session.jsonl",
"/home/user/project"
);
// payload.migrationItems[0] = { type: "SESSIONS", sourcePath: "...", cwd: "..." }
Step 2: Send the Import Request via requestExternalAgentSessionImport
Once the payload is ready, the requestExternalAgentSessionImport function (lines 101–130 in codex.mjs) handles server communication. This helper requires a CodexAppServerClient instance (provided by plugins/codex/scripts/lib/app-server.mjs) and the migration parameters.
The function transmits the payload using client.request("externalAgentConfig/import", params). Simultaneously, it registers a temporary notification listener that awaits the externalAgentConfig/import/completed event, referenced by the constant EXTERNAL_AGENT_IMPORT_COMPLETED.
A timeout mechanism guards against hanging operations, rejecting the promise if the server fails to respond within the threshold.
import { requestExternalAgentSessionImport } from './plugins/codex/scripts/lib/codex.mjs';
import { CodexAppServerClient } from './plugins/codex/scripts/lib/app-server.mjs';
const client = new CodexAppServerClient();
await requestExternalAgentSessionImport(client, payload);
Step 3: Wait for Server Completion
After transmitting the request, the import flow enters a blocking wait state (lines 121–128). The function returns a promise that resolves only when the server emits the completion notification. Upon successful resolution, the import is confirmed; if the timeout elapses first, the function throws an error to prevent indefinite blocking.
Step 4: Record and Retrieve the Imported Thread
Following successful import, Codex records a ledger entry in external_agent_session_imports.json, located in the Codex home directory ($CODEX_HOME or ~/.codex). According to the source code in codex.mjs (lines 61–78), this ledger maps the source file's absolute path and its SHA‑256 hash to the newly generated Codex thread ID.
To retrieve the thread ID later, use the importedThreadIdForSource function:
import { importedThreadIdForSource } from './plugins/codex/scripts/lib/codex.mjs';
const threadId = importedThreadIdForSource("/path/to/claude-session.jsonl");
console.log(`Resumable Codex thread: ${threadId}`);
Integration with the Transfer Command
Higher-level workflows, such as the codex transfer command documented in plugins/codex/commands/transfer.md, orchestrate these steps automatically. The claude-session-transfer.mjs module defines environment variables like TRANSCRIPT_PATH_ENV that facilitate the export/import pipeline, enabling users to run codex transfer and then codex resume <thread-id> to continue migrated sessions.
Key Implementation Files
plugins/codex/scripts/lib/codex.mjs– ContainsexternalAgentSessionMigration,requestExternalAgentSessionImport, and ledger handling logic (importedThreadIdForSource)plugins/codex/scripts/lib/app-server.mjs– ProvidesCodexAppServerClientfor RPC communicationplugins/codex/scripts/lib/claude-session-transfer.mjs– Defines environment variables for Claude session export pathsplugins/codex/commands/transfer.md– User-facing documentation for the transfer commandtests/fake-codex-fixture.mjs– Test fixture validating the ledger file structure and import flow
Summary
- Build a migration payload using
externalAgentSessionMigrationwith the source file path and optional working directory. - Transmit the payload via
requestExternalAgentSessionImport, which calls theexternalAgentConfig/importRPC and listens for theEXTERNAL_AGENT_IMPORT_COMPLETEDevent. - Handle timeouts with built-in promise-based guards that prevent indefinite waits.
- Record successful imports in
~/.codex/external_agent_session_imports.json, which stores SHA‑256 hashes mapped to Codex thread IDs. - Retrieve thread IDs using
importedThreadIdForSourceto resume imported sessions with standard Codex commands.
Frequently Asked Questions
What RPC endpoint does Codex use to import external agent sessions?
Codex uses the externalAgentConfig/import RPC endpoint to initiate the migration. As implemented in plugins/codex/scripts/lib/codex.mjs, the client sends the migration payload to this endpoint and listens for the externalAgentConfig/import/completed notification to confirm success.
Where does Codex store the mapping between imported sessions and thread IDs?
Codex maintains a ledger file named external_agent_session_imports.json in the Codex home directory ($CODEX_HOME or ~/.codex). This JSON file maps the absolute path and SHA‑256 hash of the source session file to the corresponding Codex thread ID generated during import.
How does Codex prevent import operations from hanging indefinitely?
The requestExternalAgentSessionImport function implements a timeout guard around the promise that awaits the externalAgentConfig/import/completed notification. If the server fails to emit the completion event within the timeout window, the function throws an error, aborting the operation rather than blocking indefinitely.
Can I import sessions from agents other than Claude?
While the current implementation in openai/codex-plugin-cc specifically targets Claude sessions via the SESSIONS migration type and helper modules like claude-session-transfer.mjs, the underlying architecture using externalAgentConfig/import is generic. Any external agent that exports conversation data in a compatible format could theoretically be imported using the same migration payload structure.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →