A local OpenAI Responses compatibility data plane for declared third-party Responses providers. Codex is its first qualified client, not a required client identity.
Licensed under MIT. Forge coordinates and publication actors are deployment context, not product identity.
It keeps Codex traffic provider-portable without editing conversation JSONL, SQLite state, history, stored items, or model metadata.
flowchart LR
C["Codex CLI / Desktop"] --> P["Codex Responses Proxy"]
P --> U["UCloud"]
P --> D["DMXAPI"]
P --> A["AIHubMix"]
| Owner | Responsibility |
|---|---|
| Codex | Conversations, tools, and per-conversation model selection |
| Client control plane | Credentials, provider selection, and client configuration |
| Codex Responses Proxy | Responses normalization, replay portability, bounded recovery, and native service lifecycle |
| Provider | Model execution, quotas, and upstream availability |
The proxy does not configure or restart clients. A client control plane does not manage the proxy process. Each product is installed and verified independently. "OpenAI-compatible" alone is not an admission contract: Chat Completions, Embeddings, and other OpenAI API families are outside this product's current scope. Another Responses client is supported only after its request, replay, streaming, error, and installed-client journeys pass the same conformance bar.
End users need only:
- the native release asset for their platform;
- the release trust anchor supplied by their organization;
- a third-party Responses endpoint configured by their client control plane.
Python, a source checkout, Git, and Forge credentials are not runtime requirements.
Linux installation requires a reachable systemd user manager. A container without
that user session is not a supported service host. Installation reports
native_service_unavailable and rolls back its payload and command projection;
it does not start a session-only background process or require payload recovery.
Enable the user service environment before retrying. If the service manager is
unreachable, status reports the service as unknown, not proven absent.
Boot-time startup and continued operation after logout depend on the host's systemd user lingering policy. The host administrator owns that user-wide policy. Proxy installs only its own user service; it does not change lingering or request administrative credentials.
codex-responses-proxy install \
--asset "$HOME/Downloads/codex-responses-proxy-<version>-macos-arm64.tar.gz" \
--trust-anchor ~/Downloads/codex-responses-proxy-allowed-signersReplace <version> with the release version you downloaded. Download that
platform archive together with SHA256SUMS and SHA256SUMS.sig from either
official release plane. Keep the matching platform manifest—such as
codex-responses-proxy-macos-arm64.manifest.json—in the same directory.
--asset names the local archive. --trust-anchor names the SSH
allowed_signers file distributed by the organization or release owner through
a separate trusted channel. The installer requires the complete release set
and verifies the signed checksum before changing the service.
Use --port only when the default listener port 8792 conflicts with another
local service:
codex-responses-proxy install \
--asset "$HOME/Downloads/codex-responses-proxy-<version>-macos-arm64.tar.gz" \
--trust-anchor ~/Downloads/codex-responses-proxy-allowed-signers \
--port 8801Installation verifies the selected native bundle, commits it inside a rollback
transaction, and prewarms the exact installed executable before handoff. Use
--timeout-seconds only when a cold native executable needs more than the
default 30 seconds. Installation also projects codex-responses-proxy into the
current user's platform command directory as a native link. It does not create
a wrapper or edit a shell profile. The installed-state record retains that
exact path so status, rollback, and uninstall do not depend on a later shell's
environment. Installation never downloads dependencies or reads provider
credentials.
In-place upgrade and rollback use immutable payload generations selected by one durable selector. An installation without that selector is not an upgrade predecessor. Use its existing uninstaller to remove the service and owned payload, then install the verified release into a fresh target. Inspect any reported residue before removing it; unknown files are never migration input. Provider credentials and client configuration remain outside this lifecycle.
The listener exposes one provider-scoped namespace per admitted provider:
| Provider | Responses base URL |
|---|---|
| DMXAPI | http://127.0.0.1:8792/dmxapi/v1 |
| UCloud | http://127.0.0.1:8792/ucloud/v1 |
| AIHubMix | http://127.0.0.1:8792/aihubmix/v1 |
Configure these URLs in the client control plane. For example:
[providers.dmxapi]
base_url = "http://127.0.0.1:8792/dmxapi/v1"
[providers.ucloud]
base_url = "http://127.0.0.1:8792/ucloud/v1"
[providers.aihubmix]
base_url = "http://127.0.0.1:8792/aihubmix/v1"The table names are illustrative; use the client's native configuration grammar. The proxy has no package or configuration dependency on that client.
# Human-readable state
codex-responses-proxy status
# Stable machine contract
codex-responses-proxy status --json
# Read-only diagnosis
codex-responses-proxy doctor
# Transactional same-payload handoff
codex-responses-proxy reload
# Converge on the exact active release or verified retained predecessor
codex-responses-proxy rollback --to-release <exact-version>
# Resolve an interrupted payload transaction; idle recovery is a successful no-op
codex-responses-proxy recover
# Remove native supervision; preserve the verified payload
codex-responses-proxy uninstall
# Remove supervision and manifest-owned payload files
codex-responses-proxy uninstall --purgeLifecycle JSON uses one explicit state discriminator. install returns
unchanged when the signed artifact exactly matches the healthy active
installation; it neither replaces files nor restarts the listener. The same
version with different artifact bytes is not the same installation.
rollback returns
unchanged when the requested release is already the proven active
installation, unavailable when no verified predecessor exists, and
rolled_back only after the requested predecessor is the proven accepting
installation. recover returns
not_required when no transaction exists, closed when an unmutated prepared
transaction is discarded, finalized when the committed candidate is already
the proven live installation, rolled_back when the exact prior state is
restored, and purged when interrupted removal finishes. uninstall and
uninstall --purge return not_installed with exit
status zero only when no owned service, listener, command, payload, or
transaction exists. Existing but unverifiable state is never treated as
absence and remains unchanged for diagnosis.
Before deleting payload files, purge records their exact paths and digests in
the existing transaction journal. An interrupted purge resumes through
recover or uninstall --purge; it does not depend on files already removed.
Unknown content and changed replacements are preserved and reported, including
empty directories. Remove or relocate that content deliberately, then retry.
During recovery, use a separate verified release executable if the installed
command has already been removed.
A successful upgrade retains exactly one predecessor in the immutable
generation store. One atomic selector under the stable control root is the
sole authority for both the active generation and that predecessor; installed
state and the user command remain stable control surfaces outside either
generation. The selector chooses the serving payload; the user command stays
on the newest verified selected release, so an explicit serving rollback cannot
downgrade status, doctor, recover, rollback, or the next installer.
Native supervision remains bound to the serving generation. Finalization is
idempotent across interruption, and the
transaction owns temporary bootstrap evidence, selector reconciliation,
cleanup, and recovery until it closes. status therefore reports rollback as
deferred while a transaction is active instead of treating its intermediate
state as an independent rollback authority. Upgrade and rollback use the same
capability-qualified handoff. A runtime that advertises
admission-preserving-handoff transfers listener ownership while continuing to
admit new requests and lets already accepted requests finish. Draining is used
only for the bounded native-generation replacement of an older runtime that
cannot preserve admission.
Expected failures are concise and actionable. Human mode does not emit a
traceback, warning dump, serialized object, credential, request body, or private
path. Automation should use --json where the command supports it.
Every request is projected to a provider-portable Responses grammar before it leaves the loopback listener.
| Concern | Behavior |
|---|---|
| Storage | Sends store=false; continuity comes from replayed dialogue and complete tool relationships |
| Provider IDs | Removes response, conversation, cache, stored-item, and provider-issued item bindings |
| Encrypted replay | Removes reasoning history; preserves required native agent payloads without claiming decryption |
| Tool replay | Keeps complete function/custom-tool call pairs; rejects unsafe structure locally |
| Empty upstream response | Returns a retryable local 503 instead of committing false success |
DMXAPI 477 empty_response |
Retries the already-projected bytes once |
Upstream 429 |
Relays the first response and applies a provider-scoped bounded cooldown |
Exhausted upstream 503 |
Relays the original error; subsequent turns briefly cool only that provider before probing again |
response_failed |
Uses strictly shrinking, pair-safe recovery; one final dialogue-only attempt is bounded |
Invalid input union |
Uses one smaller current-dialogue fallback, then stops |
The proxy never rewrites conversation storage to obtain portability.
Only these exact provider-scoped requests are admitted:
POST /<provider>/v1/responses
GET /<provider>/v1/models
Responses requests receive portable projection and bounded recovery. Model catalog reads are relayed once without Responses-specific transformations. Encoded path material, dot segments, duplicate separators, absolute targets, fragments, and unrelated endpoints are rejected before remote I/O. Provider origins come from the product manifest; headers, bodies, and query parameters cannot select another host.
status --json reports secret-free local evidence:
- installed release, payload integrity, and command discoverability;
- native service and exact listener identity;
- transaction state;
- accepting and draining state;
- bounded reliability counters and classified failures.
It does not report prompts, tokens, headers, request bodies, upstream payloads, or conversation content.
| Symptom | First action | Interpretation |
|---|---|---|
| Replay or encrypted-item rejection | codex-responses-proxy doctor |
Confirm local payload and listener integrity before changing the client route |
| Error after provider switch | Check the client control plane | A direct provider URL bypasses proxy portability |
Local 503 |
codex-responses-proxy status --json |
Distinguish empty/truncated upstream output from local lifecycle failure |
Local or upstream 429 |
Inspect Retry-After and provider state |
Cooldown is provider-scoped; the proxy does not impose a global request queue |
| Route change not observed | Reload the client through its normal lifecycle | The proxy does not restart or mutate clients |
Development uses the repository-owned Python environments and locked supply chain. These commands are DX, not product UX:
mise install --locked
mise run bootstrap
mise run checkThe tasks in mise.toml select the locked Python installation and this
worktree's .venv; Nox owns isolated .nox/<session> verification environments.
Use mise run quick while editing. check runs repository governance, strict
quality and Python 3.12 coverage, then Python 3.13 and 3.14 compatibility.
mise run release verifies a native release asset; mise run native also
exercises real host services and requires an authorized test host.
See CONTRIBUTING for source verification and release work.
| Need | Source of truth |
|---|---|
| Product and first use | This README |
| Development workflow | CONTRIBUTING |
| Runtime architecture | Architecture |
| Release governance | Release policy |
| Forge publication | Forge operations |
| Decision register | Decision Records |
| Durable product boundary | DR-0001 |
| Release history | CHANGELOG |
Licensed under the MIT License.