Getting started
The Claude Codex Adapter lets the Codex desktop app talk to Claude Code through the native Codex app-server protocol. Codex App still runs its normal SSH version probe, bootstrap, and app-server proxy flow — but codex app-server is handled by this adapter instead of the real Codex runtime.
How it fits together
Codex App ──SSH──▶ login shell ──▶ codex (shim, earlier in PATH)
│
app-server calls ──┘──▶ Claude Codex Adapter ──▶ Claude Code
everything else ──────▶ real Codex CLI (CODEX_REAL)The shim is the only integration point: it intercepts codex app-server and forwards everything else to the real Codex CLI, so it coexists with normal command-line Codex usage.
Prerequisites
- Node.js 24+ — the thread store uses
node:sqlite, which Node 22 hides behind--experimental-sqlite. The adapter does not pass that flag, so it crashes at runtime on 22. Pin a binary withCLAUDE_CODEX_NODEif needed. - Claude Code auth — provide your own
ANTHROPIC_API_KEY, supported cloud-provider credentials, or a localclaude /loginsession. Inject credentials through your shell or secret manager; do not commit keys, OAuth state,.envfiles, or acceptance-test transcripts.
Build
npm install
npm run build # tsc -> dist/ (production artifact)The only runtime dependency for Claude itself is @anthropic-ai/claude-agent-sdk, loaded in-process (it ships its own claude-code native binary per platform).
Next steps
- Deployment — install the shim on the remote host and bootstrap a fresh machine without sudo.
- Using the Codex App — connect the GUI and run a turn.
- Configuration — models, effort, MCP, tools, worktrees.
- Backends — switch the active Claude Code route.
Local protocol testing
Set CLAUDE_CODEX_MOCK=1 to exercise the protocol without Claude credentials:
CLAUDE_CODEX_MOCK=1 node dist/src/adapter.mjs app-server --listen ws://127.0.0.1:8788Transports / modes
node dist/src/adapter.mjs app-server --listen unix://
node dist/src/adapter.mjs app-server proxy
node dist/src/adapter.mjs app-server --listen stdio://
node dist/src/adapter.mjs app-server --listen ws://127.0.0.1:8788A ws:// listener on a non-loopback address (such as 0.0.0.0) needs a capability token (--ws-auth capability-token), or the explicit opt-out --ws-allow-unauthenticated; without either the adapter refuses to start. See WebSocket listener.
Two one-shot probes answer and exit without opening the state database, so they never disturb a server already running on the same CODEX_HOME:
# One JSON line: {"appServerVersion": ..., "configRequirements": ...}
node dist/src/adapter.mjs app-server --print-startup-config
# The unix daemon on <CODEX_HOME>/app-server-control/app-server-control.sock,
# or exit 1 when none is running there
node dist/src/adapter.mjs app-server daemon version--startup-sign-out and --startup-client-info <json> are accepted with --print-startup-config and change nothing: Claude threads have no ChatGPT account to sign out of. scripts/codex-shim answers --print-startup-config (without a client info) and a daemon version with no socket to check by itself, without starting node, and passes both to the real codex in native Codex mode.