How Session Transfer Between Claude Code and Codex Works: Complete Pipeline Guide

The codex transfer command imports Claude Code conversation transcripts into Codex by validating .jsonl file paths and communicating with the Codex app-server to create a resumable thread with full history.

The openai/codex-plugin-cc repository implements a seamless migration path for developers switching from Claude Code to OpenAI Codex. This session transfer process preserves your conversation context by converting Claude transcript files into native Codex threads through a six-step validation and import pipeline.

The Session Transfer Pipeline

When you execute codex transfer --source path/to/session.jsonl, the system processes your request through a well-defined pipeline implemented across three core modules.

Validating Claude Session Paths

The transfer begins in plugins/codex/scripts/lib/claude-session-transfer.mjs where resolveClaudeSessionPath() performs strict validation. This function expands ~ aliases and relative paths, verifies the file ends with .jsonl, and guarantees the path lives inside the Claude projects directory ($HOME/.claude/projects). Any attempt to access files outside this scope is rejected immediately.

Importing via the Codex App-Server

Once validated, the importExternalAgentSession() function in plugins/codex/scripts/lib/codex.mjs handles the core migration logic. First, it confirms the Codex CLI is installed locally. Then it calls requestExternalAgentSessionImport() with a migration request containing the transcript path. This RPC method communicates with the Codex app-server to ingest the conversation history.

Thread ID Extraction and Response Handling

After the app-server processes the import, importedThreadIdForSource() extracts the newly created thread ID from the response. If the ID cannot be found, the system raises a detailed error that includes stderr output from Codex, helping diagnose version mismatches or connectivity issues.

Result Formatting and CLI Output

The executeTransfer() function in plugins/codex/scripts/codex-companion.mjs orchestrates the final output. It wraps the thread ID, generates the resume command (codex resume <thread-id>), and packages the original source path into a payload. Finally, renderTransferResult() converts this data into a human-readable console message showing the Codex session ID and the exact command needed to resume work.

Progress Reporting and Error Handling

Throughout execution, emitProgress() reports real-time status updates such as "Importing Claude session" and "Claude session imported". Errors are enriched with actionable hints—for example, if the RPC method externalAgentSessionImport is missing, the system prompts you to update Codex to the latest version.

Implementation: Key Functions and File Paths

The session transfer relies on specific functions across three primary files:

  • plugins/codex/scripts/lib/claude-session-transfer.mjs: Contains resolveClaudeSessionPath() for path validation and security checks
  • plugins/codex/scripts/lib/codex.mjs: Implements importExternalAgentSession() and importedThreadIdForSource() for app-server communication
  • plugins/codex/scripts/codex-companion.mjs: Entry point with executeTransfer() and renderTransferResult() for CLI orchestration

Usage Examples

Command Line Interface

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

This triggers the full pipeline and outputs:


Transferred the Claude session into a Codex thread with visible turn history.
Codex session ID: 12345-abcde
Resume in Codex: codex resume 12345-abcde

Programmatic Implementation

You can invoke the same logic programmatically using the internal modules:

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,
    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}`);
})();

Error Handling and Safety Checks

The system enforces strict security boundaries during session transfer. The transcript must reside within $HOME/.claude/projects to prevent arbitrary file access. If the Codex CLI is outdated and lacks the externalAgentSessionImport RPC method, the error handler identifies the missing capability and instructs you to update Codex. All stderr output from the Codex process is captured and included in error messages to facilitate debugging.

Summary

  • Session transfer migrates Claude Code .jsonl transcripts into Codex threads via the codex transfer command
  • Path validation ensures transcripts originate from $HOME/.claude/projects and use the .jsonl extension
  • Core functions include resolveClaudeSessionPath(), importExternalAgentSession(), and executeTransfer()
  • Resume capability generates a codex resume <thread-id> command to continue the imported session
  • Error handling provides actionable hints for missing RPC methods or path violations

Frequently Asked Questions

What file format does Claude Code use for session transcripts?

Claude Code stores conversation history as .jsonl (JSON Lines) files. The session transfer process specifically requires this format and validates the file extension before processing. Each line contains a JSON object representing a single turn in the conversation.

Can I transfer sessions from any directory on my system?

No. For security reasons, resolveClaudeSessionPath() restricts transfers to files located within $HOME/.claude/projects. The function expands ~ and relative paths but throws an error if the resolved path falls outside the Claude projects directory, preventing arbitrary file access.

What happens if my Codex version is too old to support session transfer?

If the Codex CLI lacks the externalAgentSessionImport RPC method, importExternalAgentSession() captures the error and returns a detailed message instructing you to update Codex to the latest version. The error includes stderr output from the Codex process to help identify version mismatches.

Is the conversation history visible after transfer?

Yes. Once imported, the entire conversation history becomes visible as a turn history in the new Codex thread. The system creates a native Codex thread with the imported content, allowing you to resume work with full context using the codex resume <thread-id> command.

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 →