This guide starts a native or containerized proxy, creates a managed API key, and connects Codex CLI or an OpenAI-compatible client.
- A Codex CLI OAuth login.
- Go 1.26 or later when building from source.
- Docker and Docker Compose only when using the container setup.
The proxy does not implement an OAuth login flow. It reads credentials already stored on disk by Codex CLI.
The default auth directory is ~/.codex. The official Codex CLI file is:
~/.codex/auth.json
The proxy also accepts flat Codex token JSON files below the configured
auth-dir. It recursively scans JSON files, ignores files that are not Codex
credentials, and ignores records marked with disabled: true.
At least one loaded credential must contain an access token or refresh token. Expired credentials are refreshed automatically before use and written back to the same file.
GitHub Releases publish a Linux amd64 binary and SHA-256 file:
codex-oauth-proxy-linux-amd64
codex-oauth-proxy-linux-amd64.sha256
After verifying the checksum, make the binary executable and place it in a
directory on PATH.
git clone https://github.com/zendext/codex-oauth-proxy.git
cd codex-oauth-proxy
go build -o codex-oauth-proxy ./cmd/serverFrom a source checkout, copy the configuration template:
cp config.example.yaml config.yamlWhen using only the release binary, create config.yaml with the minimal
equivalent:
host: "127.0.0.1"
port: 8317
auth-dir: "~/.codex"Both forms bind to 127.0.0.1:8317 and read ~/.codex. Start the server:
codex-oauth-proxy --config config.yamlThe explicit serve form is equivalent:
codex-oauth-proxy serve --config config.yamlRun codex-oauth-proxy --help for the generated command tree, or append
--help to a command for its arguments and flags.
Confirm that the process is reachable:
curl http://127.0.0.1:8317/healthzExpected response:
{"status":"ok"}SQLite is required for startup and continued operation. The process exits with an error when the database cannot be opened, migrated, initially read, or accessed by a runtime read or write.
Production deployments must run the proxy under systemd, Docker, Kubernetes, or another external supervisor with an appropriate restart policy. Correct the database path, permissions, corruption, disk, or filesystem problem before expecting a restarted process to remain healthy. The proxy does not reconnect to SQLite or continue in a degraded in-memory mode.
Keep the server running and use another terminal:
codex-oauth-proxy admin users create aliceThe command connects to http://127.0.0.1:8317 by default. It uses a
loopback-only local administration route and does not read config.yaml or
require admin-api-key.
The plaintext cop_... API key is shown only when a user is created or a key is
reset. Store it before closing the terminal output.
Add a Responses provider to the Codex CLI configuration:
model_provider = "proxy"
chatgpt_base_url = "http://127.0.0.1:8317/backend-api/"
[model_providers.proxy]
name = "Codex OAuth Proxy"
base_url = "http://127.0.0.1:8317/v1"
env_key = "COP_API_KEY"
wire_api = "responses"
supports_websockets = true
requires_openai_auth = falseSet the managed key in the environment used to start Codex:
export COP_API_KEY="cop_..."
codexrequires_openai_auth = false tells Codex CLI to send COP_API_KEY to this
proxy. The proxy replaces it with a selected Codex OAuth access token before
forwarding the request upstream.
chatgpt_base_url enables the small set of ChatGPT backend compatibility routes
that Codex CLI uses for files, account status, and hosted MCP behavior. Those
routes are not a public API for general clients.
Use the proxy base URL and managed API key:
Base URL: http://127.0.0.1:8317/v1
API key: cop_...
List models:
curl http://127.0.0.1:8317/v1/models \
-H 'Authorization: Bearer cop_...'Send a non-streaming Chat Completions request:
curl http://127.0.0.1:8317/v1/chat/completions \
-H 'Authorization: Bearer cop_...' \
-H 'Content-Type: application/json' \
-d '{
"model": "gpt-5.4",
"messages": [
{"role": "user", "content": "Hello"}
]
}'The proxy translates Chat Completions requests to upstream Responses requests.
Use /v1/responses directly when the client already supports the Responses wire
format.
Configure Zed's open_ai_compatible_api edit prediction provider with the
dedicated endpoint:
{
"edit_predictions": {
"provider": "open_ai_compatible_api",
"mode": "eager",
"allow_data_collection": "no",
"open_ai_compatible_api": {
"api_url": "http://127.0.0.1:8317/v1/zed/edit-predictions",
"model": "gpt-5.6-luna",
"prompt_format": "qwen",
"max_output_tokens": 256
}
}
}Use Zed 0.227 or later. Configure the key separately from settings.json using
either method:
-
Open Zed's Edit Prediction provider setup, select OpenAI Compatible API, and enter the managed
cop_...value in API Key. -
Set the environment variable before starting Zed from that environment:
export ZED_OPEN_AI_COMPATIBLE_EDIT_PREDICTION_API_KEY="cop_..." zed
Zed sends the configured value as Authorization: Bearer cop_.... This
compatibility endpoint is specific to edit prediction; /v1/completions is not
implemented.
Create config.yaml from the template and change the bind host:
host: "0.0.0.0"
port: 8317
auth-dir: "/root/.codex"Place Codex OAuth files under ./auths. The default Compose project mounts:
./config.yaml -> /codex-oauth-proxy/config.yaml
./auths -> /root/.codex
Start the proxy:
docker compose up -dBecause the local administration endpoint accepts only loopback clients, run the admin CLI inside the proxy container:
docker exec codex-oauth-proxy \
/codex-oauth-proxy/codex-oauth-proxy admin users create aliceThe image can also be started directly:
docker run --rm -p 8317:8317 \
-v "$PWD/config.yaml:/codex-oauth-proxy/config.yaml:ro" \
-v "$PWD/auths:/root/.codex" \
zendext/codex-oauth-proxy:latest- Review every setting in Configuration.
- Manage users and keys with Administration.
- See supported routes in API Reference.
- Understand accounting in Usage and Observability.