Skip to content

codex-in-claude v0.20.0

Choose a tag to compare

@github-actions github-actions released this 26 Aug 23:56
· 19 commits to main since this release
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).