Skip to main content

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

Command Description
codexcomp / codexcomp run Start the proxy in the foreground.
codexcomp install-service Opt-in autostart registration for the current platform.
codexcomp uninstall-service Remove the autostart entry.
codexcompw Windowless entry (Windows); logs to %LOCALAPPDATA%\codexcomp\codexcompw.log.
Flag Default Description
--host 127.0.0.1 Bind address — keep it loopback.
--port 8787 Must match openai_base_url; if busy the proxy exits.
--upstream https://chatgpt.com/backend-api/codex Upstream base URL.
--log-level info One of critical / error / warning / info / debug.
--max-n 0 Highest 518n−2 tier to auto-continue; 0 = no cap (cuts up to n=21 observed).
--max-continue 3 Max 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

The health response also reports the current upstream-client generation and active upstream / WebSocket counts. If the shared upstream pool becomes exhausted, codexcomp logs a sanitized pool snapshot, rotates the client once, and lets Codex's next retry use a fresh pool without restarting the process. A failed proxy handshake is handled the same way when no other upstream stream is active, preventing dead handshakes from accumulating into later pool starvation.

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).

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

codexcomp-0.3.8.tar.gz (84.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

codexcomp-0.3.8-py3-none-any.whl (37.9 kB view details)

Uploaded Python 3

File details

Details for the file codexcomp-0.3.8.tar.gz.

File metadata

  • Download URL: codexcomp-0.3.8.tar.gz
  • Upload date:
  • Size: 84.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for codexcomp-0.3.8.tar.gz
Algorithm Hash digest
SHA256 fcdd130e9e5430ce4fa6d70bd9846d5a56784eb9d23f4c5456c5cac31e3cbeed
MD5 068a06a6dc0aa496576cbd30db0d7d3c
BLAKE2b-256 37e6848d53bb0c575c1d17d84bb9e7ac07d9ba898ba92283eefe6f068b873439

See more details on using hashes here.

Provenance

The following attestation bundles were made for codexcomp-0.3.8.tar.gz:

Publisher: release.yml on dzshzx/codexcomp

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file codexcomp-0.3.8-py3-none-any.whl.

File metadata

  • Download URL: codexcomp-0.3.8-py3-none-any.whl
  • Upload date:
  • Size: 37.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for codexcomp-0.3.8-py3-none-any.whl
Algorithm Hash digest
SHA256 76cf73aff61231b640478ca6c9aaef15ee7cc162c88badc648379349f1dd64ca
MD5 629c11f2777277898081244a94e0748d
BLAKE2b-256 46abbbc64f5f7985697904ad5a8aca42519dca74d01fb3153f372d40395406bc

See more details on using hashes here.

Provenance

The following attestation bundles were made for codexcomp-0.3.8-py3-none-any.whl:

Publisher: release.yml on dzshzx/codexcomp

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page