Codex Companion connects Cursor to the local OpenAI Codex CLI. It adds read-only reviews, delegated tasks, background job control, resumable Codex threads, and exact Cursor-to-Codex conversation transfer.
This is an independent integration. It is not an official OpenAI or Cursor product.
- Cursor with local plugin and hooks support
- Node.js 18.18 or later
- Git for review workflows
- A current Codex CLI installed and authenticated
npm install -g @openai/codex@latest
codex loginRun /codex-setup in Cursor after installation. The setup command reports the active provider, authentication state, and whether the configured model is offered by the installed Codex runtime, without changing credentials or configuration.
Clone or place this repository anywhere, then copy the single-plugin root into Cursor. Cursor rejects local-plugin symlinks whose targets escape ~/.cursor/plugins/local, so use a real directory:
mkdir -p ~/.cursor/plugins/local
rsync -a --delete \
--exclude '.git/' --exclude 'node_modules/' --exclude 'tests/' --exclude 'docs/' \
/Users/maozhen/Documents/cursor-plugin-codex/ \
~/.cursor/plugins/local/codex-companion/Reload Cursor. The plugin contributes eight commands, two skills, one worker agent, and lifecycle hooks.
For development verification:
npm install
npm run check| Command | Purpose |
|---|---|
/codex-setup |
Check Node, Codex, authentication, shared runtime, and review-gate state. |
/codex-review |
Run Codex's native read-only review against working-tree or branch changes. |
/codex-adversarial-review |
Run a focused read-only review with structured findings. |
/codex-task |
Delegate one task to Codex, optionally writable, backgrounded, fresh, or resumed. |
/codex-transfer |
Import the exact current Cursor conversation into a resumable Codex thread. |
/codex-status |
Show current-conversation jobs or wait for one explicit job. |
/codex-result |
Read the complete stored result of a finished job. |
/codex-cancel |
Interrupt the active Codex turn and cancel its worker. |
Examples:
/codex-review --scope working-tree --wait
/codex-review --scope branch --base main
/codex-adversarial-review --base main focus on auth and retry behavior
/codex-task --write implement the approved cache invalidation change
/codex-task --background --write refactor the parser and run its tests
/codex-task --resume follow up by addressing the remaining failure
/codex-task --fresh --model spark investigate this without changing files
/codex-status task-abc123 --wait --timeout-ms 240000
/codex-result task-abc123
/codex-cancel task-abc123
task is read-only unless --write is supplied. In read-only mode, --prompt-file must resolve inside the current workspace. --resume and --resume-last select only a finished task associated with the current Cursor conversation; --fresh never resumes. Model and reasoning effort remain unset unless requested. The spark model alias expands to gpt-5.3-codex-spark.
Review commands never grant workspace-write access. Native review uses Codex's review/start; adversarial review uses a read-only turn with a structured output schema.
Cursor commands request full terminal permission because the local runtime must read Codex authentication and state under ~/.codex, Cursor transcripts under ~/.cursor, and companion-owned job metadata outside the workspace. Review and non---write task operations still configure Codex itself with a read-only workspace sandbox.
Foreground work is the default. --background starts a tracked detached worker and immediately returns a job ID. Jobs transition through queued, running, completed, failed, or cancelled states. Status, implicit result selection, and implicit cancellation are partitioned by CURSOR_CODEX_CONVERSATION_ID; an explicit job ID can still address a known job from another conversation.
Cursor plugin invocations fail closed when an implicit job or transfer operation cannot determine the current conversation. Explicit job IDs and an explicit transfer --source bypass automatic inference, so they remain available as recovery paths. Concurrent lifecycle updates are serialized. Workspace fallback is allowed only when exactly one recent conversation is known; two distinct recent conversations are always treated as ambiguous instead of selecting the newest one.
One Codex App Server broker is lazily reused per Cursor conversation. Cancellation first sends turn/interrupt, then terminates the worker process tree if necessary. Session shutdown stops that conversation's broker and active jobs without deleting results from other conversations.
/codex-transfer uses an exact source in this order:
- Explicit
--source <cursor-jsonl> - The transcript captured for
CURSOR_CODEX_CONVERSATION_ID - The exact transcript path discovered from that conversation ID under Cursor's transcript store
CURSOR_CODEX_TRANSCRIPT_PATH is exported and explicitly cleared by lifecycle hooks for compatibility, but transfer does not use it as an ownership proof. Automatic transfer requires the canonical path stored for the conversation or discovered under a workspace-trusted Cursor transcript directory.
The beforeSubmitPrompt hook records only conversation ID, workspace roots, transcript path when available, and last-seen time; it never stores the submitted prompt. There is deliberately no “latest transcript” or workspace timestamp fallback. If Cursor has not supplied exact identity, retry with an explicit source path.
Slash-command arguments are passed as separately shell-escaped argv elements to one Node.js runtime. Command definitions explicitly forbid raw-string interpolation and eval. Windows drive paths, UNC paths, and trailing backslashes are preserved, including values supplied to --source, --cwd, and --prompt-file.
Cursor JSONL is normalized before import. User and assistant text are retained, supported tool calls retain only their name and size-bounded JSON input, and status/thinking/unsupported records are skipped. A transcript without an importable user message is rejected.
Current Codex external-session import recognizes Claude-format JSONL and requires the imported file to resolve below ~/.claude/projects. The plugin therefore writes only the normalized compatibility copy to:
~/.claude/projects/-cursor-codex-transfer/<conversation-id>.jsonl
The directory and file use user-only permissions where supported. The file is closed before import and removed in a finally path after success or failure. The original Cursor transcript can live anywhere and is never moved. This restriction comes from the current Codex importer, not from this plugin's source resolver.
Codex's import ledger de-duplicates the same staged path and SHA-256 content. Repeating an unchanged transfer returns the existing imported thread; changed content at the same path can produce a new imported thread.
Enable the gate explicitly:
/codex-setup --enable-review-gate
Disable it with /codex-setup --disable-review-gate. When enabled, Cursor's bounded stop hook runs one read-only Codex review of the immediately previous Cursor turn. Concrete findings are returned through Cursor's followup_message; clean, unavailable, aborted, or loop-limited runs return an empty hook response. The gate never exits non-zero and is limited to two continuation loops.
The gate can add latency and Codex usage at the end of edit-producing turns, so it is off by default.
- Commands call only the locally installed
codexexecutable. Codex itself uses the provider configured in your Codex installation. - Raw normalized transcript bodies are not written to operational logs or session maps.
- Session maps store only conversation ID, canonical transcript path, workspace roots, and last-seen time.
- Job metadata and results default to
~/.cursor/codex-companion/state/with private permissions where supported. CURSOR_CODEX_DATA_DIRis an override intended for tests or managed installations.- Compatibility JSONL is temporary and removed on all handled exit paths.
Cursor cloud agents may not have access to your local Codex binary, local transcript path, or local plugin state. This plugin is designed primarily for local Cursor sessions.
Codex is unavailable
Run codex --version, update with npm install -g @openai/codex@latest, then run /codex-setup again.
Authentication is unavailable or stale
Run codex login. Custom providers that do not require OpenAI authentication are accepted when Codex App Server reports them as ready.
Transfer cannot identify the current transcript
Use /codex-transfer --source /absolute/path/to/conversation.jsonl. The source must be an existing regular .jsonl file, but it does not need to be under ~/.claude/projects.
A background job appears stale
Run /codex-status <job-id>, then /codex-cancel <job-id> if it is still active. Stale worker PIDs are treated as exited rather than blindly reused.
Plugin components do not appear
Confirm ~/.cursor/plugins/local/codex-companion/.cursor-plugin/plugin.json exists, run npm run validate, synchronize the plugin directory again, and reload Cursor with Developer: Reload Window.
Update the repository, synchronize the local-plugin copy again, and reload Cursor. To remove the plugin:
rm -rf ~/.cursor/plugins/local/codex-companionOptionally remove only companion-owned state:
rm -rf ~/.cursor/codex-companionDo not delete ~/.cursor or ~/.codex wholesale; both may contain unrelated settings and conversations.
Apache-2.0. The App Server, Git review, rendering, and tracked-job runtime adapt parts of openai/codex-plugin-cc; see NOTICE.
This project explicitly references two upstream sources:
openai/codex-plugin-ccfor the proven Codex App Server, review, process-control, rendering, broker, tracked-job, and test-fixture foundations. Adapted code remains covered by Apache-2.0 and is identified in NOTICE.- Cursor's official
cursor/plugin-templatefor the single-plugin layout,.cursor-plugin/plugin.jsonconventions, commands, skills, agents, hooks, assets, and validation expectations. It was used as the authoritative structural reference for the Cursor surface.
Compared with codex-plugin-cc's Claude Code integration, Codex Companion adds or strengthens:
| Area | Cursor-specific optimization |
|---|---|
| Native plugin surface | Eight Cursor slash commands, two skills, a worker agent, lifecycle hooks, manifest validation, and local-install/reload guidance. |
| Exact session isolation | Cursor conversation IDs are captured by hooks, validated against the current workspace, serialized under a private session map, and rejected when stale or ambiguous. |
| Cursor-to-Codex transfer | Cursor JSONL is normalized, imported through Codex's native external-session API, de-duplicated through the Codex ledger, and returned as a resumable Codex thread. Explicit --source recovery never inherits stale session identity. |
| Safer multi-chat jobs | Background task, review, status, result, resume, and cancel operations are partitioned by conversation; explicit job IDs remain an intentional recovery path. |
| Cross-platform invocation | POSIX and PowerShell command forms, tokenized argv transport, Windows drive paths, UNC paths, trailing separators, and Windows process termination are covered. |
| Privacy and hardening | Prompt bodies are not persisted in session metadata, transcript ownership is proven before import, read-only prompt files stay inside the workspace, symlinks are canonicalized, and private state uses user-only permissions where supported. |
| Operational diagnostics | /codex-setup checks Node, npm, Codex, authentication, provider readiness, shared runtime state, review-gate state, and configured-model availability without changing user configuration. |
| Lifecycle reliability | Per-conversation lazy App Server reuse, interrupt-before-kill cancellation, concurrent map locking, stale PID handling, session-end cleanup, and an optional bounded stop-review gate. |
| Verification | Component, protocol, parser, session, transfer, runtime, and real Cursor UI E2E coverage with saved evidence screenshots. |
The dated command-by-command evidence, environment details, job/thread IDs, and all eight Cursor screenshots are collected in the 2026-07-15 E2E report.