Skip to content

release: v1.1.0 — cbepx fork of codex-plugin-cc - #1

Merged
CBEPX merged 49 commits into
mainfrom
release/v1.1.0
Aug 27, 2026
Merged

release: v1.1.0 — cbepx fork of codex-plugin-cc#1
CBEPX merged 49 commits into
mainfrom
release/v1.1.0

Conversation

@CBEPX

@CBEPX CBEPX commented Aug 27, 2026

Copy link
Copy Markdown
Owner

1.1.0 — 2026-08-27

Fork of openai/codex-plugin-cc 1.0.6 (db52e28). Marketplace cbepx, plugin name unchanged (codex).

Merged from upstream pull requests

Fork changes

  • Slash-command arguments reach the companion through a quoted heredoc on stdin (--args-stdin) instead of a shell string: Claude Code substitutes $ARGUMENTS before bash runs, so $(...)/backticks in a prompt used to execute on the host shell, outside Codex's sandbox. Rescue job ids are validated before use. /codex:rescue keeps the two channels separate — the request prose goes to --prompt-file through its own quoted heredoc so quotes, backslashes and newlines survive byte-exact, while --args-stdin carries only runtime flags — and randomizes both heredoc delimiters per call; the other seven command bodies keep the fixed CODEX_ARGS delimiter because their payload is only flags and job ids.
  • Approval requests (execCommandApproval, applyPatchApproval, item/commandExecution/requestApproval, item/fileChange/requestApproval, item/permissions/requestApproval) are answered with each type's refusal variant instead of a -32601 protocol error that made --write turns fail or hang.
  • Background task records are written before the worker is spawned (a fast worker used to find no record and exit while the launch reported queued), and the worker reads the full request — including --config values — from a private one-shot jobs/<id>.request.json (mode 0600); the job record status/result echo keeps secret-looking config values redacted.
  • Model and reasoning effort are sent per thread via thread/start.config (model, review_model for native review, model_reasoning_effort); generic --config pairs are applied first, dedicated flags override them; --effort now works on review and adversarial-review.
  • Repeatable --config key=value on task, review, adversarial-review forwards any config.toml override to the thread (values are JSON-parsed; quote a literal string as '"true"'). Prompt-taking commands stop option parsing at the first positional, so prompt text like ls -R is never mis-parsed.
  • --resume-last opens a fresh app-server session (cold resume) so --config, sandbox and approval policy take effect, and never sends model on thread/resume (it would drop the persisted model); the resumed turn's model/effort ride on turn/start.
  • All MCP elicitations are declined (no operator is present); URL/form flows must be completed in an interactive Codex session.
  • /codex:rescue is synchronous by default without the Agent tool: task --backgroundstatus --wait in ≤9-minute slices (job id carried literally between Bash calls) → result; launch failures stop immediately with visible stderr; Agent only for --background; --write is never added unless the user explicitly asked Codex to modify files.
  • /codex:rescue asks before continuing an existing Codex thread (Continue current Codex thread / Start a new Codex thread) instead of resuming silently; its allowed-tools is now Bash, AskUserQuestion, Agent because the body is multi-command shell.
  • A resume refuses to start a second turn on a thread that a queued or running job is still using, including a job from another Claude session.
  • Model aliases: sol, luna, terra, mini (plus spark); rescue agent has no pinned model:; runtime skill mentions $agent-compat:skill-router for uncommon domains.
  • Stop-gate script timeout (13 min) is below the hook timeout (15 min); spawnSync uses SIGKILL and a 16 MiB buffer.
  • Hermetic test environment (tests/test-env.mjs); CI on push; npm run build type-checks the JSDoc.

1.0.6 and earlier

See upstream releases: https://github.com/openai/codex-plugin-cc/releases

Reviews: per-task spec+quality gates (Claude), plan + merge-batch + Task 7 + whole-branch adversarial reviews (Codex gpt-5.6-sol), final whole-branch review (Claude opus); all findings fixed or ruled in the SDD ledger. Tests 91 → 142, npm run build and claude plugin validate --strict pass.

🤖 Generated with Claude Code

dxcmb and others added 30 commits June 23, 2026 13:40
The stop-time review gate has no built-in bound: it keeps blocking the
stop while Codex returns BLOCK, which can create a long-running
Claude/Codex loop (as the README itself warns).

This adds an opt-in cap via the CODEX_REVIEW_GATE_MAX_ROUNDS env var.
When set to a positive integer, the gate allows the stop after that many
consecutive blocked rounds in a session. Unset/0 keeps the previous
unbounded behavior. Rounds are counted per session via stop_hook_active
and persisted in the existing per-workspace state config.
… them

handleServerRequest rejected every server->client request with -32601
"Unsupported server request". Connectors surfaced as `codex_apps` (e.g.
ChatGPT connectors) request the operator's consent via an
`mcpServer/elicitation/request`, delivered as a server->client request.
Because this client runs Codex non-interactively, that request was never
answered: the background runner returned "user rejected MCP tool call" and
`codex exec` / `codex mcp-server` hung on it.

Answer the elicitation with { action: "accept" } so connectors the operator
has already enabled can run; unknown server requests still get -32601. Adds
a unit test and exports AppServerClientBase for it.

Fixes openai#499

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Reject unrecognized --options instead of swallowing them into the prompt, and print usage for --help/-h without dispatching a Codex thread.

Co-authored-by: Cursor <cursoragent@cursor.com>
Keep the rescue subagent's sole task invocation in the foreground so it returns completed stdout. Explicit background mode remains owned by the outer rescue command, which backgrounds the entire subagent.
`--effort max` and `--effort ultra` were rejected by the companion even
though Codex supports both. GPT-5.6 models advertise them as reasoning
levels, so the plugin was the only thing blocking them:

    $ codex debug models
    gpt-5.6-sol    efforts=[low,medium,high,xhigh,max,ultra]
    gpt-5.6-terra  efforts=[low,medium,high,xhigh,max,ultra]
    gpt-5.6-luna   efforts=[low,medium,high,xhigh,max]
    gpt-5.5        efforts=[low,medium,high,xhigh]

Codex's own docs string agrees: "GPT-5.6 supports none, low, medium,
high, xhigh, and max."

The app-server protocol does not model effort as a closed enum. In the
generated types, `TurnStartParams.effort` is a `ReasoningEffort`, and
`ReasoningEffort` is `string` — Codex validates the value against the
reasoning levels the selected model advertises. Because the companion
kept its own hardcoded list, it fell behind: it still accepts `none`
and `minimal`, which no model in the current catalog advertises, while
rejecting `max` and `ultra`, which the current models do.

Verified end to end against a real Codex run:

    $ node codex-companion.mjs task --model gpt-5.6-luna --effort max \
        "Reply with exactly: OK"
    [codex] Turn completed.
    OK

Per-model validation stays with Codex, which is where the model catalog
lives; the companion only rejects values Codex has no variant for.
`handleReviewCommand` accepted `--model`/`-m` but forwarded the raw string to
`executeReviewRun`, so `normalizeRequestedModel()` — the only thing that maps
`MODEL_ALIASES` — never ran on the review path. `--model spark` reached
`thread/start` as the literal `spark` and came back as:

  The 'spark' model is not supported when using Codex with a ChatGPT account.

which names the account as the cause when the account is fine and `spark` was
never a model id. The alias is documented for the runtime in
skills/codex-cli-runtime/SKILL.md and agents/codex-rescue.md with nothing
marking it task-only.

Normalize in `handleReviewCommand` the way `handleTask` already does, so both
command families resolve aliases identically.

Tests: the fake app-server now records the model it receives on `thread/start`
(it only recorded `turn/start`, so nothing could observe the review path), plus
a regression test per command mirroring the existing task-path one. Both fail
on main with `actual: 'spark', expected: 'gpt-5.3-codex-spark'`.

Fixes openai#687

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QdCdeAZa2tCJjFq69meyK9
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
# Conflicts:
#	tests/runtime.test.mjs
# Conflicts:
#	tests/fake-codex-fixture.mjs
…es, verification)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
# Conflicts:
#	tests/fake-codex-fixture.mjs
CBEPX and others added 19 commits August 27, 2026 15:01
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…tached rescue agent

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…5.6 model aliases

Model and reasoning effort are sent via thread/start.config (ReviewStartParams has no such fields; thread/start.model is unreliable). Closes upstream openai#476 openai#651 openai#468 openai#408 for this fork.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Form-mode elicitations require structured content; accepting with content: null lets the tool call proceed without the values it asked for.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…pt-5.6 aliases, agent-compat hint

Claude Code >=2.1.232 runs every Agent subagent in the background, so the default rescue path now drives the companion directly: task --background, status --wait slices, result.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…hread/resume

A broker-backed app-server keeps the thread loaded, so thread/resume is a hot rejoin and its config/approvalPolicy/sandbox overrides are ignored (app-server 0.150.1). Resume now spawns its own session. A top-level thread/resume.model sets has_model_resume_override and blocks restoring the persisted model/provider/effort, so it is dropped; model and effort ride on turn/start. Also restores the tsc gate broken by the buildThreadConfig JSDoc.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…n skill/agent with detached flow, never default to --write

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…in, never inside shell strings

Claude Code substitutes $ARGUMENTS (and a rescue request's text) into the
command body before bash runs it, so any $(...) or backtick the user typed
executed on the host shell, outside Codex's sandbox. Every command body now
feeds the raw argument string through a quoted heredoc on stdin, and the
companion's new global --args-stdin flag tokenizes it with the shell-like
splitter normalizeArgv already used — no shell involved. Rescue job ids are
validated against ^[A-Za-z0-9_-]+$ before use.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…protocol error

`--write` runs use approvalPolicy "on-request", so app-server sends approval
requests back to the client; answering them with -32601 made the turn error out
or hang. This client is non-interactive, so each approval now gets its own
type's refusal variant from the generated protocol types: execCommandApproval
and applyPatchApproval take a ReviewDecision denial with a reason string,
item/commandExecution and item/fileChange take the "decline" enum (no reason
field exists), and item/permissions has no refusal variant at all — granting
nothing for the turn is its fail-closed answer. Unknown methods still get
-32601.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…client

Accepting a url-mode elicitation fabricates operator consent: it tells the MCP
server that an out-of-band authorization succeeded when nobody completed it.
No mode may be accepted here — there is no operator. Every elicitation, in any
mode (url, form, openai/form, missing, unknown), is now declined; url/form
flows must be completed in an interactive Codex session.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…config values out of job records

enqueueBackgroundTask spawned the detached worker and only then wrote the job
record, so a worker that started fast read a missing record and exited while
the parent reported `queued`. The record (and the new private payload file) are
now written first; if the spawn fails the job is marked `failed` with the error
text. Nothing writes the record after the spawn: the worker owns it and stores
its own pid, so a parent-side pid patch would only race it.

buildTaskRequest's full `config` map reached the job record, which `status
--json` and `result --json` echo back, exposing `--config` auth headers. The
worker now reads the unredacted request from a one-shot `jobs/<id>.request.json`
(mode 0600, deleted once read, record used as fallback), while the record keeps
`config` with key|token|secret|auth|password values replaced by "[redacted]".
Pruned jobs drop their payload file with the rest of their artifacts.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…an active job

Two concurrent turns on one Codex thread interleave their history. The
resume-candidate lookup is scoped to the current Claude session, so a job from
another session could not block a resume; runAppServerTurn now checks the thread
itself, where every resume passes, and refuses while a queued or running job
holds it.

/codex:rescue also stopped choosing --resume-last on its own: when
task-resume-candidate reports a resumable thread it asks via AskUserQuestion
("Continue current Codex thread" / "Start a new Codex thread") first, so a
request is never silently appended to an unrelated earlier thread. Its
allowed-tools becomes `Bash, AskUserQuestion, Agent` — the body is
multi-command shell, not just `node`.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The README install section still pointed at the upstream marketplace and plugin
id (openai/codex-plugin-cc, codex@openai-codex); it now installs the fork
(CBEPX/codex-plugin-cc, codex@cbepx), with the "Upstream:" attribution the only
remaining upstream mention. package-lock.json still carried the upstream package
name, so `bump-version --check` now also pins the lockfile `name` and
`packages[""].name` to package.json's name, and the lockfile was regenerated.

CHANGELOG: openai#547 reworded (unknown flags are CLI errors; --help prints usage and
exits 0) plus entries for the argument boundary, approval denial and enqueue
ordering/redaction. The rescue agent returns "the `result` stdout" rather than
"the stdout of the codex-companion command", and both rescue shell blocks trap
EXIT to clean up their mktemp files.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…eredoc delimiters; unlink payload on spawn failure

R1: routing the whole rescue request through --args-stdin fed the prose to
splitRawArgumentString, which strips quotes as grouping, consumes backslashes as
escapes and splits on newlines — a stack trace, a regex (\d+ -> d+), a Windows
path or a fenced code block reached Codex mangled. The launch step now uses two
channels in the same Bash call: the prose is written byte-exact to $PROMPT by
its own quoted heredoc and passed as --prompt-file, while --args-stdin carries
only the runtime flags. readTaskPrompt already prefers --prompt-file over stdin,
so the two compose without a companion change (covered by a new test).

R2: a payload line equal to the fixed CODEX_ARGS delimiter would close the
heredoc early and run the rest on the host shell. Both rescue bodies now require
a fresh random suffix on both delimiters per call. The seven flag-only command
bodies keep the fixed delimiter.

R3: the spawn-failure branch of enqueueBackgroundTask left jobs/<id>.request.json
(0600, possibly holding --config secrets) on disk until prune; it is unlinked
there via a new removeJobRequestFile helper.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@CBEPX
CBEPX merged commit 23942d7 into main Aug 27, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.