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

Session transfer between Claude Code and Codex works by persisting the Codex interaction history to a JSON transcript file that Claude later imports and restores as its own conversation state.

The openai/codex-plugin-cc repository implements this bidirectional handoff through a shared file-based protocol. Codex writes its session after each interaction, Claude reads that transcript when the user invokes the Transfer command, and both agents append updates to maintain continuity. This article breaks down the mechanism using the actual source code implementation.

How the Transcript Path Gets Resolved

Every session transfer starts with identifying where the transcript lives. The plugin uses resolveClaudeSessionPath in plugins/codex/scripts/lib/claude-session-transfer.mjs to determine this location.

The function checks three sources in order:

  1. TRANSCRIPT_PATH_ENV environment variable — highest priority override
  2. User-specified path via CLI flag (--session-path)
  3. Default workspace location (./.codex/session.json)
import { resolveClaudeSessionPath } from "./lib/claude-session-transfer.mjs";

const transcriptPath = resolveClaudeSessionPath(process.cwd(), {
  sessionPath: "./.codex/session.json",   // optional override
});

This resolution logic ensures flexibility. Developers can store transcripts alongside project files, in temporary directories, or in CI artifacts without hardcoding paths throughout the codebase.

Writing the Codex Session Transcript

Once the path is resolved, the Codex runtime serializes its full interaction state. This happens in plugins/codex/scripts/lib/state.mjs, where the session is converted to JSON containing:

  • Complete message history
  • Code snippets and tool outputs
  • Tool call metadata
// Persist the current session
await writeFile(transcriptPath, JSON.stringify(sessionState));

The write occurs after each significant operation, ensuring the transcript remains current if the user triggers a transfer mid-session.

Importing the Session into Claude Code

Claude's side of the transfer is handled by session-lifecycle-hook.mjs. When the user invokes the Transfer command, this hook:

  1. Resolves the same transcript path using resolveClaudeSessionPath
  2. Reads and parses the JSON content
  3. Reconstructs Claude's conversation state from the message array
import { resolveClaudeSessionPath } from "./lib/claude-session-transfer.mjs";

export async function importClaudeSession(cwd) {
  const path = resolveClaudeSessionPath(cwd);
  const content = await readFile(path, "utf-8");
  const session = JSON.parse(content);
  // Rebuild Claude's conversation from the transcript
  await claude.setConversation(session.messages);
}

This restoration is stateful — Claude continues the dialogue exactly where Codex left off, preserving context, file references, and prior reasoning.

Bidirectional Continuity

The session transfer is cyclical, not one-directional. After Claude completes its portion:

  • New messages are appended to the same transcript file
  • The updated transcript can be re-imported by Codex for subsequent operations
  • Both agents maintain synchronization through this single source of truth

This design avoids protocol complexity. There's no direct IPC, no network socket, and no shared memory — just a JSON file both tools can read and write.

Configuring the Transfer Environment

The plugin exposes two configuration mechanisms for controlling transcript behavior:

Method Implementation Use Case
Environment variable TRANSCRIPT_PATH_ENV in shell environment CI/CD pipelines, persistent workspace setups
CLI flag --session-path handled in plugins/codex/scripts/lib/args.mjs Ad-hoc transfers, temporary sessions

Example with environment variable:

export TRANSCRIPT_PATH_ENV=/tmp/shared-session.json
npx codex --plugin cc

Example with CLI flag:

npx codex --plugin cc --session-path ./sessions/feature-branch.json

Summary

  • resolveClaudeSessionPath in claude-session-transfer.mjs determines where the transcript lives using environment variables, CLI flags, or defaults
  • Codex writes its full session state to this JSON file via state.mjs after each interaction
  • Claude reads and restores the same transcript through session-lifecycle-hook.mjs when the Transfer command runs
  • Both agents append updates to maintain bidirectional continuity without direct communication
  • Configuration flexibility comes from the TRANSCRIPT_PATH_ENV variable and --session-path CLI argument parsed in args.mjs

Frequently Asked Questions

How does Claude access the Codex session without direct API communication?

Claude accesses the Codex session through a shared JSON transcript file, not through API calls. Codex writes its interaction history to this file, and Claude reads from the same location when importing. This file-based approach avoids network dependencies and makes the transfer mechanism portable across different environments.

What happens to the transcript file after Claude finishes its session?

New messages from Claude's session are appended to the same transcript file. This updated file can then be re-imported by Codex, creating a continuous loop where both agents contribute to and read from a single conversation history. The transcript serves as the persistent source of truth for the entire collaborative session.

Can multiple Codex sessions point to the same transcript?

Yes, by configuring TRANSCRIPT_PATH_ENV or --session-path to the same location. However, concurrent writes from multiple Codex processes would corrupt the transcript. The plugin assumes single-writer semantics — design your workflow so only one agent writes at a time, or implement external locking if parallel access is required.

Where is the Transfer command documented for end users?

User-facing documentation for the Transfer command resides in plugins/codex/commands/transfer.md. This file explains how to invoke the command, what prerequisites exist for the transcript file, and any limitations or edge cases users should understand when handing off between Claude Code and Codex.

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 →