codexcomp

Codex + Complete — a lightweight local proxy that folds gpt-5.5's "516" reasoning truncation into complete, untruncated answers for the OpenAI Codex CLI.

PyPI Python Downloads License: MIT

English · 简体中文

uv tool install codexcomp      # install
codexcomp                      # run (127.0.0.1:8787)
# then append to ~/.codex/config.toml:  openai_base_url = "http://127.0.0.1:8787/v1"

It overrides the built-in provider's base URL in placemodel_provider is unchanged, so session grouping, remote compaction, and remote-control keep working.

Credits. The detect-and-continue mechanism originates from neteroster/CodexCont (MIT); this is an independent, from-scratch implementation that keeps the built-in provider intact.


The problem

gpt-5.5's reasoning is intermittently truncated at reasoning_tokens == 518·n − 2 (516, 1034, 1552, …): the turn stops mid-reasoning and answers from an incomplete thought, degrading quality sharply. Aggregate telemetry in the upstream report shows ~44 % of gpt-5.5 responses that reach 516 reasoning tokens end at exactly that boundary — an upstream defect with no official fix (openai/codex#30364).

codexcomp sits on 127.0.0.1 between Codex and the upstream Responses API. On a 518n−2 truncation it drives the model to keep reasoning and folds the extra rounds into a single downstream response — Codex sees one complete, untruncated answer.

Features

  • Detect → continue → fold — spots the 518n−2 fingerprint, replays the round's reasoning with a continue nudge, and folds all rounds into one response.
  • Zero-footprint wiring — one official top-level openai_base_url key; no [model_providers] entry, no provider id change, no session re-bucketing.
  • WebSocket-first transport — native responses_websockets protocol (envelope frames, serial connection reuse, prewarm); no "Falling back" noise in Codex logs.
  • Resilient SSE fallback — the POST path transparently decompresses zstd/gzip upstream responses.
  • Full /v1/* passthrough — including GET /v1/models (model catalog refresh).
  • Protocol-faithful headers & compaction — upstream response headers reach Codex on the POST path (x-codex-* rate-limit snapshots, x-models-etag, request ids), the x-codex-turn-state sticky-routing token is replayed across fold rounds when the upstream issues one, and remote-compaction requests are never folded.
  • Live streaming — reasoning streams in real time even mid-fold; only the final clean round's output is released downstream.
  • Honest accounting — the true cumulative cost of folded rounds is reported under metadata.proxy_billed_usage.
  • Loopback-only, auth passthrough — forwards Codex's Authorization header; never reads, persists, or logs a credential.
  • Opt-in autostart — installation registers nothing; one command sets up a systemd user unit (Linux/WSL) or LaunchAgent (macOS).

Quick start

Requires uv and the Codex CLI (ChatGPT OAuth; tested on 0.142.x).

uv tool install codexcomp                                  # from PyPI
# uv tool install git+https://github.com/dzshzx/codexcomp  # or from source
codexcomp                                                  # foreground, 127.0.0.1:8787

Point Codex at the proxy with one top-level config key:

# ~/.codex/config.toml  (top level, before the first [table])
openai_base_url = "http://127.0.0.1:8787/v1"

That's it. Disable by removing that line and stopping the proxy; upgrade / uninstall with uv tool upgrade codexcomp / uv tool uninstall codexcomp.

How it works

A state machine (codexcomp/fold.py) runs per round:

  1. Detectreasoning_tokens == 518n − 2 (any tier by default; cuts up to n=21 observed — see --max-n / --max-continue) marks the round as truncated.
  2. Continue — discard the tentative output and replay the round's reasoning items (incl. encrypted_content) plus one phase:"commentary" "Continue thinking..." message as the next input. If a continuation round comes back with zero reasoning tokens (the nudge stalled), it is re-nudged rather than accepted, spending from the same --max-continue budget.
  3. Fold — stream reasoning live, flush only the final clean round, and rebuild the terminal event as one response (reasoning summed, true cost under metadata.proxy_billed_usage).

CLI reference

CommandDescription
codexcomp / codexcomp runStart the proxy in the foreground.
codexcomp install-serviceOpt-in autostart registration for the current platform.
codexcomp uninstall-serviceRemove the autostart entry.
codexcompwWindowless entry (Windows); logs to %LOCALAPPDATA%\codexcomp\codexcompw.log.
FlagDefaultDescription
--host127.0.0.1Bind address — keep it loopback.
--port8787Must match openai_base_url; if busy the proxy exits.
--upstreamhttps://chatgpt.com/backend-api/codexUpstream base URL.
--log-levelinfoOne of critical / error / warning / info / debug.
--max-n0Highest 518n−2 tier to auto-continue; 0 = no cap (cuts up to n=21 observed).
--max-continue3Max continuation rounds per request (runaway guard).

Autostart (optional, off by default)

codexcomp install-service     # register + start (current platform)
codexcomp uninstall-service   # remove
  • Linux / WSL — systemd user unit; loginctl enable-linger starts it at boot without login.
  • macOS — launchd LaunchAgent in ~/Library/LaunchAgents/.
  • Windows — prints manual steps only: point a Startup shortcut (Win+Rshell:startup) at the windowless codexcompw (where.exe codexcompw). Delete it to disable.

With WSL2 networkingMode=mirrored, Windows and WSL share 127.0.0.1: run one proxy in WSL and just add the openai_base_url line on the Windows side — no second proxy needed.

Verify

curl -sS http://127.0.0.1:8787/healthz            # {"ok":true,...}
journalctl --user -u codexcomp -f | grep -E 'round|done'   # Linux/WSL

A live fold — two consecutive 516s folded, answer correct:

round 1: in=21550 out=664 reason=516 total=22214 | n=1 buffered=['function_call'] -> continue
round 2: in=22078 out=652 reason=516 total=22730 | n=1 buffered=['function_call'] -> continue
round 3: in=22606 out=566 reason=291 total=23172 | n=None buffered=[...] -> clean
done: 3 round(s) | ... | status=completed stop=natural

Round verdicts: continue (cut detected → will continue), clean (natural end), tier_out_of_window / max_continue / no_encrypted_content (cut detected but released as-is), compaction_request (remote-compaction request — never folded), upstream_eof (stream ended without a terminal event). done: lines end with stop=natural or the release reason. A fold torn down by a client disconnect logs fold aborted downstream after N round(s) instead of a done: line.

Evals

Two A/B evals ship inside the package and are available right after install. Both measure the fix end-to-end: a model × effort × proxy-on/off grid of codex exec calls, reporting boundary-cut rate, reasoning tokens and accuracy per condition:

  • codexcomp-eval — the candy pigeonhole puzzle from haowang02/codex-candy-eval (answer: 21, independently re-verified by brute force); a short trap-style question that under-thinking runs get wrong fast.
  • codexcomp-sudoku-eval — a hard 6×6 arithmetic-cage sudoku with four given anchor cells; its chained deduction spends far more reasoning tokens and hits the 518n−2 lattice across many rounds — a stress test for fold stability.

Both modes wire openai_base_url explicitly, so the ambient config doesn't matter; results append to <out>/results.jsonl, so an interrupted grid resumes by re-running the same command. Per-round fold detail for on runs is read from the systemd user unit's journal when it is active. Runs are serial by default; --parallel N opts into N concurrent runs — faster, but it disables per-round journal capture (folded runs are then detected from usage fingerprints only) and spends tokens faster. The harness wraps codex exec in coreutils timeout, so it needs Linux/WSL (macOS needs coreutils).

codexcomp &                                     # proxy must be running for `on`
codexcomp-eval -m gpt-5.5 -r xhigh -n 5         # small grid
codexcomp-eval                                  # default grid (gpt-5.5 × medium,xhigh × on/off × 4 reps)
codexcomp-sudoku-eval -r xhigh,ultra,max        # long-reasoning stress grid

Inside a checkout use uv run codexcomp-eval for the same thing.

An 80-run grid of the candy eval (2026-07-06) found every unmitigated gpt-5.5 run cut exactly on a 518n−2 boundary, 15% vs 90% accuracy off/on — details in openai/codex#30364.

FAQ

Does it touch normal turns? No. Clean rounds pass through byte-for-byte; the fold path only engages on a detected 518n−2 truncation.

What does a fold cost? Continuation rounds spend extra real tokens, bounded by the continuation cap (--max-continue, default 3). The true cumulative usage is reported under metadata.proxy_billed_usage.

Does it work with the gpt-5.6 series? Mechanically yes — the 518n−2 lattice still appears on gpt-5.6 and folding engages exactly as on gpt-5.5 — but it no longer buys accuracy: in a 192-run A/B grid, proxied and direct accuracy were identical. A 5.6 run that hits the lattice usually has a complete answer already, and 5.6's real losses (reasoning collapsing to a few hundred tokens at non-lattice values — under-thinking, not truncation) are invisible to any proxy. If you only use 5.6, unwire codexcomp (folds just spend extra tokens); it remains fully effective for gpt-5.5. Grid data in #11.

What happens when OpenAI fixes this upstream? Nothing breaks — the detector simply stops firing and the proxy becomes a transparent passthrough. Unwire it by deleting the openai_base_url line whenever you like.

Why not a separate [model_providers] entry? That changes the provider id, which re-buckets session history and drops remote compaction and remote-control. openai_base_url is the official in-place override of the built-in openai provider.

Is my credential safe? The proxy forwards the Authorization header untouched and binds to loopback only; it never reads, persists, or logs a credential.

Security & disclaimer

  • Auth passthrough only — forwards Codex's Authorization header; never reads, persists, or logs a credential.
  • Loopback only — do not expose it on a non-loopback interface.
  • Unofficial — it relies on non-contract upstream behavior; an OpenAI-side change may break it. Use at your own risk.
  • Continuation spends extra real tokens (metadata.proxy_billed_usage), bounded by the --max-continue cap (default 3 rounds).

Development

git clone https://github.com/dzshzx/codexcomp && cd codexcomp
uv sync
uv run python test_fold.py        # fold state-machine self-test → ALL PASS
uv run python test_ws.py          # transport self-test (WS protocol, headers) → ALL PASS
uv run codexcomp                  # run locally

Releases go out via PyPI Trusted Publishing (OIDC, no stored token): push a v* tag to build and publish. Version history: CHANGELOG.md.

Contributing

Bug reports, fold-log excerpts, and reproduction details are the most valuable contributions — please file them on GitHub Issues. For code changes, run uv run python test_fold.py and uv run python test_ws.py before opening a PR and keep changes focused.

Community

Built for and shared with the LINUX DO community, where the gpt-5.5 "516" degradation was diagnosed. Feedback and issues welcome there and on GitHub Issues.

License

MIT — mechanism credit to neteroster/CodexCont (MIT), whose 518n−2 detect-and-continue idea this reuses with an independent, from-scratch implementation. The candy puzzle eval task and its standalone-21 grading rule come from haowang02/codex-candy-eval — the task prompt is reproduced with attribution (the upstream repo declares no license).