Skip to content

feat: add /codex:transfer for Claude Code session handoff - #374

Merged
dkundel-openai merged 1 commit into
mainfrom
codex/claude-session-transfer
Jun 23, 2026
Merged

feat: add /codex:transfer for Claude Code session handoff#374
dkundel-openai merged 1 commit into
mainfrom
codex/claude-session-transfer

Conversation

@stefanstokic-oai

Copy link
Copy Markdown
Contributor

Description

Adds /codex:transfer to import the current Claude Code session into a persistent Codex thread and print the corresponding codex resume <thread-id> command.

The command reuses Codex's native external-agent session importer so transferred conversations follow the same conversion rules and produce the same visible turn history as Codex App imports. The existing SessionStart hook captures Claude's transcript path automatically, with --source <claude-jsonl> available as a manual override.

Includes compatibility handling for unsupported Codex versions, clear import-failure errors, documentation, and test coverage. Validated with npm test (90 tests) and npm run build.

@stefanstokic-oai
stefanstokic-oai marked this pull request as ready for review June 15, 2026 00:03
@stefanstokic-oai
stefanstokic-oai requested a review from a team June 15, 2026 00:03

@dkundel-openai dkundel-openai left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed locally: npm test (90 tests), npm run build, and a live happy-path transfer all pass. The completion-protocol hardening can follow separately.

@dkundel-openai
dkundel-openai merged commit 430e2a8 into main Jun 23, 2026
1 check passed
kingdoooo added a commit to kingdoooo/codex-plugin-cc that referenced this pull request Jun 26, 2026
Brings in upstream openai#374 (Claude session transfer) and openai#398 (version bump).
The only conflict was in plugins/codex/scripts/lib/codex.mjs: openai#374 added the
EXTERNAL_AGENT_IMPORT_* constants in the same location as this branch's
turn-idle-timeout / inferred-completion block. Both features are unrelated;
resolved additively by keeping both.
Jafee added a commit to Jafee/codex-plugin-cc-stable that referenced this pull request Jul 3, 2026
…ings

Net diff 807e03a..80c31f9 (openai#374 + openai#398) re-landed as a clean commit per the
fork's merge policy: /transfer imports the current Claude transcript into a
resumable Codex thread via externalAgentConfig/import, the SessionStart hook
exports CODEX_COMPANION_TRANSCRIPT_PATH, app-server exit errors carry stderr,
initialize advertises requestAttestation: false, and buildThreadParams drops
experimentalRawEvents. Command docs and tests renamed to /codex-stable:*.

Fork deviations from upstream, from the dual audit (Fable + Codex gpt-5.5
xhigh, which flagged two of these on the upstream diff):
- request() accepts a bounded per-call timeoutMs override and the import RPC
  uses the same 2-minute ceiling as the completion wait, so a never-answered
  import request cannot hang the transfer and skip client teardown (our openai#302
  wall-clock timeout would otherwise cut large imports off at 30s).
- importedThreadIdForSource() re-verifies that the validated canonical source
  path still resolves to itself before hashing, closing the ledger-side
  TOCTOU window when the file is swapped after validation.
- handleTransfer resolves --cwd with requireExists, matching the fork's
  fail-fast rule for commands that start Codex work.

Known limitation (accepted, LOW): a transcript that grows between Codex's
import read and the ledger lookup fails the content-hash match and reports
"did not record an imported thread"; retrying is safer than silently
resuming an older imported thread.

Co-authored-by: stefanstokic-oai <stefanstokic@openai.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017FLdF7gB8iPZf1eKF1WMYt

@arfter69-debug arfter69-debug left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Vc

aihuangjun pushed a commit to aihuangjun/codex-plugin-cc that referenced this pull request Jul 5, 2026
… 2.0.x fork

Port the /codex:transfer feature from openai/codex-plugin-cc 1.0.5 without
taking upstream's 1.0.5 version bump. Dropped upstream runAppServerReview
(this fork uses its own review path); kept importExternalAgentSession and
adapted README + command-sync test to the fork's structure.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
patriyang added a commit to patriyang/codex-plugin-cc that referenced this pull request Jul 7, 2026
)

Merges the 2 commits our fork was behind `openai/codex-plugin-cc:main`:

- `430e2a8` feat: add Claude session transfer command (openai#374) — new
`/codex:transfer` command that imports the current Claude Code session
into a resumable Codex thread (via Codex's external-agent session
importer).
- `80c31f9` fix: bump plugin version to 1.0.5 (openai#398).

## Conflict resolution
- **Versions** (`marketplace.json`, `package.json`, `package-lock.json`,
`plugin.json`): kept our higher `1.0.8` and bumped to **`1.0.9`** for
the new command; discarded upstream's lower `1.0.5`.
- **README**: merged both — kept our `/codex:deep-review` +
`/codex:implement` sections and added the upstream `/codex:transfer`
section.
- **`codex.mjs`**: auto-merged cleanly. Both our
`resolveWorktreeWritableRoots` worktree logic and the new
`importExternalAgentSession` / `withDirectAppServer` transfer code
coexist; the transfer commit's removal of `experimentalRawEvents`
carried through.

## Verification
- `npm test` → **101/101 pass**.
- New files present: `commands/transfer.md`,
`scripts/lib/claude-session-transfer.mjs`.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: stefanstokic-oai <stefanstokic@openai.com>
Co-authored-by: Dominik Kundel <dkundel@openai.com>
Crazytieguy added a commit to Crazytieguy/codex-plugin-cc that referenced this pull request Jul 9, 2026
…ture

Adopted:
- Remove shell expansion for git commands (upstream openai#447): git spawns now
  pass shell: false via an options.shell passthrough in lib/process.mjs
  and tests/helpers.mjs, composed with our resolveWindowsShell() on win32.
  Includes upstream's regression test for branch names with shell
  metacharacters.
- app-server.mjs: append captured stderr to "app-server exited
  unexpectedly" errors.

Rejected:
- /codex:transfer Claude-session-to-Codex-thread feature (upstream openai#374):
  transferring Claude-generated assistant turns into a Codex thread puts
  Codex out of distribution; also couples to Codex's private import ledger.
  All transfer code, command, protocol types, fixtures, and tests dropped.
- Upstream version bumps and identity churn (package.json, marketplace,
  plugin.json, README) per fork policy.

Post-merge fixes:
- Dropped upstream's requestAttestation: false capability — the checked-in
  generated InitializeCapabilities type doesn't define it, so it broke the
  tsc build (found by Codex review).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LE4prC9U5Snku24TXbUfYr
zknpr added a commit to zknpr/codex-plugin-cc that referenced this pull request Jul 16, 2026
Brings the branch onto v1.0.6: session transfer (openai#374), 1.0.5/1.0.6 bumps,
and no-shell-expansion for git commands (openai#447). Conflicts resolved in
codex-companion.mjs (workspace-boundary notice + transfer dispatch coexist)
and lib/app-server.mjs (child exit deregisters the host-exit reaper AND
carries captured stderr in protocol errors). Full suite green: 124/124.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
robinmordasiewicz added a commit to f5-sales-demo/codex-plugin-cc that referenced this pull request Jul 24, 2026
* Fix working-tree review crash on untracked directories (openai#166)

* fix: skip untracked directories in review context

* fix: skip broken untracked symlinks in reviews

* fix: respect SHELL on Windows for Git Bash (openai#178)

* Use app-server auth status for Codex readiness (openai#177)

* Use app-server auth status for Codex readiness

* fix: reuse existing app server for auth checks

* fix: inherit process.env in app-server spawn when no explicit env is provided (openai#159)

`SpawnedCodexAppServerClient.initialize()` passes `this.options.env` to
`spawn()`, but no caller ever sets `env` in options. In Node.js, passing
`undefined` for `env` gives the child process **no** environment variables,
breaking any model provider that relies on env vars (e.g. DATABRICKS_TOKEN).

Fall back to `process.env` when `this.options.env` is not set, matching the
existing pattern in `broker-lifecycle.mjs` and `codex-companion.mjs`.

Co-authored-by: Isaac

Co-authored-by: Bhuvanesh Sridharan <bhuvanesh.sridharan@databricks.com>

* fix: gracefully handle unsupported thread/name/set on older Codex CLI (openai#126)

* fix: gracefully handle unsupported thread/name/set on older Codex CLI

Codex CLI v0.118.0 does not recognize the thread/name/set JSON-RPC method,
causing startThread() to throw. Thread naming is cosmetic (for job log
labels) and should not block thread creation. Wraps the call in try/catch
so it fails silently on older CLI versions.

Fixes openai#119

* refactor: only suppress unsupported-method errors for thread/name/set

Address Codex review feedback: the bare catch swallowed all errors
including auth, network, and server failures. Now only suppresses
errors containing 'unknown variant' or 'unknown method' (the specific
error older CLI versions return) and rethrows everything else.

* codex: scope implicit resume-last selection to the current Claude session (openai#83)

Co-authored-by: VOIDXAI <VOIDXAI@users.noreply.github.com>

* codex: scope default cancel selection to the current Claude session (openai#84)

Co-authored-by: VOIDXAI <VOIDXAI@users.noreply.github.com>

* fix: avoid embedding large adversarial review diffs (openai#179)

* fix: avoid embedding large adversarial review diffs

* fix: preserve untracked content in lightweight review

* address comments

* fix: handle ENOBUFS type check in git diff sizing

* bump: update plugin version to 1.0.3 (openai#180)

* codex: honor --cwd when reporting session runtime (openai#35)

* codex: honor --cwd when reporting session runtime

* codex: keep session runtime lookup scoped to callers

---------

Co-authored-by: VOIDXAI <VOIDXAI@users.noreply.github.com>

* fix: declare model in codex-rescue agent frontmatter (openai#169)

* fix: declare model in codex-rescue agent frontmatter

The codex-rescue agent had no model field, leaving Claude Code to assign
whatever default it chooses. As a thin forwarding wrapper that issues a
single Bash call, this agent is well-suited to the haiku tier; declaring
it explicitly ensures a predictable cost profile and tier guarantee.

Co-Authored-By: Claude Code <noreply@anthropic.com>

* Update codex-rescue.md

---------

Co-authored-by: claude[bot] <claude-bot@anthropic.com>
Co-authored-by: Claude Code <noreply@anthropic.com>
Co-authored-by: Dominik Kundel <dkundel@openai.com>

* fix: correct invalid 'xhigh' reasoning effort in README (openai#99)

Closes openai#77

Updated README to replace unsupported 'xhigh' value with 'high' to prevent configuration errors.

* fix: quote \$ARGUMENTS in cancel, result, and status commands (openai#168)

Unquoted \$ARGUMENTS in the ! shell commands allowed shell metacharacters
in user-supplied job IDs to be expanded before Node received them (e.g.,
`task-123; malicious-cmd` would execute the trailing command). This is
inconsistent with review.md and adversarial-review.md, which both wrap
"$ARGUMENTS" in double quotes.

Co-authored-by: claude[bot] <claude-bot@anthropic.com>
Co-authored-by: Claude Code <noreply@anthropic.com>

* fix: route /codex:rescue through the Agent tool to stop Skill recursion (openai#234) (openai#235)

* fix: route /codex:rescue through the Agent tool to stop Skill recursion (openai#234)

`/codex:rescue` previously combined two things that together caused a hang:

- `context: fork` in the frontmatter, which spawns a `general-purpose`
  subagent for the command body.
- Body prose "Route this request to the `codex:codex-rescue` subagent."
  without naming the transport.

When the main agent called `Skill(codex:rescue)` programmatically, the
fork resolved the ambiguous prose by trying `Skill(codex:codex-rescue)`
(unknown skill) and then falling back to `Skill(codex:rescue)`, which
re-entered this command and hung the session until the user cancelled.
No Codex job was ever created.

Naming the transport as `Agent(codex:codex-rescue)` alone is not enough:
forked general-purpose subagents do not expose the `Agent` tool, so the
forked runner cannot reach the subagent that way either. The minimal fix
is therefore two coordinated changes:

- Drop `context: fork` so the command body runs inline in the calling
  agent's context, where `Agent` is in scope.
- Say explicitly "use the `Agent` tool with `subagent_type:
  "codex:codex-rescue"`", and call out that `Skill(codex:codex-rescue)`
  and `Skill(codex:rescue)` are not valid routing paths. Add `Agent`
  to `allowed-tools` so the call does not prompt for permission.

Everything else in rescue.md (resume-candidate check, flag handling,
background/foreground semantics, operating rules) is unchanged. The
`codex:codex-rescue` subagent itself is unchanged.

Tests pin the new allow-list, the explicit `subagent_type`, the ban on
`Skill(codex:codex-rescue)`, and the absence of `context: fork`. The
existing "run the `codex:codex-rescue` subagent in the background"
assertion continues to hold since that sentence still reads correctly
with the Agent-tool transport.

Fixes openai#234

* test: match quoted result and cancel command arguments

---------

Co-authored-by: Dominik Kundel <dkundel@openai.com>

* fix: bump plugin version to 1.0.4 (openai#244)

* feat: add Claude session transfer command (openai#374)

* fix: bump plugin version to 1.0.5 (openai#398)

* Remove shell expansion for git commands (openai#447)

* Remove shell expansion for git commands

* Version bump

---------

Co-authored-by: Dominik Kundel <dkundel@openai.com>
Co-authored-by: Bhuvanesh Sridharan <bhuvan.sridharan@gmail.com>
Co-authored-by: Bhuvanesh Sridharan <bhuvanesh.sridharan@databricks.com>
Co-authored-by: Trevin Chow <trevin@trevinchow.com>
Co-authored-by: VOIDXAI <oliviawilliams199206@gmail.com>
Co-authored-by: VOIDXAI <VOIDXAI@users.noreply.github.com>
Co-authored-by: xiaolai <lixiaolai@gmail.com>
Co-authored-by: claude[bot] <claude-bot@anthropic.com>
Co-authored-by: Claude Code <noreply@anthropic.com>
Co-authored-by: Manav Agarwal <23bai70003@cuchd.in>
Co-authored-by: Friende <35026241+pengyou200902@users.noreply.github.com>
Co-authored-by: stefanstokic-oai <stefanstokic@openai.com>
Co-authored-by: bryane-oai <bryane@openai.com>
cubicj pushed a commit to cubicj/codex-plugin-cc that referenced this pull request Aug 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants