How Session Transfer Between Claude Code and Codex Works: A Technical Deep Dive

Session transfer between Claude Code and Codex converts Claude's .jsonl transcript files into new Codex threads using the codex transfer CLI command, which validates paths, imports via the Codex app-server RPC method externalAgentSessionImport, and returns a resumable thread ID.

The openai/codex-plugin-cc repository enables seamless migration of conversation history from Claude Code to OpenAI's Codex CLI. This session transfer functionality allows developers to preserve context when switching between AI coding assistants by converting Claude's transcript format into Codex-compatible threads through a secure, validated pipeline.

The Session Transfer Pipeline

When a user runs codex transfer, the plugin executes a six-step pipeline that moves a Claude session into a new Codex thread. Each stage performs specific validation and transformation tasks.

Step 1: Path Resolution and Validation

The process begins with resolveClaudeSessionPath() in plugins/codex/scripts/lib/claude-session-transfer.mjs. This function expands ~ and relative paths, verifies the file ends with .jsonl, and enforces a critical security constraint: the transcript must live inside the Claude projects directory ($HOME/.claude/projects). This prevents arbitrary file access outside the expected scope.

Step 2: App-Server Import Request

The importExternalAgentSession() function in plugins/codex/scripts/lib/codex.mjs handles the actual migration. It first validates that the Codex CLI is installed, then constructs a migration request calling requestExternalAgentSessionImport(). This RPC method transmits the transcript path to the Codex app-server for processing.

Step 3: Thread ID Extraction and Error Handling

After the app-server processes the import, the code extracts the newly created thread ID via importedThreadIdForSource(). If the ID cannot be found, the function raises a detailed error including any stderr from Codex, providing actionable hints such as updating the Codex CLI if the externalAgentSessionImport RPC method is missing.

Step 4: Result Aggregation and Command Generation

The executeTransfer() function in plugins/codex/scripts/codex-companion.mjs orchestrates the workflow. It wraps the thread ID, generates a resume command (codex resume <thread-id>), and bundles the original source path into a payload object for the CLI.

Step 5: User Output Rendering

Finally, renderTransferResult() (also in codex-companion.mjs) transforms the technical payload into a human-readable message. Throughout the pipeline, emitProgress() reports status updates such as "Importing Claude session" and "Claude session imported" to the console.

Implementing Session Transfer Programmatically

You can invoke the transfer logic manually using the same functions the CLI calls internally.

Manual Transfer Implementation

import { resolveClaudeSessionPath } from "./plugins/codex/scripts/lib/claude-session-transfer.mjs";
import { importExternalAgentSession } from "./plugins/codex/scripts/lib/codex.mjs";

async function transferClaudeSession(cwd, source) {
  // Step 1 – Resolve & validate the transcript path
  const transcriptPath = resolveClaudeSessionPath(cwd, { source });

  // Step 2 – Ask Codex to import the transcript
  const { threadId } = await importExternalAgentSession(cwd, {
    sourcePath: transcriptPath,
    // optional progress callback
    onProgress: (msg, state) => console.log(`[${state}] ${msg}`)
  });

  // Step 3 – Return a ready-to-run resume command
  return {
    threadId,
    resumeCommand: `codex resume ${threadId}`
  };
}

// Example usage
(async () => {
  const cwd = process.cwd();
  const result = await transferClaudeSession(cwd, "~/myproject/session.jsonl");
  console.log(`✅ Imported, resume with: ${result.resumeCommand}`);
})();

CLI Usage

For standard command-line transfers, the user simply specifies the source transcript:

codex transfer --source ~/myproject/session.jsonl

Behind the scenes, this executes executeTransfer() in plugins/codex/scripts/codex-companion.mjs with the provided source path.

Key Source Files and Architecture

The session transfer feature spans three primary modules:

  • plugins/codex/scripts/lib/claude-session-transfer.mjs: Handles path expansion, .jsonl extension validation, and security checks ensuring transcripts reside within $HOME/.claude/projects.

  • plugins/codex/scripts/lib/codex.mjs: Implements the Codex app-server client, including importExternalAgentSession() and the externalAgentSessionImport RPC integration.

  • plugins/codex/scripts/codex-companion.mjs: CLI entry point containing executeTransfer() and renderTransferResult() for orchestrating the workflow and formatting output.

Summary

  • Strict path validation ensures transcript files are .jsonl format and reside within the Claude projects directory before processing.
  • RPC-based import uses the externalAgentSessionImport method to communicate with the Codex app-server, creating a new thread from the transcript.
  • Automatic thread recovery extracts the new thread ID via importedThreadIdForSource() and generates the codex resume <thread-id> command.
  • Comprehensive error handling provides specific guidance when the Codex CLI is outdated or when transcripts are inaccessible.
  • Modular architecture separates path resolution, server communication, and CLI presentation into distinct, testable modules.

Frequently Asked Questions

What file format does Claude Code use for sessions?

Claude Code stores session history as .jsonl (JSON Lines) transcript files. The resolveClaudeSessionPath() function explicitly checks for this extension and rejects other formats before attempting transfer.

Can I transfer sessions from any directory on my system?

No. The security model in claude-session-transfer.mjs restricts transfers to files within $HOME/.claude/projects. This prevents the plugin from accessing arbitrary files outside the Claude Code workspace, ensuring transcripts can only be migrated from approved locations.

What happens if my Codex CLI version doesn't support session import?

The importExternalAgentSession() function detects missing RPC methods and throws an error indicating that the externalAgentSessionImport method is unavailable. The error message specifically suggests updating the Codex CLI to the latest version to enable this functionality.

How do I resume a transferred session in Codex?

After successful transfer, the CLI outputs a resume command: codex resume <thread-id>. You can execute this command immediately to continue the conversation in Codex with full access to the imported turn history from Claude Code.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →