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/projectsto 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
- User invokes:
codex transfer --source ~/myproject/session.jsonl - Command dispatcher routes to
executeTransfer() resolveClaudeSessionPath()validates the transcript locationimportExternalAgentSession()sends the migration request to the Codex app-server- App-server creates a new thread and returns the thread ID
- 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/projectsimportExternalAgentSession()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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →