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

> Explore how session transfer between Claude Code and Codex works. Learn how JSON transcripts enable seamless conversation state restoration in this technical deep dive.

- Repository: [OpenAI/codex-plugin-cc](https://github.com/openai/codex-plugin-cc)
- Tags: deep-dive
- Published: 2026-08-05

---

**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`](https://github.com/openai/codex-plugin-cc/blob/main/./.codex/session.json))

```javascript
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

```javascript
// 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

```javascript
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:

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

```

Example with CLI flag:

```bash
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`](https://github.com/openai/codex-plugin-cc/blob/main/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.