How Session Transfer Works Between Claude Code and Codex

The codex transfer command migrates Claude Code session transcripts (.jsonl files) into new Codex threads by validating the source path, sending a migration request to the Codex app-server, and returning a resumable thread ID.

The openai/codex-plugin-cc repository enables seamless migration of conversation history from Claude Code to Codex through a structured session transfer protocol. This feature converts Claude's .jsonl transcript format into Codex-compatible threads, preserving visible turn history while allowing users to resume work in the Codex CLI.

The Session Transfer Pipeline

The transfer process follows a six-step pipeline orchestrated across three core modules. When a user executes codex transfer --source <path>, the companion script processes the Claude transcript through validation, import, and formatting stages.

Step 1: Path Resolution and Security Validation

In plugins/codex/scripts/lib/claude-session-transfer.mjs (lines 20-44), the resolveClaudeSessionPath() function performs security-critical path validation:

  • Expands ~ and relative path segments to absolute paths
  • Verifies the file extension is .jsonl
  • Ensures the resolved path lives within $HOME/.claude/projects to prevent directory traversal attacks

Step 2: Importing the Session into Codex

The importExternalAgentSession() function in plugins/codex/scripts/lib/codex.mjs (lines 58-70) handles the actual migration:

  • Validates that the Codex CLI is installed locally
  • Constructs a migration request containing the transcript path
  • Dispatches to requestExternalAgentSessionImport() to communicate with the Codex app-server

Step 3: Thread ID Extraction and Error Handling

After the app-server processes the import, the code in plugins/codex/scripts/lib/codex.mjs (lines 80-88):

  • Extracts the new thread ID using importedThreadIdForSource()
  • If extraction fails, raises detailed errors including stderr from Codex to diagnose version compatibility issues

Step 4: Result Formatting and User Output

The executeTransfer() function in plugins/codex/scripts/codex-companion.mjs (lines 25-38) packages the results:

  • Constructs the resume command: codex resume <thread-id>
  • Wraps the thread ID, source path, and command into a payload
  • renderTransferResult() (lines 16-22) generates the console output showing the Codex session ID and resume instructions

End-to-End Execution Flow

  1. User invokes: codex transfer --source ~/myproject/session.jsonl
  2. Command dispatcher routes to executeTransfer()
  3. resolveClaudeSessionPath() validates the transcript location
  4. importExternalAgentSession() sends the migration request to the Codex app-server
  5. App-server creates a new thread and returns the thread ID
  6. CLI displays the transfer confirmation with resume instructions

Implementation Examples

Programmatic Transfer

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

  return {
    threadId,
    resumeCommand: `codex resume ${threadId}`
  };
}

CLI Usage

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

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

Error Handling and Progress Reporting

Throughout the pipeline, emitProgress() reports status updates like "Importing Claude session" and "Claude session imported". When the RPC method externalAgentSessionImport is missing (indicating an outdated Codex version), the error message includes actionable hints to update the Codex CLI.

Summary

  • The session transfer between Claude Code and Codex operates through a four-step validation and import pipeline
  • resolveClaudeSessionPath() enforces security by restricting access to $HOME/.claude/projects
  • importExternalAgentSession() communicates with the Codex app-server via RPC to create new threads
  • The transfer preserves visible turn history and generates a codex resume <thread-id> command for continuity
  • Comprehensive error handling includes version compatibility checks and detailed stderr reporting

Frequently Asked Questions

What file format does Claude Code use for session transcripts?

Claude Code stores session history as .jsonl (JSON Lines) files within the $HOME/.claude/projects directory. The transfer tool specifically requires this extension and location to ensure compatibility and security.

Can I transfer sessions from outside the Claude projects directory?

No. The resolveClaudeSessionPath() function explicitly validates that the source path resides within $HOME/.claude/projects. This prevents directory traversal attacks and ensures the plugin only accesses legitimate Claude session files.

What happens if my Codex CLI is outdated?

If the Codex CLI lacks the externalAgentSessionImport RPC method, the import operation fails with a detailed error message. The error includes stderr output from Codex and suggests updating to the latest version to enable session transfer functionality.

Does the transfer delete the original Claude session?

No, the session transfer creates a copy of the conversation history in Codex. The original .jsonl transcript remains intact in the Claude projects directory, allowing you to reference or re-import the session if needed.

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 →