Skip to main content

Local OpenAI-compatible HTTP proxy backed by Codex/OpenAI credentials

Project description

codex-api-proxy

Local OpenAI-compatible HTTP proxy backed by Codex/OpenAI credentials.

The proxy has one runtime path: it reads credentials from ~/.codex/auth.json or CODEX_HOME/auth.json, then forwards requests to the upstream OpenAI/Codex API. It no longer runs local codex exec, starts codex app-server, manages workspaces, or exposes sandbox/agent/fast engine settings.

Product Scope

This package is intentionally narrow:

  • expose OpenAI-compatible local endpoints for clients such as OpenClaw;
  • reuse the user's existing Codex/OpenAI login credentials;
  • support /v1/chat/completions, /v1/responses, /v1/messages, and /v1/models;
  • convert Chat Completions to Responses API when using ChatGPT Codex credentials;
  • convert Anthropic-style Messages API requests to Responses API for local Anthropic-compatible clients such as Claude Code;
  • accept image input for vision tasks through Chat Completions image_url parts and Anthropic image content blocks;
  • otherwise transparently forward OpenAI API-key requests to OpenAI's native /chat/completions.

Out of scope:

  • local command execution;
  • workspace read/write control;
  • Codex sandbox configuration;
  • app-server workers;
  • simulated tool-call wrapping;
  • custom model execution engines.

Tool calls and function calls are handled by the upstream OpenAI-compatible API response, not by local prompt wrapping.

Install

pip3 install codex-api-proxy

For local development from this checkout:

python3 -m pip install -e '.[dev]'

Credentials

The proxy reads Codex credentials from:

~/.codex/auth.json

or, when CODEX_HOME is set:

$CODEX_HOME/auth.json

Supported auth shapes:

  • OPENAI_API_KEY: forwarded to https://api.openai.com/v1;
  • Codex/ChatGPT tokens.access_token: forwarded to https://chatgpt.com/backend-api/codex.

For Codex/ChatGPT token auth, the proxy refreshes tokens automatically:

  • before a request when the access token JWT expires within 5 minutes;
  • before a request when last_refresh is older than 8 days and the access token has no parseable expiry;
  • after an upstream 401, then it retries the original request once.

Refreshed tokens are written back to auth.json with 0600 permissions when supported by the platform.

Outbound upstream proxy settings are controlled by environment variables:

  • CODEX_API_PROXY_HTTPS_PROXY
  • HTTPS_PROXY
  • https_proxy

When none are set, the proxy connects directly to the upstream API without a proxy.

You can also set the upstream proxy explicitly at startup:

codex-api-proxy start --proxy=http://127.0.0.1:8118

If the upstream connection passes through a corporate TLS proxy or another endpoint using a private/self-signed certificate chain, point the proxy at a CA bundle that trusts that chain:

  • CODEX_API_PROXY_CA_BUNDLE
  • REQUESTS_CA_BUNDLE
  • SSL_CERT_FILE

For example:

CODEX_API_PROXY_CA_BUNDLE=/path/to/internal-ca-bundle.pem codex-api-proxy start

Run

Start in the background:

codex-api-proxy start

Run in the foreground with debug logs:

codex-api-proxy start --foreground --log-level debug

Bind to all interfaces with local bearer auth:

codex-api-proxy start --host 0.0.0.0 --api-key local-secret

Binding to 0.0.0.0, ::, or [::] requires --api-key; the proxy refuses to start on public interfaces without local bearer auth.

Start with an explicit upstream proxy:

codex-api-proxy start --proxy=http://127.0.0.1:8118

Restart using the last saved start config:

codex-api-proxy restart

Stop:

codex-api-proxy stop

Status:

codex-api-proxy status --verbose

Run diagnostics:

codex-api-proxy doctor

CLI Options

  • --host: bind host, default 127.0.0.1
  • --port: bind port, default 8765
  • --api-key: require client requests to send Authorization: Bearer <key>
  • --proxy: upstream HTTP(S) proxy URL for OpenAI/Codex API calls; omitted means direct upstream connections
  • --log-level: debug, info, warning, or error
  • --log-format: text or json for application event logs
  • --models-cache-ttl: seconds to cache /v1/models, default 300; use 0 to disable
  • --pid-file: daemon pid file, default ~/.codex-api-proxy/codex-api-proxy.pid
  • --log-file: daemon log file, default ~/.codex-api-proxy/codex-api-proxy.log
  • --state-file: daemon config file, default ~/.codex-api-proxy/config.toml
  • --foreground: run without daemonizing

Environment variables for the local server:

  • CODEX_PROXY_HOST
  • CODEX_PROXY_PORT
  • CODEX_PROXY_API_KEY
  • CODEX_API_PROXY_HTTPS_PROXY
  • CODEX_API_PROXY_CA_BUNDLE
  • CODEX_PROXY_LOG_LEVEL

Token refresh compatibility variables:

  • CODEX_REFRESH_TOKEN_URL_OVERRIDE: override the OAuth refresh endpoint
  • CODEX_APP_SERVER_LOGIN_CLIENT_ID: override the OAuth client id

API

Health:

curl -sS http://127.0.0.1:8765/health

Models:

curl -sS http://127.0.0.1:8765/v1/models

/v1/models responses are cached locally for --models-cache-ttl seconds. Use ?refresh=true to bypass and refresh the cache.

Chat completion:

curl -sS http://127.0.0.1:8765/v1/chat/completions \
  -H 'Content-Type: application/json' \
  -d '{"model":"gpt-5.5","messages":[{"role":"user","content":"Reply with exactly: pong"}]}'

Streaming chat completion:

curl -N http://127.0.0.1:8765/v1/chat/completions \
  -H 'Content-Type: application/json' \
  -d '{"model":"gpt-5.5","stream":true,"messages":[{"role":"user","content":"Reply with exactly: pong"}]}'

Responses API passthrough:

curl -sS http://127.0.0.1:8765/v1/responses \
  -H 'Content-Type: application/json' \
  -d '{"model":"gpt-5.5","input":"Reply with exactly: pong"}'

Anthropic-style Messages API:

curl -sS http://127.0.0.1:8765/v1/messages \
  -H 'Content-Type: application/json' \
  -H 'anthropic-version: 2023-06-01' \
  -d '{
    "model": "gpt-5.5",
    "max_tokens": 128,
    "system": "Be brief.",
    "messages": [{"role":"user","content":"Reply with exactly: pong"}]
  }'

Streaming Anthropic-style Messages API:

curl -N http://127.0.0.1:8765/v1/messages \
  -H 'Content-Type: application/json' \
  -H 'anthropic-version: 2023-06-01' \
  -d '{
    "model": "gpt-5.5",
    "max_tokens": 128,
    "stream": true,
    "messages": [{"role":"user","content":[{"type":"text","text":"Reply with exactly: pong"}]}]
  }'

When local --api-key auth is enabled, /v1/messages accepts either Authorization: Bearer <key> or x-api-key: <key> because Anthropic-compatible clients vary in which header they send.

The Anthropic compatibility layer currently covers text messages, system prompts, streaming text deltas, and image content blocks. Full Anthropic tool_use / tool_result round-tripping is not yet implemented.

When --api-key is configured:

curl -sS http://127.0.0.1:8765/v1/chat/completions \
  -H 'Authorization: Bearer local-secret' \
  -H 'Content-Type: application/json' \
  -d '{"model":"gpt-5.5","messages":[{"role":"user","content":"Reply with exactly: pong"}]}'

Image Recognition

The proxy forwards image input to the upstream Codex/OpenAI Responses API for vision tasks.

Supported input shapes:

  • Chat Completions: image_url parts with a data: URL or remote https:// URL, plus optional detail
  • Chat Completions: Responses-style input_image parts (passed through as-is)
  • Anthropic Messages: image content blocks with source.type of base64 or url

When using ChatGPT Codex credentials, image parts are converted to Responses API input_image parts before the upstream call. /v1/responses requests with input_image are passed through unchanged.

Chat Completions example:

BASE64_IMAGE=$(base64 < image.jpg)
curl -sS http://127.0.0.1:8765/v1/chat/completions \
  -H 'Content-Type: application/json' \
  -d '{
    "model": "gpt-5.5",
    "messages": [{
      "role": "user",
      "content": [
        {"type": "text", "text": "What is in this image?"},
        {
          "type": "image_url",
          "image_url": {
            "url": "data:image/jpeg;base64,'"$BASE64_IMAGE"'",
            "detail": "high"
          }
        }
      ]
    }]
  }'

Anthropic Messages example:

BASE64_IMAGE=$(base64 < image.jpg)
curl -sS http://127.0.0.1:8765/v1/messages \
  -H 'Content-Type: application/json' \
  -H 'anthropic-version: 2023-06-01' \
  -d '{
    "model": "gpt-5.5",
    "max_tokens": 256,
    "messages": [{
      "role": "user",
      "content": [
        {"type": "text", "text": "What is in this image?"},
        {
          "type": "image",
          "source": {
            "type": "base64",
            "media_type": "image/jpeg",
            "data": "'"$BASE64_IMAGE"'"
          }
        }
      ]
    }]
  }'

Claude Code

Claude Code speaks the Anthropic Messages API. Point it at this proxy so requests are converted to the upstream Codex/OpenAI Responses API using your existing ~/.codex/auth.json credentials.

1. Start the proxy

Start the proxy with a local API key if you want to protect the local endpoint:

codex-api-proxy start --api-key sk-tmp

ANTHROPIC_AUTH_TOKEN in Claude Code must match the value passed to --api-key. If you start the proxy without --api-key, local bearer auth is disabled and ANTHROPIC_AUTH_TOKEN is not required.

2. Configure Claude Code

Edit ~/.claude/settings.json and set the Anthropic base URL to this proxy:

{
  "env": {
    "ANTHROPIC_BASE_URL": "http://127.0.0.1:8765",
    "ANTHROPIC_AUTH_TOKEN": "sk-tmp",
    "ANTHROPIC_MODEL": "gpt-5.5",
    "CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS": "1",
    "CLAUDE_CODE_DISABLE_ADAPTIVE_THINKING": "1"
  },
  "enabledPlugins": {
    "superpowers@claude-plugins-official": true
  },
  "skipDangerousModePermissionPrompt": true,
  "theme": "dark"
}

Key fields:

  • ANTHROPIC_BASE_URL: local proxy URL, default http://127.0.0.1:8765
  • ANTHROPIC_AUTH_TOKEN: must match codex-api-proxy start --api-key ... when local auth is enabled
  • ANTHROPIC_MODEL: upstream model id exposed by /v1/models, for example gpt-5.5

Restart Claude Code after changing settings.json.

3. Verify

codex-api-proxy status --verbose
curl -sS http://127.0.0.1:8765/health

Then launch Claude Code from a terminal:

claude

Image attachments in Claude Code are sent as Anthropic image blocks and are converted by the proxy before the upstream request. Tool calling in Claude Code depends on Anthropic tool_use / tool_result support, which is not fully implemented in this proxy yet.

Operations

/health is a process liveness check. It returns the proxy version and uptime without loading credentials, refreshing tokens, writing auth.json, or contacting upstream services.

/ready checks that credentials can be loaded and shows the upstream mode without exposing secrets. It may refresh Codex/ChatGPT tokens when refresh criteria are met.

/metrics returns local request counters as JSON. /metrics/prometheus returns Prometheus text format metrics.

Successful proxied responses include x-request-id. The proxy uses incoming x-request-id or x-correlation-id when present, otherwise it generates one.

/metrics returns local request counters:

  • requests_total
  • requests_ok
  • requests_error
  • errors_by_status
  • uptime_seconds

When --log-level debug is set, chat completions log input messages and output messages through codex_api_proxy.messages and the daemon's uvicorn.error log stream. Streaming output is logged after the stream finishes. These logs can contain prompt and response data; use debug logging only in trusted environments.

Latency summaries are logged through codex_api_proxy.latency. Set --log-format json for structured JSON event logs.

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_api_proxy-0.1.6.tar.gz (40.0 kB view details)

Uploaded Source

Built Distribution

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

codex_api_proxy-0.1.6-py3-none-any.whl (30.6 kB view details)

Uploaded Python 3

File details

Details for the file codex_api_proxy-0.1.6.tar.gz.

File metadata

  • Download URL: codex_api_proxy-0.1.6.tar.gz
  • Upload date:
  • Size: 40.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.11

File hashes

Hashes for codex_api_proxy-0.1.6.tar.gz
Algorithm Hash digest
SHA256 1231f92f3d61607d0afe2ea4cdc5d564c252592a69ba26ce3f9855adea1dea9a
MD5 e789dfc3dabf7edc5caa2fedc33e165d
BLAKE2b-256 a4b09ad7c8917aa1cdaeb80e3449c9af8ea45c883f989b0e1f241d18dbaa285d

See more details on using hashes here.

File details

Details for the file codex_api_proxy-0.1.6-py3-none-any.whl.

File metadata

File hashes

Hashes for codex_api_proxy-0.1.6-py3-none-any.whl
Algorithm Hash digest
SHA256 dc92b6bf11b6153d407f05e1d9c5bf23dfb991b00dd3ff95a4eb0540c0c75305
MD5 3990ba58c467acfa1299f69c7ccaa26b
BLAKE2b-256 3a9128fbf61de0acb855600f2d8439297204bb82706e3fbf0cb339b843283e47

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