Skip to main content

Local OpenAI-compatible FastAPI gateway for Codex app-server.

Project description

Codex Gateway

Experimental: this is an early local compatibility gateway for Codex app-server. Treat the HTTP contract and safety model as unstable, review changes carefully before relying on it, and do not expose it outside loopback.

Local FastAPI adapter that lets the official OpenAI Python SDK talk to codex app-server over stdio:

from openai import OpenAI

client = OpenAI(
    base_url="http://127.0.0.1:8000/v1",
    api_key="<local-gateway-token>",
)

print(client.models.list())
print(client.chat.completions.create(
    model="gpt-5.5",
    messages=[{"role": "user", "content": "Say pong"}],
))

Run

One-shot from GitHub with uvx, including local gateway environment variables:

eval "$(uvx --from git+https://github.com/kayvane1/codex-gateway codex-gateway env)"
uvx --from git+https://github.com/kayvane1/codex-gateway codex-gateway

codex-gateway env prints shell exports for CODEX_GATEWAY_TOKEN, CODEX_GATEWAY_BASE_URL, CODEX_GATEWAY_HOST, and CODEX_GATEWAY_PORT. It does not write the generated local bearer token to disk. With those variables set, OpenAI SDK setup is three lines:

import os
from openai import OpenAI

client = OpenAI(base_url=os.environ["CODEX_GATEWAY_BASE_URL"], api_key=os.environ["CODEX_GATEWAY_TOKEN"])

For scripts that only need a token value, use codex-gateway token.

For local development:

uv sync --group dev
uv run codex-gateway --port 8000

The api_key is a local gateway bearer token. It is not an OpenAI API key and is never proxied to Codex. If CODEX_GATEWAY_TOKEN is not set, the gateway prints a generated local token at startup.

Implemented

  • GET /v1/models
  • POST /v1/chat/completions
  • stream=True SSE chunks compatible with openai.OpenAI(...).chat.completions.create(..., stream=True)
  • Multi-turn text chat history via Codex thread/inject_items
  • OpenAI image_url content parts in user messages, mapped to Codex image inputs/history. Image data URLs are materialized as temporary local files for the live Codex turn and cleaned up afterward.
  • Local bearer-token authentication
  • Codex app-server stdio transport

Safety Defaults

  • Binds to 127.0.0.1 by default.
  • Starts ephemeral Codex threads with sandbox="read-only", approvalPolicy="never", no environments, and no dynamic tools.
  • Unsubscribes from each per-request thread after the API response finishes.
  • Accepts only http://, https://, and data:image/... image URLs; local file URLs are rejected.
  • Denies app-server requests for command execution, patch approval, file-change approval, MCP elicitations, and dynamic tool calls.
  • Does not expose app-server filesystem, shell, config, auth, or account endpoints through the OpenAI-compatible HTTP API.
  • Does not print, persist, proxy, or expose Codex auth credentials.

Architecture

  • chat_contract.py owns the OpenAI-facing chat subset: validation, text/image message conversion, history item construction, completion payloads, streaming chunks, SSE framing, and OpenAI-style errors.
  • _app_server_stdio_session.py owns the Codex app-server stdio transport: JSON-RPC request correlation, notification fan-out, stderr redaction, shutdown, and denial responses for privileged app-server requests.
  • _codex_turn_lifecycle.py owns Codex turn behavior: starting turns, collecting final assistant output, streaming assistant deltas, draining idle notifications, and mapping token usage.
  • codex_client.py is the high-level client used by FastAPI. It initializes the app-server session, lists models, starts ephemeral read-only Codex threads, injects prior text/image history, materializes image data URLs for live turns, delegates turn execution, and unsubscribes when finished.

Unsupported OpenAI Features

This MVP returns a 400 instead of pretending to support features it cannot honor, including tools/functions, tool choice, response formats, JSON/schema-constrained output, audio, n > 1, logprobs, sampling controls, stop sequences, token limits, metadata storage, and non-chat APIs such as /v1/responses, /v1/embeddings, and legacy completions.

Tests

uv sync --group dev
uv run --group dev pytest -m "not integration" tests

Live contract tests are opt-in because they start the FastAPI gateway, launch codex app-server over stdio, and require working Codex auth:

CODEX_GATEWAY_RUN_CONTRACT_TESTS=1 uv run --group dev pytest -m integration tests/test_contract.py

The contract tests instantiate the official OpenAI SDK with base_url=.../v1, call /v1/models, call non-streaming chat completions including a multi-turn message chain and image content part, call streaming SSE chat completions, and verify missing/invalid local bearer tokens are rejected. The coverage gate is configured at 95% in pyproject.toml.

Linting

uv run --group dev ruff check src tests
uv run --group dev ruff format --check src tests
uv run --group dev pre-commit install
uv run --group dev pre-commit run --all-files

The generated Codex app-server JSON Schema and TypeScript protocol references used for this implementation are in generated/.

Project details


Download files

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

Source Distribution

codex_gateway-0.1.0.tar.gz (26.8 kB view details)

Uploaded Source

Built Distribution

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

codex_gateway-0.1.0-py3-none-any.whl (17.8 kB view details)

Uploaded Python 3

File details

Details for the file codex_gateway-0.1.0.tar.gz.

File metadata

  • Download URL: codex_gateway-0.1.0.tar.gz
  • Upload date:
  • Size: 26.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.14 {"installer":{"name":"uv","version":"0.11.14","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for codex_gateway-0.1.0.tar.gz
Algorithm Hash digest
SHA256 669dff64499aae565ff260c1c2cf23518d786312fffaa0cfe8fee55baf980f99
MD5 08dc53cfa012390e321b1b15023e41ca
BLAKE2b-256 7b6d225274c9cef0524f40284d0ba43fdc3669e9040204032704938a6e2cb2de

See more details on using hashes here.

File details

Details for the file codex_gateway-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: codex_gateway-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 17.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.14 {"installer":{"name":"uv","version":"0.11.14","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for codex_gateway-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 8aabe0179f04ed484e91ef5408b14ba8eef2365fcc18296a8f050d0603d7b71c
MD5 fdd5e358cc69a707cc660778d99a3410
BLAKE2b-256 456e90da70b029c7825c13df0533129bb5fdb0ea6c9c5bc8242c9acbea54144a

See more details on using hashes here.

Supported by

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