How to Transfer a Claude Code Session to Codex and Resume It There

Run /codex:transfer inside Claude Code to convert the active JSONL transcript into a resumable Codex thread, then use the printed codex resume <threadId> command to pick up where you left off.

The openai/codex-plugin-cc repository ships a built-in session-transfer mechanism that migrates Claude Code conversation history into Codex format without exposing API secrets. This workflow reads your local Claude transcript files and creates a matching Codex thread that preserves the entire turn-by-turn context.

How the Session Transfer Architecture Works

The transfer process is completely internal to the plugin—no network requests transmit your Claude data to external services during the conversion.

CLI Entry Point and Command Parsing

The codex-companion.mjs script exposes the transfer subcommand through its handleTransfer function. When you invoke /codex:transfer or run the companion CLI directly, the script parses arguments at lines 24‑31 in plugins/codex/scripts/codex-companion.mjs and routes them to the execution pipeline.

Validating the Claude Transcript Path

Before importing history, resolveClaudeSessionPath validates that the supplied --source path (or the CODEX_COMPANION_TRANSCRIPT_PATH environment variable) points to a valid JSONL file inside ~/.claude/projects. This check occurs at lines 20‑44 in plugins/codex/scripts/lib/claude-session-transfer.mjs, ensuring the plugin only ingests legitimate Claude session files.

Converting History to a Codex Thread

The core import logic resides in importExternalAgentSession within plugins/codex/scripts/lib/codex.mjs. This function reads the validated JSONL transcript and generates a new Codex thread that mirrors each conversational turn from Claude Code. The companion script calls this logic at lines 25‑30 of codex-companion.mjs, capturing the resulting thread metadata for display.

Environment Propagation for Resumed Sessions

After successful transfer, session-lifecycle-hook.mjs propagates session identifiers to downstream processes. Lines 77‑81 set CODEX_COMPANION_SESSION_ID and CODEX_COMPANION_TRANSCRIPT_PATH as environment variables, ensuring subsequent Codex commands in the same shell session automatically reference the transferred Claude context.

Step-by-Step: Transferring Your Claude Code Session

Using the Built-In Command

From any directory within your Claude Code workspace, execute the transfer command:

/codex:transfer

This locates the active session transcript in ~/.claude/projects and outputs a human-readable result via renderTransferResult (lines 16‑23 in codex-companion.mjs):


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

For programmatic consumption, request JSON output:

/codex:transfer --json

Running the CLI Directly

You can invoke the underlying Node script explicitly with a specific source path:

node plugins/codex/scripts/codex-companion.mjs transfer \
  --source ~/.claude/projects/my-project/session-001.jsonl \
  --json

The command returns a JSON payload:

{
  "threadId": "12345-abcd-ef01",
  "resumeCommand": "codex resume 12345-abcd-ef01",
  "sourcePath": "/home/you/.claude/projects/my-project/session-001.jsonl",
  "sessionId": "session-001"
}

Programmatic Session Transfer

Embed the transfer logic in your own Node.js tooling by importing the core functions:

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

async function transferClaudeToCodex(cwd, source) {
  const sourcePath = resolveClaudeSessionPath(cwd, { source });
  const { threadId, resumeCommand } = await importExternalAgentSession(cwd, { sourcePath });
  console.log(`Codex thread ${threadId} created – resume with: ${resumeCommand}`);
}

This approach gives you fine-grained control over the working directory (cwd) and source selection while maintaining the same validation and thread-creation logic used by the CLI.

Verifying the Transfer State

After running the transfer, confirm the session context is active by checking your environment:

echo $CODEX_COMPANION_SESSION_ID
echo $CODEX_COMPANION_TRANSCRIPT_PATH

The first variable contains the Claude session identifier, while the second points to the exact JSONL file consumed during transfer. These values persist for the lifetime of your shell session, allowing seamless handoff between Claude Code and Codex.

Summary

  • Command: Use /codex:transfer inside Claude Code or run codex-companion.mjs transfer from the shell to initiate migration.
  • Validation: The plugin enforces that source transcripts reside within ~/.claude/projects via resolveClaudeSessionPath.
  • Core Logic: importExternalAgentSession in lib/codex.mjs handles the JSONL-to-Codex-thread conversion.
  • Resume: The output provides a codex resume <threadId> command that restores your conversation history.
  • State: Environment variables CODEX_COMPANION_SESSION_ID and CODEX_COMPANION_TRANSCRIPT_PATH maintain session continuity across tools.

Frequently Asked Questions

Where does the Claude Code transcript come from?

Claude Code writes conversation history to JSONL files inside ~/.claude/projects/<project-name>/. The transfer command automatically resolves the active session path, or you can specify a file explicitly using the --source flag when running the companion CLI directly.

Is the transfer process secure?

Yes. According to the openai/codex-plugin-cc source code, all processing happens locally on your machine. The handleTransfer function in codex-companion.mjs performs filesystem operations only, and no Claude session data is transmitted over the network until you actively invoke the Codex service using the generated resume command.

Can I transfer multiple sessions at once?

The current implementation processes one transcript per invocation. Each call to executeTransfer creates a single Codex thread from one JSONL source. To migrate multiple sessions, run the transfer command sequentially or script the importExternalAgentSession function in a loop with different source paths.

What happens if the transcript path is invalid?

resolveClaudeSessionPath throws a validation error if the supplied path is not a JSONL file or resides outside the ~/.claude/projects directory. The CLI catches this error and exits with a non-zero status, preventing the creation of empty or corrupted Codex threads.

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 →