Skip to content

Releases: briandconnelly/codex-in-claude

codex-in-claude v0.22.0

Choose a tag to compare

@github-actions github-actions released this 31 Aug 23:18
f529853

An install-repair and hardening release. The headline is the dependency cap: fastmcp 4.0.0
published and every earlier release's uncapped fastmcp>=3.4 floor now resolves it and fails at
import, so fresh installs — including the .mcp.json plugin path — are broken until this release
supersedes them. Alongside the cap, the three free diagnostics gain the same envelope guarantees
as the paid tools, and the developer_instructions docs stop overstating what the parameter and
its fingerprint prove. The result fingerprint moves schema-85schema-87 (both hops
additive or wording-only); nothing is breaking. The fastmcp 4 port itself lands separately
(#570).

Fixed

  • Fresh installs no longer resolve the incompatible fastmcp 4 (#572): every released version
    declares fastmcp>=3.4 with no upper bound, so once fastmcp 4.0.0 (on mcp 2.1.1) published, a
    fresh install resolved it and failed at import (cannot import name 'McpError' from 'mcp') —
    including the .mcp.json plugin path. The floor is now capped at <4. Already-published
    versions cannot be repaired, only superseded by releasing this cap. The fastmcp 4 port itself is
    #570.

  • The three free diagnostics can no longer fail as a raw MCP protocol error (#541):
    codex_status, codex_capabilities and codex_models are synchronous, so the _guard
    decorator — which wraps async tools — never covered them, and anything they raised escaped the
    handler instead of returning the documented envelope. That was worst for codex_status, whose
    entire job is to answer "is codex usable right now?": the tool an agent reaches for because
    something is already wrong was the one least able to report it. All three are now guarded and
    advertise internal_error in their per-tool error_codes; their output schemas already carried
    a success|error union, so no schema shape changed. The result fingerprint moves schema-86 ->
    schema-87. Adding an error code is backward-compatible, so this is not breaking.

  • A codex on PATH that cannot be executed is a readiness fact, not a crash (#541):
    binpath.codex_bin() deliberately falls back to the bare literal "codex" when resolution finds
    nothing, and subprocess then does its own PATH lookup without the is_file() + X_OK
    predicate binresolve applies to its own candidates. An executable directory named codex (or a
    file with the execute bit set that the kernel cannot exec) therefore raised PermissionError /
    OSError(ENOEXEC) straight out of the probes. Those spawn failures are now classified the way a
    missing binary already was, so codex_status reports codex_found: false instead of raising.

  • The three free tools now report their own pinned posture on an invalid-argument error
    (#541): README documents that every shipped tool pins its own tier and sandbox and ignores
    CODEX_IN_CLAUDE_TIER_DEFAULT / CODEX_IN_CLAUDE_SANDBOX_DEFAULT. Because the three unguarded
    tools had no entry in the posture map, their invalid_arguments envelope fell back to
    config.defaults() and reported whatever an operator had configured — an operator running
    TIER_DEFAULT=propose saw codex_capabilities claim propose/workspace-write. Guarding them
    registers their real posture and restores the documented promise. meta values are not part of
    the discovered surface, so this moves no fingerprint of its own.

Changed

  • developer_instructions now documents that compliance is best-effort (#563): the only
    "instructed, not compelled" statement on the surface was scoped to verdicts, which reads as a
    promise that everything else applies. It does not — Codex may honor the caller text in full, in
    part, or not at all, and no result field attests which happened — meta's fingerprint attests
    the request the server accepted and staged, never what the model did with it. Non-compliance may be silent,
    though the server's framing does instruct Codex to disclose a conflict with the rules above it,
    and detail="full" returns the raw model text. Stated once in the parameter contract (inline
    summary and codex://params full text), and echoed in README.md, COMPATIBILITY.md, and the
    bundled skill. The result fingerprint moves schema-85 -> schema-86; documenting an
    existing limit weakens no guarantee, so this is not breaking.
  • The bundled skill no longer overstates what the fingerprint proves (#564): the
    options-and-errors reference called it "how you tell a steered run from a default one". It
    separates a steered request — it attests what the server SENT, not what the model did — and
    its absence means only that the per-call parameter was omitted, not that the run was otherwise
    unsteered. The same reference now also states what validation does and does not cost: a value
    the server REFUSES costs nothing — unsafe text, the byte cap, framing markers, and the combined
    input budget are all rejected pre-spend — while a value it ACCEPTS goes straight into the paid
    run, so there is no free positive check. Because the checks stop at the first failure in
    unsafe -> byte cap -> marker order, a value that is both over-cap and marker-bearing reports
    only the cap.

codex-in-claude v0.21.0

Choose a tag to compare

@github-actions github-actions released this 30 Aug 23:17
ec6fc2b

A caller-steering release. Consult and review gain an optional developer_instructions
parameter — caller stance for Codex's developer turn, always behind this server's framing, with
a {sha256, bytes} fingerprint reported in meta — and the operator passthrough loses the
ability to set the instruction-bearing config keys that could outrank that framing (the one
breaking change, operator surface only). The bundled skill teaches agents how to route content
into the new parameter and how to recover its refusals. The result fingerprint moves
schema-84schema-85 and the persisted RESULT_FORMAT 10 → 11 (both additive); the tracked
Codex version moves to 0.151 with no contract break.

Added

  • developer_instructions on codex_consult, codex_consult_async, codex_review_changes,
    and codex_review_changes_async
    (#556): optional caller stance/focus text for Codex's
    developer turn, composed into ONE -c developer_instructions value — this server's framing
    always leads, the caller text is delimited on both sides, and the closing marker outranks
    anything between the markers. codex places the value as the first developer-role message,
    ahead of its own developer messages (verified via codex debug prompt-input on 0.151.0), so
    that placement is disclosed rather than reordered. Normalized once (stripped; blank =
    omitted); refused pre-spend over 4096 bytes, on control characters (C0 except tab/LF/CR, DEL,
    NUL) or lone surrogates, or when the text carries a framing-marker line (invalid_arguments
    with a reason naming forged_framing_marker); counted against
    CODEX_IN_CLAUDE_MAX_INPUT_BYTES with the call's other caller-authored inputs. Emitted only
    when text is present, so the common run's argv is byte-identical to 0.20.0's and never arms
    --strict-config; an instruction-carrying run does arm it, and a strict-config rejection of
    the plugin's own key is attributed to the plugin (cli_contract_changed), never to the user's
    config. meta gains a developer_instructions {sha256, bytes} fingerprint on sync results,
    the async launch handle, and fetched job results; the text itself is never echoed, though it
    does ride the codex command line and the on-disk background-job record — the tool description
    and skill disclose both carriers. Deliberately NOT on codex_delegate/codex_delegate_async.
    New developer_instructions parameter contract in codex://params. fingerprint
    schema-84schema-85; persisted RESULT_FORMAT 10 → 11 (new Meta field). Non-breaking
    (additive).
  • The bundled skill teaches when and how to use developer_instructions (#560): a
    content-routing rule (stance/persona/emphasis in developer_instructions; the target via the
    review scope or a consult's question; facts and quoted artifacts in extra_context; data
    never in the developer turn), refusal recovery for forged_framing_marker and the two byte
    limits, a dry-run caveat (codex_dry_run takes no developer_instructions), an independence
    hazard (a stance hinting at Claude's approach forfeits the two-member pattern), and framing
    stability across review–revise passes with the meta.developer_instructions fingerprint as
    the equality check. SKILL.md gains a Data-exposure bullet for the argv/job-record carriers and
    three binding rules (routing, exposure, independence) so the rules agents apply are as wide as
    the disclosures. Skill prose only — no wire text.

Changed

  • BREAKING (operator surface): the extra-args passthrough can no longer set the
    instruction-bearing config keys
    (#555). CODEX_IN_CLAUDE_EXTRA_ARGS now refuses
    -c developer_instructions=…, model_instructions_file, its deprecated alias
    experimental_instructions_file, the documented-as-reserved instructions, and
    model_catalog_json (a catalog entry can redefine a model's base_instructions) — plus the
    usual case/quote lookalikes — at parse time with extra_args_rejected, before any spend.
    Every framing string this server sends rides the user turn while developer_instructions
    lands as the first developer-role message, so a passthrough value outranked the server's own
    guardrails with no meta record; the per-call, meta-reported parameter (above) is the
    first-class replacement. --profile and, at inherit isolation, the user's config.toml
    remain the documented operator-trust boundary. Not itself a fingerprint move: the denylist
    is not part of the discovered surface.
  • pontonier 0.6.0 → 0.7.0: the caller text crosses the backend adapter on the new
    first-class RunRequest.instructions_append field (pontonier#12) instead of riding
    extra_args, which the protocol reserves for operator descriptors;
    CodexBackend.validate_request mirrors the server boundary and prepare() fails closed for
    direct adapter callers (#558).
  • Tracked Codex version is now 0.151. SUPPORTED_VERSIONS tracks (0, 151); a 0.149
    or 0.150 CLI still runs and reports the advisory untracked-version warning in
    codex_status. Verified end to end against codex-cli 0.151.0 and A/B'd against a
    side-by-side 0.149.1. No contract break and no agent-visible change.
    • All 12 ALWAYS_SEND flags, the --model help-gated flag, and all three --sandbox values
      are present; the five relevant help screens are byte-identical to 0.149.1.
    • Both security pins re-verified live with positive controls, each against the config file
      and an operator --profile: sandbox_workspace_write.network_access=false still blocks
      egress, and sandbox_workspace_write.writable_roots=[] still blocks writes outside the
      workspace; upstream's SandboxWorkspaceWrite struct still carries exactly the four fields
      COMPATIBILITY.md accounts for.
    • The --strict-config grammars still parse, --ignore-user-config still exempts the config
      file, and the app-server schema diff left all seven consumed schemas byte-identical.
    • KNOWN_MODEL_SLUGS is unchanged, and the implicit-context presence matrix (AGENTS.md
      sources and both skills roots) is identical to 0.149.1 under the read-forbidding probe.
      0.151 adds a default-off skip_host_skill_discovery feature flag — inert here, but the
      flag to re-probe first when it stages.
    • New 0.151 surface is deliberately not adopted; remote_plugin, view_image, and
      recommended_plugins all hold their recorded stage and default.

codex-in-claude v0.20.0

Choose a tag to compare

@github-actions github-actions released this 26 Aug 23:56
782a1e8

A compatibility and diagnosis release. Nothing on the agent-visible surface changed: the result
fingerprint stays at codex-in-claude/0.1/schema-84 and RESULT_FORMAT at 10, and there is
no breaking change.

The tracked Codex version moves to 0.149, verified end to end and A/B'd against 0.148.0.
Two more ways a user's own Codex config can refuse to start are now diagnosed instead of surfacing
as a bare nonzero_exit: a setting 0.149 retired, and a value of the wrong variant or type.
Each is attributed to whoever sent the key — the plugin's own pins only when this run actually
emitted them. On WSL2, codex is resolved to the WSL-native install instead of a Windows-side
shim that Windows-PATH interop can put first on PATH, and a new CODEX_IN_CLAUDE_CODEX_BIN
override names a binary outright.

Added

  • user_config_rejected now covers two more config-parse failures — a setting codex has
    RETIRED (#542; 0.149 retired the untrusted approval policy and refuses to start when the
    user's config still selects it) and an INVALID value, the wrong enum variant or the wrong TOML
    type (#550; a plain typo in config.toml). Both are distinct grammars from the --strict-config
    unknown-KEY one — the key exists and only its value is refused — and neither matched a drift
    signature, so each surfaced as a bare nonzero_exit with the diagnosis lost. Neither needs a
    -c pin or --strict-config, and both fire at the default inherit isolation, so they are the
    failures a user meets on the first run after an upgrade or an edit. Captured verbatim from
    codex-cli 0.149.1; each recognizer is anchored to the whole of stderr so a config-shaped pair
    quoted ahead of a genuine auth/drift/rate-limit diagnostic cannot steal the classification. The
    offending value is never echoed — it is free text the user typed into the wrong key, plausibly
    a secret no pattern-based redactor recognizes — while what codex expected (the allowed
    variants, or the type) is surfaced as the actionable content. Because these messages name no
    file, an error under an operator --profile discloses that the profile may be the source rather
    than asserting the user's own config, and the repair guidance is written for a refused value
    rather than inherited from the unknown-key prose. Attribution follows the --strict-config
    discipline, keyed on who sent the rejected key on this run: one of the plugin's own pins —
    emitted only on workspace-write runs and effort-carrying runs, and verified live to outrank a
    bad file value entirely, so the refused value can only have been ours — is cli_contract_changed;
    an operator passthrough key, or a dotted child of one (codex echoes a -c t={k=v} parent-table
    assignment as t.k), is extra_args_rejected; anything else is user_config_rejected. No new
    error code, so no FINGERPRINT change.
  • CODEX_IN_CLAUDE_CODEX_BIN names the codex binary to invoke (#538). A non-empty value is
    used exactly as given, with no PATH re-resolution, and must be an executable file on disk: a
    missing path, a directory, or a file without the execute bit is reported by codex_status as
    codex_found: false with a readiness_detail naming the env var — never its value, which is
    operator-controlled and unbounded — and by every paid run as codex_not_found, zero spend,
    rather than as an internal_error inviting a retry. Documented in the README's Configuration
    table and COMPATIBILITY.md.

Changed

  • Tracked Codex version is now 0.149. SUPPORTED_VERSIONS tracks (0, 149); a 0.148 CLI
    now warns in codex_status (advisory only — it never blocks). Verified end to end against
    codex-cli 0.149.1 and A/B'd against a side-by-side 0.148.0. No contract break: all 12
    ALWAYS_SEND flags, --model, and all three sandbox values are present and unchanged.
    • Re-verified live, each with its own positive control: the workspace-write network-egress and
      writable-roots pins (both still outrank the config file and --profile); the read boundary on
      both tiers, with the write negative control proving the sandbox was in force; --ignore-rules;
      model_reasoning_effort; --output-schema conformance together with --output-last-message
      receiving exactly the final agent_message; and the --strict-config rejection grammar,
      unchanged in both forms.
    • The implicit-context marker probe (AGENTS.md sources, both skills roots, all four variants)
      produced a presence matrix identical to 0.148.0 — notable because 0.149 reworked skill
      selection and carried an upstream change titled "Enforce filesystem permissions when loading
      AGENTS.md".
    • KNOWN_MODEL_SLUGS gains gpt-reserve. A contemporaneous cache-free A/B had 0.148.0 fetch
      the identical set, so this is a backend catalog move, not a client change. Its
      visibility: "hide" is deliberately not filtered (#547).
    • The 0.148.00.149.1 app-server schema diff leaves six of the seven consumed schemas
      byte-identical; GetAccountRateLimitsResponse gains two PlanType enum values (edu_plus,
      edu_pro), absorbed because planType is read as a bounded free-form string.
    • New 0.149 surface is deliberately not adopted: the agents and queue subcommands and
      exec --thread-source are unused, and the retired untrusted approval value was never sent.
      remote_plugin, view_image, and recommended_plugins all hold their recorded postures.
  • The remote_plugin guarantee now says which half of it is verified (#542, #548). The
    mechanism half is re-verified and pinned in the live integration suite: --disable wins over
    --enable in either order and over -c features.remote_plugin=true, and an unknown feature name
    still fails loud. The tool-surface half — proving no connector tool is exposed — needs a machine
    with a connector installed as a positive control, and none is; it is recorded as not exercised
    rather than as a pass, and COMPATIBILITY.md tells the next agent to check for that control
    first. Upstream 0.149.0's "Remove the workspace settings gate for apps and plugins" touches only
    the app-server and chatgpt crates, so it does not reach the codex exec path this covers.
  • collaborating-with-codex skill: the spend step describes only the live codex_status quota
    read; the readiness gate, blocked refusal, cap declaration, async preference, and composition
    opt-in gate are now explicit Binding rules; the compound Delegation and Retry rules are
    split; the untrusted-workspace rationale moved to Data exposure; and the transfer reference notes
    that a resumed thread runs under Codex's own AGENTS.md auto-loading and skill discovery,
    outside the plugin's flags.

Fixed

  • On WSL2, codex subprocesses resolve the WSL-native install instead of a Windows-side shim
    (#537, #538). WSL2 — this project's documented way to run on Windows — forwards the Windows
    PATH into the WSL PATH, so the bare "codex" every spawn site used could resolve to a
    Windows npm-global shim and fail confusingly (codex_status reported codex_found: false next
    to a fully populated flags_warning). Every spawn site now goes through binpath.codex_bin(),
    resolved once per process: under WSL2 ($WSL_DISTRO_NAME, or microsoft in /proc/version) it
    probes $HOME/.local/bin/codex, /usr/local/bin/codex, then the npm global bin dir (from
    npm prefix -g; npm bin -g was removed in npm 9+) ahead of shutil.which("codex"); on any
    other host it goes straight to shutil.which, so a stale ~/.local/bin/codex cannot shadow a
    newer install there. The probe order lives in binresolve.py, and codex_status's "not found"
    detail no longer claims PATH is the only place checked. Thanks to @cbeaulieu-gt (#539).

codex-in-claude v0.19.0

Choose a tag to compare

@github-actions github-actions released this 21 Aug 00:47
13640e4

A sandbox-hardening and egress-disclosure release.

Three workspace-write guarantees that were advertised but not enforced now hold at every
isolation level: network egress and the writable-root set are pinned on the command line, where
the user's own $CODEX_HOME/config.toml can no longer widen them, and codex exec --strict-config turns a pin codex silently ignores into a zero-spend startup failure instead of
a guarantee that quietly stopped holding.

The egress disclosures were corrected in the unsafe direction they were wrong in. Codex's reads
are not bounded by the workspace; AGENTS.md is auto-loaded from the repository root and from
$CODEX_HOME as well as from the resolved workspace; a discovered skill's body reaches OpenAI
through a read the model itself issues after selecting it on its description alone; a dry-run
preview does not bound what the paid call sends; and the propose tier's throwaway worktree does
not bound where Codex writes, because workspace-write grants the OS temp roots by default.
Every one of these was probed live on codex-cli 0.148.0 with negative controls; none is a
behavior change, and each corrects a claim that never held.

Foreign text is no longer echoed raw. A rejected config key, codex's stderr, an unknown argument
name, a job id, and the codex --version string are now sanitized, bounded, or rejected before
they reach a result envelope, so a control character can neither spoof a terminal nor wedge
itself into a secret to defeat the redactor.

The tracked Codex version moves to 0.148.

Three breaking changes: an unknown key in your own Codex config now fails pin-carrying runs; the
propose-tier surface retracts its "writes only inside a throwaway worktree" promise; and five
parameters reject control characters in their values. The agent-visible surface changed nine
times (result fingerprint codex-in-claude/0.1/schema-75schema-84, and the persisted
RESULT_FORMAT 810), so pre-1.0 this is a minor release; clients that cache by
fingerprint re-fetch the contract, and a reader older than RESULT_FORMAT 10 rejects newly
stored job records.

Changed

  • BREAKING: codex exec --strict-config guards the guarantee-bearing -c key pins, and a new
    user_config_rejected error code reports an unknown key in your own Codex config.
    codex
    silently tolerates an unknown config key, so an upstream rename of
    sandbox_workspace_write.network_access (#518), sandbox_workspace_write.writable_roots
    (#520), or model_reasoning_effort (#309) would leave the plugin sending a key codex no longer
    reads — reopening the guarantee with no signal. The flag turns that into a zero-spend startup
    failure, since config parsing precedes auth and any model call. It is emitted only on runs
    that carry a -c override
    — every workspace-write run, every effort-carrying run, and any
    run with an operator -c in CODEX_IN_CLAUDE_EXTRA_ARGS — because at the default inherit
    isolation the flag also hard-fails on an unknown key anywhere in the user's own config,
    including tables for profiles the run never selects; a plain read-only consult carries no pin,
    so sending it there would risk availability while guarding nothing.

    Breaking because a previously accepted operator environment — a junk or version-skewed key in
    $CODEX_HOME/config.toml — now hard-fails pin-carrying runs. Ownership keys on the rejected
    KEY, never on the shared -c descriptor codex's own message contains: a rejected plugin pin is
    cli_contract_changed (the fail-loud drift signal this exists to produce), an operator key or
    an operator --profile-selected file is extra_args_rejected, and any other config file is
    the new user_config_rejected — permanent, repairing with correct_config, naming the file
    and line to fix and offering isolation="ignore-config" only as an explicitly lossy fallback,
    since it drops your entire config. Neither codex_status nor a dry run parses Codex config, so
    neither can predict this failure. Strict validates key names only, so a bad
    reasoning_effort VALUE still takes the backend invalid_reasoning_effort path unchanged.
    (#524)

  • BREAKING: the propose-tier surface no longer promises "writes only inside a throwaway
    worktree", and the delegate tools now advertise destructiveHint: true.
    codex's
    workspace-write sandbox grants the OS temp roots (/tmp and $TMPDIR) by default
    (exclude_slash_tmp/exclude_tmpdir_env_var default false), verified live at this plugin's
    exact argv, so the exclusivity claim never held. The exclude_* keys are deliberately not
    pinned closed — build tools, uv, git, and test runners need $TMPDIR — so every carrier
    discloses the grant instead: a canonical cli_contract.WORKSPACE_WRITE_SCOPE_FACT is carried
    verbatim by both delegate descriptions, their codex_capabilities returns entries, and a new
    negative_scope item, each alongside the persistence clause (temp-root writes are neither
    captured in the returned diff nor cleaned up); Meta.tier and Meta.sandbox carry a short
    form. The annotation preset splits: MCP defines destructiveHint: false as "performs only
    additive updates", and a delegated task can overwrite or delete pre-existing files under the
    temp roots, so codex_delegate/codex_delegate_async flip to true while consult and review
    keep false — the split is stated on annotations_reading.

    Breaking because the retired carriers made an exclusive promise ("writes only inside", "the
    worktree bounds what Codex may WRITE"), and correcting them weakens a documented guarantee
    a client could have relied on — even though runtime behavior is unchanged and the guarantee
    never held. What remains true and promised: the plugin never applies anything to your working
    tree, and the returned diff is gathered from the worktree only. (#523)

  • The egress disclosures no longer scope Codex's reads to the workspace or the repo. Several
    descriptions said Codex reads "files ... from its resolved working dir", "other repo files",
    or "tracked files in the throwaway worktree". A reader takes that as a bound; it is not one.
    --sandbox read-only bounds writes: probed on codex-cli 0.148.0 under this plugin's own
    flags with the workspace a bare non-repo directory, the model shelled out and read a file in
    $HOME on both tiers, while a write attempt in the same read-only run was refused — the
    negative control that makes the read informative. A canonical cli_contract.READ_SCOPE_FACT
    now states the truth at every carrier: the server instructions block, the codex_status
    caveat, codex_capabilities' negative_scope, all six active tools' returns and docstrings,
    readonly_honesty_statement, the extra_context parameter contract, and workspace_root's
    own description, which now says it selects where Codex works, not what it can read. It is a
    ceiling, not a warrant — the probe shows reads far outside the workspace, not that every
    file the OS user can read is reachable, since a platform sandbox can still deny individual
    paths. Not breaking: no carrier ever promised reads were confined (every one said "may read"),
    so this widens a disclosure. The practical consequence for callers: narrowing workspace_root
    is no longer a mitigation for egress.

  • The egress disclosure names every AGENTS.md Codex auto-loads, not just the workspace's own.
    Two further sources reach the model, both previously understated: inside a repository the load
    walks up from the resolved workspace to the repository root, so a caller who narrows
    workspace_root to a subdirectory precisely in order to bound egress still ships the repo-root
    AGENTS.md — a file it never named (#472); and a user-global $CODEX_HOME/AGENTS.override.md,
    else $CODEX_HOME/AGENTS.md, loads on every call from any workspace — the AGENTS.md twin of
    the $CODEX_HOME/skills/ hole (#358). Neither --ignore-user-config nor
    -c project_doc_max_bytes=0 suppresses the user-global file, though the latter does suppress
    the workspace and ancestor files. Outside a repository there is no walk at all.
    cli_contract.SKILLS_DISCOVERY_FACT and every carrier state all three sources. Not breaking.

  • Every disclosure now states HOW a skill's body reaches OpenAI, not just that skills are
    discovered.
    The two halves of Codex's implicit context arrive differently: AGENTS.md
    content is auto-loaded, already in context before the turn, while a skill is
    auto-discovered as name and description only, and its body follows a read the model
    itself issues once it selects that skill (#480). The wire and the prose now agree on this, in
    one canonical sentence (cli_contract.SKILL_BODY_FACT) across the server instructions block,
    the codex_status caveat, negative_scope, all six active tools' returns and descriptions,
    SECURITY.md, README.md, COMPATIBILITY.md, the collaborating-with-codex skill and its
    fallback reference, and the upgrade docs. Four wire carriers gained disclosure rather than
    wording: codex_consult_async and codex_review_changes_async named the skills roots with no
    mechanism at all, as did both delegate returns. The warnings are stronger, not weaker —
    each site now says the metadata alone is enough for the model to select a skill, and that
    selecting it pulls the body to OpenAI even when the prompt names neither the skill nor the
    file. Not breaking. (#498, #501)

  • The dry-run previews no longer imply they bound what a paid call can send. codex_dry_run
    led with "Preview what a codex_review_changes call would send", so a clean preview read as
    "nothing sensitive will be sent". It cannot establish that: a dry run never invokes Codex, so
    the model's own reads have not happened yet and none can be listed, and those reads are not
    bounded by the work...

Read more

codex-in-claude v0.18.0

Choose a tag to compare

@github-actions github-actions released this 18 Aug 00:22
33da6e7

Added

  • cli_contract.PONTONIER_CONTRACT — the declarative CLI contract in the shared
    BackendContract shape, derivation-pinned against the legacy constants.
  • Surface-honesty gates via pontonier.testing: FORBIDDEN_SURFACE_PHRASES
    (cross-bridge contamination canaries and refused-mechanism claims) enforced
    against the built manifest.
  • backend.CodexBackend — this bridge's adapter on the frozen pontonier
    AgentBackend protocol (contract_api_version = 1), validated by an argv
    differential against the production command builder.

Changed

  • Every model-bearing run now goes through the pontonier AgentBackend adapter:
    codex.run_codex_exec stages via CodexBackend.prepare() (temp artifacts,
    argv from the shared builder, prompt over stdin, help-gate drops surfaced on
    PreparedRun.dropped_flags) and keeps only the execution step — timeouts,
    output byte caps, and event streaming stay this bridge's. The consult-only
    --skip-git-repo-check moved from an inline call-site flag to backend policy
    derived from the canonical kind, pinned by the argv differential test (which
    now compares against true production argv — it previously validated a variant
    without the flag). Wire snapshots are byte-identical; argv is unchanged for
    every tier.

  • Generic core machinery (jobs, worktree, gitdiff, redaction, runtime,
    gitproc, streamcap, idempotency, workspace, jsoncache) now comes from
    the shared pontonier library
    instead of the vendored _core/ package. This bridge's worktree knobs
    (cic-worktree- prefix, codex-in-claude@local baseline identity) are pinned
    in config.WORKTREE_CONFIG, so git-visible behavior is unchanged; all wire
    snapshots are byte-identical.

  • Docs and code comments retire the deleted _core/ package. CONTRIBUTING.md's one-way
    import rule named a directory that no longer exists, and SECURITY.md / COMPATIBILITY.md
    cited _core/redaction.py / _core/workspace.py as the authority for security-relevant
    behavior; all now point at pontonier.core. Eight source and test comments were updated the
    same way, and tests/test_backend.py no longer calls the protocol "provisional" while every
    other doc calls it frozen. No agent-visible surface changed — the built manifest is
    byte-identical, so no FINGERPRINT bump.

  • Runtime dependency bumps. fastmcp 3.4.5 → 3.4.7. The built manifest is byte-identical
    under the new version, so the agent-visible surface is unmoved and no FINGERPRINT bump follows.

  • Tracked Codex version is now 0.147. SUPPORTED_VERSIONS tracks (0, 147); a 0.146 CLI
    still runs and only draws the advisory codex_status warning. The docs/UPGRADING-CODEX.md
    procedure was run end to end against codex-cli 0.147.0, A/B'd against a side-by-side
    0.146.0 from npm (the retrieved binary authenticated clean against the committed 0.146.0
    help snapshots, and an npm-vs-Homebrew diff of the new version retired the cross-channel
    concern). Nothing this plugin sends or reads changed: all 11 ALWAYS_SEND_FLAGS, --model, and
    the three sandbox values are present, and the guarantee semantics were re-probed live —
    read-only blocked a write, workspace-write allowed the workspace write and blocked network
    egress, --output-last-message received the final message, and an --output-schema run
    validated against FINDINGS_OUTPUT_SCHEMA. The model_reasoning_effort config key is still
    applied (the backend rejection carried both [ReasoningEffortParam] and [reasoning.effort]),
    and codex exec still has no dedicated effort flag. Contract-drift stderr signatures still
    match. docs/codex-help/0.147.0/ carries fresh snapshots and the live integration suite
    passes against the new binary.

  • KNOWN_MODEL_SLUGS gains gpt-5.6-sol-wm. The bundled advisory fallback is refreshed from
    the 0.147.0-written models_cache.json. The catalog is backend-served rather than shipped in
    the binary, so this slug had already appeared under 0.146.0 — it is catalog drift the upgrade's
    slug diff caught, not a 0.147 change. The reasoning-effort discovery fields still hold their
    pinned shape.

  • --approve-for-me (new in 0.147.0) is deliberately not adopted, and cli_contract.py now
    records why alongside the other never-sent flags: it routes approval requests through an
    automatic review under the workspace-write sandbox, which would let a read-only-tier run
    acquire write capability without the caller electing a write tier.

  • App-server: the 0.146.00.147.0 generated-schema diff is additive only on the consumed
    surface — an optional extensions map on InitializeParams (not sent), an optional title on
    the import progress/completed per-item results (read tolerantly, ignored), and two new
    PlanType values, self_serve_business_prolite and enterprise_cbp_automation, already read as
    a free-form capped string. Ten unconsumed v2 ThreadSection* messages were added; none removed.

Fixed

  • Multi-line private-key blocks (PEM/PKCS8/OpenSSH/PGP) in gathered diffs and
    returned prose are now redacted statefully (via pontonier): the BEGIN/END
    markers stay visible, every body line between them is replaced with a
    [redacted: secret value] marker, and an unterminated block fails closed. Previously only the
    BEGIN marker was masked while the entire base64 body was sent.
  • Bare provider tokens are now redacted. The shared redactor adds patterns for github_pat_,
    glpat-, sk-ant-, npm_, and pypi- tokens. The vendored redactor already caught these in a
    labelled assignment (token = "…"), because its value-pattern matcher keys on the label; what
    changed is the unlabelled case — a bare token in prose, or a diff line with no key = in front
    of it, which that redactor passed through verbatim. Measured old-vs-new over both spellings: five
    improvements, and no payload where the new redactor leaks something the old one caught.
  • Redaction preserves the diff's trailing newline, so delegate diffs are
    git apply-able again (ports moonbridge's fix).
  • COMPATIBILITY.md corrects the 2026-08-02 "parent AGENTS.md above the git root is loaded"
    observation.
    That mechanism does not reproduce on 0.146.0 or 0.147.0: the parent codeword
    was absent from both binaries with a project AGENTS.md present, with it removed, and with
    --cd set to a repository subdirectory. The corrected behavior is that codex walks upward from
    the resolved workspace directory and stops at the git root. What is retracted is the
    mechanism, not the concern — because resolve_workspace returns an explicit workspace_root
    unchanged, the resolved workspace can be a subdirectory, and the walk then crosses above it
    (from repo/sub, codex loaded repo/AGENTS.md). The published "the resolved workspace's
    AGENTS.md" caveat therefore still understates egress and issue #472's conclusion stands.
    Correcting that published wording is a FINGERPRINT-bumping change tracked in #472, so this
    entry changes no agent-visible text and carries no bump.
  • config.py's extra-args comment no longer states a plugin-side narrowing as a codex fact.
    It claimed an attached -cKEY=VAL is "rejected"; codex accepts it (clap attached short-option
    value) on both 0.146.0 and 0.147.0. It is this parser that refuses it, because the
    attached-form split fires only on long --flag=value. Behavior is unchanged and
    safe-direction — the plugin passes through strictly less than codex would take.
  • Shared-core diagnostics stay inside the server's log configuration. Moving the core out of
    codex_in_claude._core made its loggers siblings of the server namespace rather than children,
    so pontonier.core.* records inherited none of the configured handlers and propagated to the
    stdlib root logger instead — the exact escape propagate = False exists to prevent, since an
    embedding host may have wired root to stdout (the stdio JSON-RPC channel). obs.configure() now
    configures the pontonier namespace alongside codex_in_claude, so library diagnostics honor
    CODEX_IN_CLAUDE_LOG_LEVEL/CODEX_IN_CLAUDE_LOG_FILE and reach the same stderr and file
    handlers.

codex-in-claude v0.17.0

Choose a tag to compare

@github-actions github-actions released this 03 Aug 02:09
61244b1

A secret-redaction release. The inline redactor was rebuilt around merged candidate spans so no
matcher can strand part of a secret another one covers whole; its labelled-secret pattern now
reaches quoted-JSON and bracket-subscripted keys without scrubbing ordinary source out of reviewed
diffs; two quadratic patterns were bounded; and a replacement that may be incomplete now says so
instead of advertising a completeness it doesn't have. Alongside that, codex_review_changes and
codex_dry_run disclose how a diff was redacted — files withheld whole versus files sent with
values masked inline — codex_capabilities declares the targeted MCP protocol revision and its
readOnlyHint reading, and the dry-run tools warn when the call they preview may exceed the
synchronous deadline. The tracked Codex version moves to 0.146. One breaking change: a blank
question or task is now rejected before any spend. The agent-visible surface changed nine times
(result fingerprint
codex-in-claude/0.1/schema-66schema-75, and the persisted RESULT_FORMAT 78), so
pre-1.0 this is a minor release; clients that cache by fingerprint re-fetch the contract.

Added

  • coverage.redaction distinguishes withheld files from inline masks on
    codex_review_changes and codex_dry_run (#433). The redacted omission reason previously
    conflated two different things a secret-looking diff can trigger: a whole file dropped (its path
    itself looked secret-bearing, e.g. .env) versus a file sent with one or more values masked
    inline. The new optional RedactionSummarywithheld_paths, masked_paths, and
    inline_masks (markers actually emitted, after span merging, not raw pattern candidates) —
    splits them, counting only content that lands in the retained, byte-capped diff text.
    meta.redacted_paths and DryRunResult.redacted_paths/redacted_paths_count are unchanged:
    still the single backward-compatible union of both path lists, and still codex_delegate's only
    redaction disclosure. The field is optional (so a Coverage persisted before it existed still
    replays) and the redacted reason can fire without it — a legacy-shaped producer, or a
    disclosure dropped entirely by byte-cap truncation — but the field is never populated without
    the reason. FINGERPRINT schema-74schema-75; RESULT_FORMAT 78 for the persisted
    Coverage. Additive, not breaking.
  • codex_capabilities declares the targeted MCP protocol revision via a new
    protocol_revision field ("2025-11-25"), previously derivable only by inspecting the
    initialize wire response (#423). Its description points at the new
    docs/adr/0004-mcp-2026-07-28-migration.md, which records why this server stays on 2025-11-25
    (verified FastMCP/mcp SDK support, not any spec-granted support window) and the per-feature
    migration plan for the deprecated pieces already in use. FINGERPRINT schema-70
    schema-71; additive, not breaking.
  • codex_capabilities documents the server's readOnlyHint reading via a new
    annotations_reading field, previously stated only in source comments (#426). The hint tracks
    whether a call changes observable state that outlives the response (a job record, committed
    spend) rather than file I/O — which is why codex_consult, codex_review_changes, and
    codex_delegate are readOnlyHint: false even though consult and review never write files,
    while the two dry-run tools, which create no job record, stay true. Consistency guards assert
    the claim against the live tool annotations. FINGERPRINT schema-71schema-72; additive,
    not breaking.
  • codex_dry_run and codex_delegate_dry_run advise when the previewed call may exceed the
    synchronous deadline
    via a new deadline_advisory field, described identically on both
    (#342). Non-null exactly when the previewed call would run the model and either its prompt
    exceeds 100,000 bytes or its resolved reasoning_effort is high/xhigh (an exact match — a
    near-miss like "Xhigh" is deliberately not treated as high); null whenever the call would run
    no model at all. It is a hint, not a refusal, and it names the previewed paid tool's own
    _async counterpart, never the dry-run tool's own name, which has none. FINGERPRINT
    schema-73schema-74; additive, not breaking.

Changed

  • Tracked Codex version is now 0.146. SUPPORTED_VERSIONS tracks (0, 146); a 0.145 CLI
    still runs and now warns as untracked (the gate is advisory and never blocks). The upgrade
    procedure was run end to end against codex-cli 0.146.0, A/B'd against a side-by-side
    0.145.0, and required no code change: help text for codex/exec/review/exec review is
    byte-identical, every guarantee-bearing flag and sandbox value is present, the drift signatures
    still match observed output, and the model catalog is unchanged. Semantics were re-probed rather
    than assumed — read-only still blocks writes, workspace-write still writes in-workspace while
    blocking network egress, --output-last-message still delivers, -c model_reasoning_effort is
    still applied, and structured output still conforms. Upstream additions were reviewed and none is
    consumed: a new app-server --help flag, two new app-server messages, an optional providerId
    and an ent26 PlanType value on the consumed schemas (the plan type is read as a free-form
    capped string, not an enum), and four new feature flags — including mcp_2026_07_28, still
    under development, which corroborates this release's decision to target MCP 2025-11-25.
    remote_plugin remains default-on, so the --disable remote_plugin isolation guarantee still
    applies and still fails closed.
  • The skills-discovery egress caveat now reads identically everywhere it appears (#427).
    Fifteen prose sites — the server instructions, the codex_status caveat, six
    ToolCapability.returns clauses, codex_capabilities' negative_scope, and six tool
    docstrings — stated the same fact (Codex auto-loads the resolved workspace's AGENTS.md and
    discovers skills in that workspace's .agents/skills/ and in the user-global
    $CODEX_HOME/skills/, and the plugin's isolation flags do not suppress any of it) in
    independently drifted wording. All now share one canonical sentence pair defined in
    cli_contract.py, already the single source of truth for every Codex CLI assumption. This is a
    wording convergence, not a byte-identical refactor — no carrier shared one sentence before — and
    no guarantee is removed or weakened; the three _async docstrings keep their deliberately
    lighter subset. tools/list grew 157 bytes, inside its existing budget. FINGERPRINT
    schema-72schema-73; not breaking.
  • Meta.timeout_seconds is now described — it was the only semantically-loaded Meta member
    published without a description (#413). It states which deadline the value is, by envelope: a
    synchronous paid call reports that call's own resolved deadline, post-clamp (10–600s); a
    background job's start handle, or a later codex_job_result fetch of that job's originating
    run, reports the job-lifecycle ceiling instead (job_max_seconds, default 1800, clamped
    60–7200); and invalid_arguments or internal_error, tied to no run, report the server's
    configured sync deadline. Wording only: FINGERPRINT schema-67schema-68,
    RESULT_FORMAT unmoved, not breaking.
  • The three sync tools' Progress & recovery paragraphs now describe job-record recovery
    correctly
    (#414). They named only codex_job_listcodex_job_result, omitting
    codex_job_status as the polling step in between, and framed recovery as a fallback for a
    dropped connection — when some MCP clients background a long tool call well before the server's
    own deadline. Wording only: FINGERPRINT schema-68schema-69, not breaking.

Fixed

  • BREAKING (agent surface): a blank question or task is now rejected before any spend
    (#411). An empty or whitespace-only value passed validation and bought a real Codex run that
    could produce nothing — the prompt builders strip it, so the model received framing scaffolding
    and no ask (a reported codex_consult(question=" ") burned 23,120 tokens and returned
    ok: true). codex_consult, codex_consult_async, codex_delegate, codex_delegate_async,
    and codex_delegate_dry_run now return invalid_arguments naming the offending argument, with
    a correct_arguments repair. Flagged breaking because it narrows an accepted value set: input
    that previously returned ok: true now returns an error. Blankness is Python's str.strip(),
    so U+00A0 is blank while U+200B counts as content, and the check sits after the byte-limit
    guard, so an oversize whitespace-only value still reports input_too_large. FINGERPRINT
    schema-66schema-67; RESULT_FORMAT unchanged.

  • Redaction no longer strands part of a secret behind a marker that looks complete (#443,
    #445). The inline patterns ran as sequential re.sub passes, each over the previous pass's
    output, and sub never revisits consumed text — so a matcher with a narrower value class could
    eat a prefix of a value a later matcher would have covered entirely: token=ghp_<20 chars>-tail
    came out as token=[redacted: secret value]-tail. The worse harm is not the disclosure but that
    the output advertised itself as fully redacted, suppressing the reaction a bare secret would
    provoke. Every pattern is now run with finditer against the original line, each candidate
    contributes the span it would replace, the spans are merged on strict overlap, and the line is
    rebuilt with one marker per merged interval — so the order of the pattern list no longer affects
    output at all. Touching (non-overlapping) candidates deliberately stay separate, and a preserved
    prefix (a labelled key, an Authorization: header...

Read more

codex-in-claude v0.16.0

Choose a tag to compare

@github-actions github-actions released this 29 Jul 00:24
3e6393c

A discovery-metadata and envelope-slimming release. Every tool now states its cost, its title, and
its stability tier in tools/list itself; codex_capabilities gains a summary default and a
contracts mode, so a client can fetch a schema or recheck a fingerprint without re-reading the
whole tool inventory; codex_job_list gains limit/status filters; and each codex:// resource
carries triage metadata a client can read before spending context on the body. Delivered success
envelopes stop sending explicit null meta members, and meta.roots_source now reports what the
MCP-roots probe actually saw on every envelope that reports it. Several capability and
documentation contracts that described something other than what was being sent are corrected. The
agent-visible surface changed ten times (result fingerprint codex-in-claude/0.1/schema-56
schema-66, and the persisted RESULT_FORMAT 67), so pre-1.0 this is a minor release;
clients that cache by fingerprint re-fetch the contract. Every change is backward-compatible — no
tool, field, or error code was removed or retyped.

Added

  • codex_capabilities accepts detail="contracts", which omits tool_details and returns
    everything else unchanged. The include_schemas fallback for resource-blind clients previously
    re-sent the whole tool inventory on every schema fetch; pairing it with contracts drops a
    schema fetch from 30,404 to 23,082 bytes, and detail="contracts" alone is a 3,787-byte
    fingerprint recheck for cache revalidation (was 11,109). tool_details is the only field
    removed, and it is already optional in the published schemas, so a contracts response still
    validates against both the tool's outputSchema and codex://capabilities-result — no schema
    change was needed. The new token lives on a separate CapabilitiesDetail Literal used only by
    this tool; the shared Detail stays two-valued, so the five other tools taking detail are
    unaffected. Backward-compatible: summary remains the default and both existing modes are
    unchanged.

  • Every tool now states its cost in its own description — five tools that previously relied
    on codex_capabilities alone (codex_consult, codex_review_changes, codex_delegate,
    codex_job_result, codex_job_consume_result) now say PAID or Free explicitly, and two
    more (codex_dry_run, codex_delegate_dry_run), which already stated NO model call and no spend in prose, were normalized onto the same Free token — so a client reading only
    tools/list gets one consistent cost marker across every tool.

  • Every cost marker now uses one canonical token — PAID — for active tools, Free — no model call for free ones — instead of near-miss variants (FREE —, a line-wrapped
    Free —, or bare mentions of "spend"). codex_transfer, codex_capabilities,
    codex_consult_async, codex_review_changes_async, and codex_delegate_async gain the
    literal marker; the three async PAID — blocks each point at the correct preview tool
    (codex_status only for codex_consult_async, codex_dry_run for
    codex_review_changes_async, codex_delegate_dry_run for codex_delegate_async), and all
    six active tools now say "every new call" rather than "every call" so the marker doesn't
    contradict idempotency_key's no-new-spend replay semantics.

  • Every tool now carries a title for human-facing pickers and a namespaced
    _meta stability tier, so a client reading only tools/list can see which tools are
    experimental.

  • codex_job_list gained optional limit (1-1000) and status filters to narrow the
    returned jobs. Both are purely opt-in: omitting limit (the default) still returns every
    job the store retains, so the tool every error's repair hint names as the way to recover
    a lost job_id never hides a row the server deliberately kept — the job store's own
    retention policy is the only server-side limiter, and a soft one, since running jobs are
    exempt from eviction. Only an explicit
    limit can truncate; when more jobs match, the response sets truncated: true with a
    truncation_hint pointing back at omitting limit (or narrowing with status) — the
    extra rows are dropped, not paged, so there is no cursor. Running jobs are never evicted,
    so a busy workspace can retain more rows than limit's 1000 ceiling can ask for, which is
    why omitting it is the only complete listing. The tool's codex_capabilities record
    advertises both params and the cap-not-a-page semantics, so a client treating the
    detail="full" inventory as authoritative sees them too (audit F5, #396, #395).

  • meta.roots_source (and the matching field on codex_dry_run/codex_delegate_dry_run)
    reports which of three states the MCP-roots probe saw: client (the client advertised the
    roots capability and the probe returned, possibly an empty list), not_negotiated (this client
    never advertised the roots capability — pass workspace_root instead), or probe_failed
    (roots were advertised but the call errored this turn — retrying may help). It reports the
    probe, not where the workspace came from — workspace_source answers that. Previously all
    three collapsed into a silent empty list and a fallback to the server's own cwd; roots stays
    advisory either way, and workspace_root remains the durable path (audit F8). Which run the
    value describes now depends on the envelope, and codex://result-meta states the rule: when
    present, a DELIVERED consult/review/delegate result reports the ORIGINATING run (like
    meta.tier) whether returned synchronously or fetched later, while a *_async handle, a
    dry-run preview, and an error a codex_job_* call generates instead of delivering a stored
    result each report the CURRENT call — so a replay handle and the result later fetched for the
    same job may legitimately differ. Absence implies none of that: it means only that the value
    was not reported (an unexpected server-side internal_error, for instance, is built without
    one), so never infer a run's age or identity from a missing key. Bumps the persisted result-format (RESULT_FORMAT 67)
    for the new Meta field; not breaking.

  • Each codex:// resource now carries a namespaced _meta["dev.bconnelly.codex-in-claude/triage"]
    so an agent can decide whether a body is worth the context before reading it: the five static
    schema resources declare size_bytes (computed from the payload at registration, so it cannot
    drift from the body); codex://models, whose body is a refreshed cache, declares volatile: true with a freshness_via pointer to the payload's fetched_at field instead of a size that
    would go stale (audit F4). size_bytes now counts the UTF-8-encoded bytes rather than
    len() of the JSON string (Copilot review of #385): today's payloads are pure ASCII under
    json.dumps's default ensure_ascii=True, so the count is unchanged for all five resources,
    but the name is now true by construction instead of by coincidence of that default.

Changed

  • Delivered codex_consult/codex_review_changes/codex_delegate success envelopes now omit
    meta members whose value is null, instead of sending a run of explicit null keys on every
    call — between 5 and 17 of them across the representative envelopes in
    tests/fixtures/wire_shape_snapshot.json, though a real call's count varies with which
    members apply to it.
    A key's absence means exactly what the null meant — not applicable, or not reported for this
    run — so read meta with a null-safe accessor rather than by testing key presence. Measured
    against those same representative envelopes: ~6–37% smaller at detail="summary", and the
    same ~6–37% at full; the saving scales with how many members the run leaves
    inapplicable, so the sparsest envelope gains most. The six required meta members are
    always present and empty arrays stay empty arrays; everything outside meta is delivered
    verbatim, so top-level fields (including codex_delegate's diff, which is null when a run
    proposes no changes) and all of raw_response keep their keys. The *_async job handle and
    codex_job_status are unaffected. Trimming happens on delivery, so the stored result.json
    is byte-for-byte unchanged (RESULT_FORMAT stays 7 and already-stored job results stay
    readable) and a replayed result still matches a fresh synchronous one. Not breaking: the
    published output schemas and codex://result-meta already accept absence for every affected
    field. Bumps FINGERPRINT (schema-60schema-61); the rule is published on
    codex://result-meta (#334).
  • codex_capabilities now defaults to detail="summary", returning only the per-tool facts
    tools/list does not already carry (name, cost, stability, error_codes, and, for the
    *_async tools only, async_lifecycle). Pass detail="full" for the previous payload. The
    extra_context parameter contract moved its full text to codex://params and
    idempotency_key's inline summary was compressed. The durable size win is codex_capabilities'
    own response — 21,763 → 11,109 bytes (−49%) — but that is paid only by clients that call the
    tool, not by every client the way tools/list is.
  • Net effect on the preloaded discovery surface: this release's other additions (per-tool cost
    markers, titles, stability tiers, codex_job_list filters, roots_source provenance,
    resource triage metadata) outgrew the compression above for every client, not just
    codex_capabilities callers. tools/list went from 79,242 to 83,895 bytes (+5.9%). That is a
    deliberate trade: a larger preloaded surface in exchange for cost/stability/next-step metadata
    that was previously missing or unreachable.

Fixed

  • codex_capabilities delivered the per-tool stability key in one detail mode but not the
    other
    (#399). detail="summary" force-added stability: null...
Read more

codex-in-claude v0.15.0

Choose a tag to compare

@github-actions github-actions released this 22 Jul 23:39
2916e93

A status-signal and diff-gather-hardening release. codex_status learns to report an
administrative spend block, codex_job_status/codex_job_list expose a finished job's
success/failure without a fetch, the diff-gather paths gain consistency and bounded-memory
guarantees across every review scope, and several capability-discovery contracts are corrected to
match what they advertise. Tracked Codex is bumped to 0.145. The agent-visible surface changed
(result fingerprint codex-in-claude/0.1/schema-49schema-56, and the persisted
RESULT_FORMAT 46), so pre-1.0 this is a minor release; clients that cache by fingerprint
re-fetch the contract. Every change is backward-compatible — no tool, field, or error code was
removed or retyped.

Added

  • codex_status reports an administrative spend block (#359). codex 0.145 added
    spendControlReached to the app-server's rate-limit snapshot — a spend control the backend
    enforces, distinct from a quota window: no reset clears it. rate_limit now carries
    spend_control_reached (true | false | null) and rate_limit.status gains the value
    blocked, which outranks every window-derived verdict because its remedy is not waiting; it
    reports limiting_window: null and a note saying a reset will not clear it. The tri-state is
    load-bearing — null is not false, and a null never downgrades a healthy window reading to
    unknown (which would reintroduce the permanent-unknown failure #321 removed). The bundled
    collaborating-with-codex skill gains the matching rule: blocked is the one non-advisory
    rate-limit state — refuse the paid call rather than deferring it. Bumps the persisted
    result-format (RESULT_FORMAT 56) for the new status value; not breaking.

  • result_ok on job status and list entries (#335). codex_job_status and each
    codex_job_list entry now carry result_ok — a finished job's producer-declared outcome
    (true = success, false = a stored error envelope, null = running, unclassifiable, or a
    record finalized before this field) — so a stored failure can be triaged without a per-job fetch.
    It reports the outcome recorded when the result was written and does not guarantee the payload
    is still readable across releases. codex_capabilities gains an
    async_lifecycle.result_ok_field entry for structural discovery. Backward-compatible output
    addition; not breaking.

Changed

  • Diff-gather git reads are now counted in bounded memory (#331, #350, #351, #353). The
    untracked-file listing, the tracked-diff --numstat summary, and the untracked-count stderr read
    — all reached on the default codex_review_changes and free codex_dry_run paths — previously
    materialized whole git outputs unbounded in the workspace's changed-file count. They now stream
    through a single shared bounded runner, so a pathological workspace can neither exhaust server
    memory nor stall a review past its deadline, and a latent stderr deadlock is removed. The same
    work fixed a real corruption bug: a carriage return in a git-produced filename was rewritten by
    Python's universal-newline translation before the NUL-splitter saw it, silently omitting one file
    while still counting it as included — a quiet coverage-contract violation (#353). Reported counts
    and error vocabulary are unchanged, so no fingerprint change.

  • Every egress caveat now discloses that user-global Codex skills auto-load (#358). Skills under
    $CODEX_HOME/skills/ (default ~/.codex/skills/) are discovered from outside the workspace
    and their bodies can reach OpenAI on any active call, despite --ignore-user-config — pre-existing
    behavior (verified against codex-cli 0.144.1 and 0.145.0), not new. The disclosure is
    corrected across the server instructions, all six tool descriptions and their capability entries,
    codex_capabilities' negative scope, README.md, SECURITY.md, COMPATIBILITY.md,
    cli_contract.py, and the collaborating-with-codex skill. A reword of covered descriptions, so
    it bumps the fingerprint; not breaking — the contract only ever promised ignore-config
    drops $CODEX_HOME/config.toml, never that all $CODEX_HOME content stays local.

  • Tracked Codex version bumped to 0.145 (#361). SUPPORTED_VERSIONS now tracks (0, 145);
    the CLI contract, help snapshots, and KNOWN_MODEL_SLUGS fallback are verified against
    codex-cli 0.145.0, which required no code change — help text, sandbox values, drift/auth
    signatures, and reasoning-effort handling are all intact, and the app-server schema diff is
    additive-only for the surface this plugin consumes. Advisory only: an untracked version warns in
    codex_status but never blocks, and the CODEX_IN_CLAUDE_SUPPORTED_VERSIONS override still
    applies. No agent-visible surface change, so no fingerprint bump.

Fixed

  • Diff gathers are now consistency-checked and atomic across every review scope (#336, #355). A
    gather runs its context summary and the transmitted diff as separate git invocations, so a
    concurrent edit or ref move between them could make the summary and the reviewed patch describe
    different content while coverage.status still reported "complete". working_tree reviews now
    bracket that window with a best-effort porcelain state token; on a mismatch they set a new
    tree_changed_during_gather value on coverage.omission_reasons, degrading coverage to partial
    and (via the #319 rules) a pass verdict to unknown. It is a consistency caveat, not a claim
    that specific content was omitted, and it does not trip on a content-only re-edit — so complete
    is documented as no longer proof the tree held still. branch and commit reviews now resolve
    their refs to immutable commit object IDs once, up front, so the summary and diff cannot split
    under a mid-gather commit/reset/checkout; an unborn HEAD fails closed, a concurrent HEAD move is
    disclosed via the same token, and a commit=<annotated-tag> review peels the tag to its commit.
    Widens CoverageOmissionReason and bumps the persisted result-format (RESULT_FORMAT 45,
    since an older closed-schema reader could reject the new enum value); not breaking.

  • Capability-discovery contracts corrected to match what they advertise (#337, #370, #372, #373).
    Several codex_capabilities and error-envelope contracts were narrower or staler than their
    promise. fingerprint_covers said any change in a covered category bumps the fingerprint but
    silently excluded release-identity fields (serverInfo.version, the capabilities version); it
    now carries a description disclosing the carve-out in both directions, so a caching client can
    trust that an unchanged fingerprint means an unchanged contract. The codex_capabilities tool
    description advertised only two of the five include_schemas tokens (the parameter schema
    already listed all five), hiding the resource-blind route to parameter-contracts. And
    invalid_arguments omitted allowed_values for a rejected list[Literal] element — the one
    parameter shape the domain resolver did not read — on the very field whose repair hint says to use
    those values. The include_schemas token set is additionally drift-proofed against its runtime
    payload by an exact-equality test. Wording and coverage corrections that widen what is documented
    and weaken no guarantee — the fingerprint bump is for the fingerprint_covers and tool-
    description changes (the allowed_values fix is per-call envelope data, no discovered surface);
    not breaking.

  • invalid_reasoning_effort gives the local pre-spend guard a provenance-specific repair (#332).
    The code is emitted from two paths: the Codex backend rejecting a sent effort (table repair
    correct_arguments + codex_models, correct there) and the local pre-spend guard refusing a
    hostile resolved value before any subprocess (zero spend). The guard previously inherited the
    backend repair, misdirecting an agent that branches on error.repair to a useless codex_models
    call. It now emits a provenance-specific repair with no tool: correct_config when the
    invalid value is the resolved CODEX_IN_CLAUDE_REASONING_EFFORT default, correct_arguments when
    it is an explicit per-call argument. Bumps the fingerprint for the corrected parameter contract;
    not breaking (correct_config is already a published RepairStep).

codex-in-claude v0.14.0

Choose a tag to compare

@github-actions github-actions released this 20 Jul 02:41
6860fcd

A discovery-slimming and sync-timeout release. The tools/list catalog gets lighter and a new
codex://params resource becomes the single home for the full parameter contracts, the sync tools
steer long-running work to their _async variants at selection time, and the built-in sync
timeout_seconds default rises from 180 to 300. The agent-visible surface changed (result
fingerprint codex-in-claude/0.1/schema-46schema-49), so pre-1.0 this is
a minor release; clients that cache by fingerprint re-fetch the contract. Every change is
backward-compatible — no tool, field, or error code was removed or retyped.

Added

  • codex://params resource and parameter-contracts capabilities fold-in (#333). A new
    read-only resource serves the full lifecycle/validation semantics for parameters whose
    tools/list description is a compressed summary, backed by a single-source
    PARAMETER_CONTRACTS registry so the inline summary and the resource body cannot drift.
    codex_capabilities(include_schemas=["parameter-contracts"]) embeds the same document for
    resource-blind clients. Its content is guarded by the new parameter_contracts
    FINGERPRINT_COVERS category and the manifest snapshot.

Changed

  • Slimmed the tools/list catalog (#333). MCP inlines each parameter description into every
    tool's schema, so a long shared description repeats on the wire. The idempotency_key and
    reasoning_effort inline descriptions are compressed to their selection-, safety-, and
    spend-critical facts (the full lifecycle/validation detail moves to codex://params),
    workspace_root/isolation are tightened, and the sync/async tool docstrings are slimmed —
    reducing the serialized tools catalog by ~6% (~85.2 KB → ~80.2 KB, snapshot measure) with
    no weakened guarantee: a table-driven per-tool freeze test asserts every egress/security
    guarantee (raw-input, files-read, auto-loaded AGENTS.md/.agents/skills, isolation, best-
    effort redaction, delegate no-network, review diff-redaction) still ships inline. This bumps the
    result fingerprint but is not breaking; the deeper ≤60 KB target requires opaquing the output
    schemas (tracked separately).

  • Sync tools steer long-running work to their _async variants, and the default sync
    timeout_seconds rises from 180 to 300
    (#338, #341). Two changes to how the synchronous tools
    handle work that can outlast a foreground call:

    • The codex_consult / codex_review_changes / codex_delegate descriptions, their _async
      counterparts, all six codex_capabilities use_when entries, and the server instructions
      block now name the shapes that can exceed the synchronous deadline — a high-reasoning-effort or
      broad repo-grounded consult, a multi-file or whole-branch review, or a substantial
      implementation task — and recommend the matching _async tool, so the steer reaches the agent
      at tool-selection time instead of only in the post-timeout repair, after the paid run was
      already lost.
    • The built-in default sync timeout_seconds rises from 180 to 300: a sync call that omits
      timeout_seconds now waits up to 300s before terminating. The 10–600s clamp and the
      CODEX_IN_CLAUDE_TIMEOUT_SECONDS operator override are unchanged, and a caller wanting the
      prior deadline can pass timeout_seconds=180. 300 is the smallest round value that recovers the
      mid-tier consult/review runs observed exceeding the old 180s cap; the destructive >~420s cliff
      stays the domain of the _async variants (separate 1800s job deadline), so the raise reduces
      the frequency of mid-tier sync timeouts rather than removing the cliff. A longer sync deadline
      only helps a client whose own foreground window is at least the server deadline; a client with a
      short window already backgrounds long sync calls, and the timeout_seconds/env override remains
      the escape hatch either way.

    The collaborating-with-codex skill routing and the /codex:consult|review|delegate command
    prompts carry the same steer. Wording and default-value changes that narrow no input and weaken no
    guarantee — the deadline was already documented as overridable — so they move the result
    fingerprint but are not breaking. A codex_dry_run size advisory remains tracked separately
    (#342).

  • Internal: the stripped git-subprocess environment is now built by a single
    gitdiff._base_git_env() helper shared across _core (previously duplicated at five
    call sites), so the hardening posture cannot drift between them.

Fixed

  • Untracked-file handling now honors the user's global gitignore (#330). The git
    subprocesses that enumerate untracked files run with a HOME-stripped environment
    (deliberate hardening — no user hooks/fsmonitor/attributes), which also prevented git
    from resolving the user's global excludes (core.excludesFile from global config,
    or the default ~/.config/git/ignore / $XDG_CONFIG_HOME/git/ignore). As a result a
    globally-ignored file (e.g. a ~/.config/git/ignore-listed .claude/settings.local.json)
    was misclassified as untracked: it inflated the untracked_files_detected /
    delegate-plan untracked counts, and under untracked="include" its contents were
    gathered and sent to OpenAI
    , contrary to the documented "non-ignored untracked files"
    contract. The effective core.excludesFile is now resolved from the server's own
    environment (mirroring git's own precedence, including a repo-local override) and passed
    explicitly as -c core.excludesFile=<path> to only the untracked-enumeration calls, so
    the global ignore layer is honored without restoring HOME (no other global config
    becomes readable). The resolver drops inherited GIT_DIR-family variables so a stray
    GIT_DIR cannot anchor resolution to another repo, and GIT_CONFIG (which only
    git config honors) so it mirrors what ls-files actually reads. Repo-local
    (.gitignore, .git/info/exclude) and local/system core.excludesFile layers with
    ordinary absolute or relative paths were already honored; a ~-containing local/system
    core.excludesFile previously failed to expand under the HOME-stripped child (a fatal
    error) and now resolves too, since the value is ~-expanded in the server. Behavior-only
    fix restoring the already-documented meaning — no change to the agent-visible schema or
    descriptions, so the result fingerprint is unchanged.

codex-in-claude v0.13.0

Choose a tag to compare

@github-actions github-actions released this 15 Jul 13:58
f28d8a3

A review-honesty and rate-limit-recovery release. codex_review_changes no longer reports an
unreviewed working tree — the all-untracked shape most agent work takes — as a high-confidence
pass, and codex_status reads live rate-limit quota from the codex app-server again after
codex 0.144 moved it off the codex exec stream. Both are breaking on the agent-visible
surface: the result fingerprint moves twice (codex-in-claude/0.1/schema-44schema-46) and
RESULT_FORMAT twice (24), so pre-1.0 this is a minor release and clients that cache by
fingerprint re-fetch the contract.

Changed

  • codex_review_changes no longer reports an unreviewed tree as a high-confidence pass
    (#319, breaking). A working tree whose only changes were untracked (new) files — the most
    common shape of agent work — used to short-circuit to verdict: "pass", confidence: "high"
    with no model call, indistinguishable from a genuinely clean review. Now:

    • The result carries top-level review_status (completed | not_run) and a coverage object
      (status complete | partial; pathspec-scoped untracked_files_detected/included/omitted
      counts, null outside working_tree scope; a closed omission_reasons set of untracked_omitted
      / truncated / redacted). Untracked files are inventoried with git ls-files --others — a
      count only, no contents read, so the blind spot is disclosed at zero egress.
    • A review that never ran the model returns verdict: "unknown", confidence: "low",
      review_status: "not_run"never pass. A model pass over partial coverage (omitted
      untracked files, a truncated diff, or a redacted file) is surfaced as unknown/low with the
      caveat prefixed to summary; concrete fail/concerns findings are always retained.
    • A new untracked input (explicit_only default | include | exclude) on
      codex_review_changes, codex_review_changes_async, and codex_dry_run. explicit_only
      preserves #74 (only untracked files named in paths are reviewed); include reviews every
      non-ignored untracked file (opt-in egress — it sends their contents); exclude includes none.
    • codex_dry_run now reports would_call_model and the same coverage object, and its
      prompt_bytes is 0 when the previewed call would send nothing — matching the paid path
      instead of reporting the size of a prompt never sent (#320).
    • Git invocations in the diff-gathering path now run with -c core.fsmonitor=false, so a
      working-tree review of an untrusted repo cannot execute a repo-configured fsmonitor program in
      the server process.
    • Hardening (from an implementation review): the untracked inventory is stream-counted in
      bounded chunks (an untrusted workspace with arbitrarily many untracked files cannot exhaust
      memory); an invalid untracked policy reaching the core is rejected as invalid_arguments
      rather than silently behaving like exclude; the coverage counts come from a single
      enumeration so detected == included + omitted can't be violated under concurrent mutation,
      and Coverage now validates that invariant; review_status/would_call_model are required
      (no unsafe positive default); and the empty-review repair hint is tailored to the active
      untracked policy.

    Bumps FINGERPRINT (schema-44schema-45) and RESULT_FORMAT (23); clients that
    cache by fingerprint re-fetch the contract, and cross-release job replay of a review result
    written by an older version is refused rather than misread.

  • codex_delegate_dry_run's worktree preview counts in bounded memory (#323, #326). All three
    counts in worktree.plan() — untracked files, tracked files/bytes (git ls-tree -r --long), and
    uncommitted tracked files (git diff --numstat) — previously materialized their whole git listing
    in memory. The untracked count now delegates to the shared gitdiff.count_untracked inventory
    (the same NUL-delimited, fsmonitor-hardened enumeration codex_review_changes/codex_dry_run
    use), and the other two stream through a new shared _core/gitproc.run_lines runner (bounded
    per-line reader, concurrent capped stderr drain, process-group kill/reap on timeout or consumer
    failure — lifecycle guarantees ported from the diff streamer), so a repo with a pathological
    number of tracked, changed, or untracked files is counted without exhausting memory. Reported
    counts and failure semantics are unchanged — a git failure surfaces as a structured
    worktree_error (or, for numstat, still degrades to 0) instead of a silently-authoritative
    0 — so no fingerprint change. (The newline over-count originally filed as #323 did not
    reproduce: git C-quotes control characters, newline included, by default, so plan()'s non--z
    line-count was already correct.)

Fixed

  • codex_status reports live rate-limit quota again on codex 0.144+ (#321, breaking).
    codex 0.144 removed the token_count event that carried the quota block on the codex exec
    stream, so rate_limit had gone permanently unknown while the note told you to "run any Codex
    call to populate it" — advice that could never work. The data had moved to the app-server
    protocol, not disappeared. Now:

    • codex_status fetches quota live from codex app-server (account/rateLimits/read) — a
      read-only call with no model-token spend — reusing the hardened one-shot client that backs
      codex_transfer. The read is ephemeral: nothing is persisted, so codex_status stays a
      genuinely read-only call and no stale cache can mislead a spend decision. rate_limit.source
      is app_server_live.
    • Windows are re-slotted by duration, not by the app-server's slot order: primary is the
      shorter/rolling window (historically 5-hour), secondary the longer (weekly). The 0.144
      app-server reports only the windows that currently bind an account and may place the weekly
      window in the primary slot with no secondary — so a naive field rename would have kept the
      bug. An absent window is no longer treated as "unobserved," so a single healthy window now
      correctly reports available instead of a permanent unknown.
    • New rate_limit.status value unavailable (this codex/account exposes no quota data) and
      rate_limit.source value app_server_live; codex_status's meaning changes from a cached
      paid-run snapshot to a live read (breaking under the versioning rules — a closed-schema
      output meaning changed, and meta.rate_limit is now null on current CLIs). A read that finds
      the method missing, the protocol drifted, or a malformed result is surfaced as unavailable
      (never as a plausible "no quota") with a note that the plugin may need an update — a loud
      signal, not another silent unknown. A committed real-shape fixture plus an integration test
      against the live app-server guard against the next such drift.
    • Untrusted app-server output is hardened: planType is length-bounded and
      rateLimitReachedType is accepted only from the known enum (an unknown value is dropped, never
      trusted as a false exhausted); a cached reason code degrades to unknown once every window
      has reset; a pathological numeric field (e.g. a 400-digit usedPercent) degrades to absent
      instead of raising; two windows are duration-sorted so primary is always the shorter horizon;
      and the read response is correlated on an unpredictable request id so a prequeued/unsolicited
      message can't be trusted as quota.
    • The dead exec-stream quota parser (normalize.parse_rate_limit), the per-run capture, and the
      snapshot cache (CODEX_IN_CLAUDE_RATE_LIMIT_FILE) are removed.

    Bumps FINGERPRINT (schema-45schema-46) and RESULT_FORMAT (34) for the added
    enum values and the changed meaning of the rate_limit block.