Skip to main content

claude-in-codex

CI Python 3.11+ License: MIT

Ask Claude Code for an independent code review or second opinion, straight from Codex.

claude-in-codex is review-only: Claude reviews, critiques, and advises. It does not edit your code, run shell commands, or get write tools. It is the mirror image of openai/codex-plugin-cc, which lets Claude call Codex.

What it does

  • Lets Codex call the Claude Code CLI through MCP.
  • Sends Claude bounded context for reviews, critiques, and second opinions.
  • Returns structured findings Codex can summarize or act on.
  • Keeps Codex as the actor and Claude as a read-only reviewer.

Quickstart

You need:

  • Codex
  • the claude CLI, installed and authenticated
  • Python 3.11 or newer
  • uvx
  • git

Check the basics:

claude --version
claude /login
uvx --version
git --version

Add this repository as a Codex marketplace, then install the plugin from it:

codex plugin marketplace add briandconnelly/claude-in-codex
codex plugin add claude-in-codex

Restart Codex after installing. Then ask Codex:

Ask Claude to run claude_status.

claude_status is free. It checks whether the claude CLI is installed, authenticated, and compatible, gives a ready stop/continue signal, and shows the defaults a paid call would use.

Use it

Once claude_status reports ready: true, ask Codex in plain language:

Ask Claude to review my current diff. Pass workspace_root as this repository.

Passing workspace_root matters. It keeps reviews pointed at your project instead of the plugin install directory when the MCP client does not provide a repo root.

Other useful prompts:

  • "Ask Claude to review my staged changes for security issues."
  • "Have Claude attack this plan for weaknesses."
  • "Get an independent second opinion from Claude on this design."
  • "Start a background Claude review of this branch against main."
  • "Ask Claude in the background whether this schema migration is safe."

Use this when you want a second model to look for bugs, regressions, missing tests, security issues, or weak assumptions before you merge or commit to a design.

Codex uses the plugin skill to choose the right tool and arguments. Direct MCP calls are also available:

Tool Use Cost
claude_review_changes Review a git diff now paid
claude_review_changes_async Start a background diff review paid
claude_adversarial_review Pressure-test a plan, claim, or change paid
claude_adversarial_review_async Start a background adversarial review paid
claude_consult Ask for a free-form second opinion paid
claude_consult_async Start a background second opinion paid
claude_status Check readiness and defaults free
claude_dry_run Preview diff/context before a review free

Diff review scopes are working_tree, staged, and branch.

Review staged changes with a test-coverage focus:

claude_review_changes({
  "workspace_root": "/absolute/path/to/your/repo",
  "scope": "staged",
  "focus": "tests"
})

For a long review, launch it in the background:

claude_review_changes_async({
  "workspace_root": "/absolute/path/to/your/repo",
  "scope": "branch",
  "base": "main"
})

Branch the reply on outcome, which every successful launch carries:

  • started — a new paid job is running. Poll with claude_job_status, then fetch the result with claude_job_result.
  • existing_job — an idempotency_key replay handed back a job that already existed, so it may already be finished. The reply is a job status: read its status and result_available, and go straight to claude_job_result when it is already done.
  • no_changes — the diff was empty, so the spend was skipped and the result is inline; there is no job to poll.

Branch on outcome, not on whether job_id is present: both started and existing_job carry one, so its presence cannot tell a fresh launch from a replay. The full routing table is published under claude_capabilities.async_lifecycle.start_outcome_routing.

Each of the three paid operations — claude_consult, claude_review_changes, and claude_adversarial_review — has an _async form. No paid tool is blocking-only.

Prefer the _async form whenever the run may outlive the call: a blocking call that is cancelled or loses its connection loses the work it already paid for, while a job keeps running and claude_job_result still pays out. Pass idempotency_key so a retry after a dropped connection replays the existing job instead of starting a second paid one. Background runs are bounded by the job deadline (CLAUDE_IN_CODEX_JOB_MAX_SECONDS), not by timeout_seconds, which the _async tools therefore do not accept.

Safety and cost

  • Paid tools run Claude and send code or prompts to Anthropic, billed through your existing claude login or ANTHROPIC_API_KEY.
  • Free tools only inspect local state, preflight a request, or manage background jobs.
  • Claude never receives write or Bash tools from this plugin. Claude Code hooks are not tools and may run in config_mode=inherit/scoped; use config_mode=safe or config_mode=bare for untrusted workspaces.
  • access=toolless is the default: Claude receives gathered context as text and cannot read more files. access=readonly lets Claude use Read, Grep, and Glob for extra context.
  • Secret redaction is best-effort defense in depth. Use access=toolless when a workspace may contain secrets.
  • Explicit max_budget_usd values must be between $0.01 and $5.00 inclusive and are rejected outside that range. It is a best-effort Claude CLI stop threshold, not a hard cap. Results distinguish the requested/configured threshold from the effective value and report actual spend in meta.cost_usd when available.
  • Reviews default to effort=xhigh for depth. Lower effort to high or medium for routine reviews when cost matters.
  • system_prompt_append (on claude_consult, claude_consult_async, claude_review_changes, and claude_review_changes_async) adds your own persona or focus directive to Claude's system prompt. The plugin's guardrail prompt always leads and cannot be replaced, and your text is bracketed by markers whose closing side restates that the guardrails outrank anything between them. It is capped at 4096 bytes and rejected before any spend. Text containing one of those marker lines, or a near-miss with a common ASCII fence or caller supplied unhyphenated, is refused. That makes it harder to forge a close and pose as server-authored instructions; a determined caller can reword a marker past the pattern, which is why the guardrails also tell Claude to distrust anything between the markers. meta.system_prompt_append records a SHA-256 and byte length of the text, never the text, so a result shows it ran under a non-default prompt — on sync results and on background-job results alike. A background job stores that same fingerprint on disk, never your text — though Claude's reply is stored until consumed or expired, and a reply can repeat anything you sent. Neither claude_adversarial_review form accepts it.
  • One guarantee there is mechanical and one is not. Claude cannot gain a tool from this text: the allowlist rides the command line, not the prompt. Claude is only instructed not to let the text dictate a verdict. Treat system_prompt_append as a trust boundary you are widening — it is the one way caller text reaches the system turn — and never build it from untrusted workspace content. Note that the system prompt rides the command line, so your text is visible to a process listing on that machine for the duration of the run.
  • focus (on claude_review_changes and claude_review_changes_async) narrows a review to a topic. Your text stays in the user turn, and the server no longer restates it in its own voice: it is delimited by markers of its own, announced as caller-supplied and untrusted, and followed by a sentence saying it may not limit the review's scope, remove a finding, relax a rule, or set the verdict. The guardrail prompt names focus alongside the diff as untrusted data. It is capped at 4096 bytes and rejected before any spend, and, like the append, text carrying one of the server's framing marker lines is refused — each channel reserves both families, so neither can forge the other's delimiters. The framing makes an injected directive visible as caller text; it does not make Claude incapable of following one, so never build focus from untrusted workspace content.
  • paths narrows which changes the server gathers. Its values are never interpolated into server-authored prose: the prompt says only that a caller-supplied filter was applied, and keeps the caveat that access=readonly may still permit reads outside the filter. Path validation cannot police this channel — spaces, punctuation, and prose are legal in filenames — so the fix is that the values do not reach the server's own voice, where an injected sentence would have read as task framing. The guarantee is the voice, not the bytes: an entry naming a file the diff contains still appears in that file's diff header, as untrusted diff data. The guardrail prompt also names path filters as untrusted. What none of this covers is omission: a filter chosen from untrusted material can hide the very changes worth reviewing before Claude ever sees them, so treat paths as scope you decide, and never derive it blindly from workspace content.

If a requested diff scope has no changes, the review tools return a passing result without invoking Claude.

Mental model

Codex remains responsible for deciding what to do with Claude's feedback. Claude receives only the context the plugin provides, or read-only file access when you explicitly allow access=readonly. The plugin does not give Claude write tools, Bash tools, or permission to modify your workspace. In inherit and scoped, Claude Code may still load workspace hooks from .claude/settings*.json; those hooks execute outside the tool allowlist.

Common knobs

Every setting is optional. These are the knobs most users are likely to change:

Variable Default Purpose
CLAUDE_IN_CODEX_ACCESS toolless toolless or readonly
CLAUDE_IN_CODEX_CLAUDE_CONFIG inherit inherit, scoped, safe, or bare
CLAUDE_IN_CODEX_EFFORT xhigh low, medium, high, xhigh, or max
CLAUDE_IN_CODEX_MAX_BUDGET_USD 1.00 best-effort per-call budget threshold
CLAUDE_IN_CODEX_MODEL unset Claude model; unset uses the CLI default
CLAUDE_IN_CODEX_TIMEOUT_SECONDS 180 per-call timeout, clamped to 10-600 seconds
ANTHROPIC_API_KEY unset required only for config_mode=bare

Set these in the environment you launch Codex from. The bundled MCP config forwards the common cost, safety, model, timeout, and API-key variables to the server.

config_mode=inherit uses your normal Claude environment without persisting a session. scoped drops user-global settings and user MCP servers but keeps CLAUDE.md and workspace hooks. safe disables Claude Code customizations and hooks while preserving normal authentication. bare strips CLAUDE.md, memory, and hooks, and requires ANTHROPIC_API_KEY.

Troubleshooting

Start with:

Ask Claude to run claude_status.

Then:

  • If claude_authenticated is false, run claude /login.
  • If ready is false, inspect readiness_detail and default_errors before making paid calls.
  • If the workspace looks wrong, pass workspace_root explicitly.
  • If a review is large or expensive, run claude_dry_run first.
  • If a background job id is lost, use claude_job_list.
  • If config_mode=bare fails, confirm ANTHROPIC_API_KEY is set in the environment that launches Codex.

Distribution

The Codex plugin install path is the primary user-facing path. The bundled MCP config pins the server to a versioned Git tag so installed users update deliberately.

The Python package publishes the MCP server entry point for direct use and release provenance. After a PyPI release, the server can also be launched with:

uvx --from claude-in-codex==0.9.0 claude-in-codex-mcp

Advanced reference

Every tool returns a structured ok/error envelope. Paid results include usage metadata and cost when the Claude CLI reports it. The tool contract is experimental and pre-1.0; clients can pin meta.fingerprint to detect agent-visible changes.

The Claude CLI compatibility assumptions are centralized in src/claude_in_codex/cli_contract.py and documented in COMPATIBILITY.md.

Local development

Run the MCP server from a checkout:

codex mcp add claude-in-codex -- uv run --directory "$(pwd)" claude-in-codex-mcp

Run tests:

uv run pytest

The full suite enforces a 95% coverage floor. For one-file iteration:

uv run pytest tests/test_jobs.py --no-cov

Live Claude integration tests are excluded by default:

uv run pytest -m integration --no-cov

They require the claude CLI and make a small paid API call.

Metadata

Release files for claude-in-codex 0.9.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for claude-in-codex 0.9.0
File Size Uploaded
claude_in_codex-0.9.0.tar.gz 629.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for claude-in-codex 0.9.0
File Interpreter ABI Platform
claude_in_codex-0.9.0-py3-none-any.whl Python 3 none any Details

Total release size: 773.6 kB

Release files / claude_in_codex-0.9.0.tar.gz

Download URL claude_in_codex-0.9.0.tar.gz
Size 629.5 kB
Tags Source
SHA-256 checksum
How to use checksums
9199d47a40517f550c2c9bf4858f29a3869434ff5a1397fd257cb2681d69d1c9
BLAKE2b-256 checksum
How to use checksums
57d98a4a1a2c032bd872d5672b8f5a6bf37c0251c481edb9143389fb5df0299d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 4, 2026.

Transparency log

Release files / claude_in_codex-0.9.0-py3-none-any.whl

Download URL claude_in_codex-0.9.0-py3-none-any.whl
Size 144.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
e00f5c56f94e981945c316d7e4c838e0ed2db5df6daa34f26dfeb53a771d33ee
BLAKE2b-256 checksum
How to use checksums
e889a929364dda7e09509d4d26e732b299ee989be1591548c21520ce9231beb8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 4, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.9.0 This release

2 release files

0.8.0

2 release files

0.7.0

2 release files

0.6.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page