{"id":49558069,"url":"https://github.com/joshuasundance-swca/codex_openai_server","last_synced_at":"2026-05-03T06:17:28.630Z","repository":{"id":353533907,"uuid":"1219822201","full_name":"joshuasundance-swca/codex_openai_server","owner":"joshuasundance-swca","description":"OpenAI-compatible FastAPI server backed by locally authenticated ChatGPT Codex.","archived":false,"fork":false,"pushed_at":"2026-04-24T09:14:39.000Z","size":47,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-24T11:11:28.441Z","etag":null,"topics":["api-proxy","chat-completions","codex","copilot-cli","docker","fastapi","local-proxy","openai","openai-api","openai-compatible","python","responses-api","sse"],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/joshuasundance-swca.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-04-24T08:53:37.000Z","updated_at":"2026-04-24T09:13:27.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/joshuasundance-swca/codex_openai_server","commit_stats":null,"previous_names":["joshuasundance-swca/codex_openai_server"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/joshuasundance-swca/codex_openai_server","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joshuasundance-swca%2Fcodex_openai_server","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joshuasundance-swca%2Fcodex_openai_server/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joshuasundance-swca%2Fcodex_openai_server/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joshuasundance-swca%2Fcodex_openai_server/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/joshuasundance-swca","download_url":"https://codeload.github.com/joshuasundance-swca/codex_openai_server/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joshuasundance-swca%2Fcodex_openai_server/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32559760,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-03T03:21:47.309Z","status":"ssl_error","status_checked_at":"2026-05-03T03:21:43.884Z","response_time":103,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["api-proxy","chat-completions","codex","copilot-cli","docker","fastapi","local-proxy","openai","openai-api","openai-compatible","python","responses-api","sse"],"created_at":"2026-05-03T06:17:27.289Z","updated_at":"2026-05-03T06:17:28.617Z","avatar_url":"https://github.com/joshuasundance-swca.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# codex-openai-server\n\nIn [OpenAI's announcement for GPT-5.5](https://openai.com/index/introducing-gpt-5-5/), they said \"We'll bring GPT‑5.5 and GPT‑5.5 Pro to the API very soon.\"\n\nWell, soon is now.\n\n`codex_openai_server` is an OpenAI-compatible FastAPI server that connects to ChatGPT Codex using the local Codex CLI auth file.\n\n```pwsh\ncodex login [--device-auth]\ndocker compose up\n\n$env:COPILOT_PROVIDER_TYPE=\"openai\"\n$env:COPILOT_PROVIDER_BASE_URL=\"http://127.0.0.1:8000/v1\"\n$env:COPILOT_PROVIDER_API_KEY=\"your-super-secret-key-from-.env\"\n$env:COPILOT_MODEL=\"gpt-5.5\"\n$env:COPILOT_PROVIDER_WIRE_API=\"responses\"\n\ncopilot --disable-builtin-mcps -p \"Who are you?\"\n```\n\n```\n● Checking my documentation\n  └ # GitHub Copilot CLI Documentation\n\nI’m **GitHub Copilot CLI**, a terminal-native AI coding assistant. I can help build, edit, debug, refactor, and understand code from your command line, with GitHub and MCP-powered integrations.\n\nI’m powered by **gpt-5.5** in this session.\n\n\nChanges   +0 -0\nDuration  16s\nTokens    ↑ 67.0k • ↓ 157 • 0 (cached) • 37 (reasoning)\n```\n\n`codex_openai_server` is intended for local use on a trusted machine or private network segment. It is not hardened as a public internet-facing multi-tenant service.\n\nIt is intended to look like a regular OpenAI endpoint to clients. The server exposes:\n\n- `/v1/models`\n- `/v1/responses`\n- `/v1/chat/completions`\n\nFeatures:\n\n- async transport to the upstream Codex backend using `httpx`\n- streaming SSE support for Responses API and Chat Completions\n- tool call translation between Chat Completions and Codex Responses payloads\n- local API key protection for your compatibility server\n- optional Docker and Docker Compose local deployment\n\n## Requirements\n\n- Python 3.10+\n- Python 3.14 is the preferred version for local development\n- a local Codex CLI login with `auth.json`\n\nThis project assumes you already trust the clients that can reach it. There is no built-in rate limiting or request-size enforcement, so do not expose it directly to the public internet without adding your own edge controls.\n\nThe server reads Codex credentials from `CODEX_HOME/auth.json`. By default that resolves to your local `.codex` directory.\n\n## Stability and security posture\n\nThe package metadata currently classifies this project as alpha, and that is the right expectation for upgrades and automation around it. Keep version pins explicit if you depend on exact request or deployment behavior.\n\nThis server is meant for local use on a trusted machine or private network segment. Treat `auth.json`, your local compatibility API key, and any logged payloads as sensitive material. Routine bugs and feature requests can go through the issue tracker; suspected vulnerabilities should follow [SECURITY.md](SECURITY.md) instead of a public issue.\n\n## Installation\n\nFor a published install:\n\n```bash\npython -m pip install codex-openai-server\n```\n\nFor local development, create your virtual environment with Python 3.14 if you have it available. The package and CI still target Python 3.10+ compatibility.\n\n```bash\npython -m pip install -e .[dev]\n```\n\n## Local configuration\n\nCreate a local `.env` file from `.env.example`.\n\nRequired values:\n\n- `OPENAI_COMPAT_API_KEY`: bearer token clients must send to your local compatibility server\n\nOptional values:\n\n- `OPENAI_COMPAT_HOST`\n- `OPENAI_COMPAT_PORT`\n- `OPENAI_COMPAT_PUBLISHED_HOST`\n- `OPENAI_COMPAT_PUBLISHED_PORT`\n- `LOCAL_CODEX_HOME`\n- `OPENAI_COMPAT_LOG_LEVEL`\n- `OPENAI_COMPAT_LOG_FORMAT`\n- `OPENAI_COMPAT_DEBUG_LOGGING`\n- `OPENAI_COMPAT_LOG_PAYLOADS`\n- `OPENAI_COMPAT_LOG_UPSTREAM_BODY_LIMIT`\n\n## Run locally\n\n```bash\npython -m codex_openai_server\n```\n\nOr use the installed console script:\n\n```bash\ncodex_openai_server\n```\n\n## Use with OpenAI clients\n\nPoint your client at `http://127.0.0.1:8000/v1` and use the local API key you set in `.env`.\n\n```python\nimport openai\n\nclient = openai.OpenAI(\n    api_key=\"your-local-server-key\",\n    base_url=\"http://127.0.0.1:8000/v1\",\n)\n\nresponse = client.responses.create(\n    model=\"gpt-5.5\",\n    input=\"Reply with exactly: hello\",\n)\n\nprint(response.output_text)\n```\n\n## Use with Copilot CLI\n\nFor GPT-5 series models, configure the Copilot CLI to use the Responses wire API. The examples below use `COPILOT_MODEL` consistently for the model selection value.\n\n```powershell\n$env:COPILOT_PROVIDER_TYPE = \"openai\"\n$env:COPILOT_PROVIDER_BASE_URL = \"http://127.0.0.1:8000/v1\"\n$env:COPILOT_PROVIDER_API_KEY = \"your-local-server-key\"\n$env:COPILOT_MODEL = \"gpt-5.5\"\n$env:COPILOT_PROVIDER_WIRE_API = \"responses\"\n\ncopilot -p \"who are you?\" --disable-builtin-mcps --allow-all-tools --stream on\n```\n\nWithout `COPILOT_PROVIDER_WIRE_API=responses`, the Copilot CLI may default to the wrong wire format for GPT-5 models.\n\n## Logging\n\nThe server supports env-controlled proxy logging for debugging upstream compatibility issues.\n\n```dotenv\nOPENAI_COMPAT_LOG_LEVEL=INFO\nOPENAI_COMPAT_LOG_FORMAT=text\nOPENAI_COMPAT_DEBUG_LOGGING=false\nOPENAI_COMPAT_LOG_PAYLOADS=false\nOPENAI_COMPAT_LOG_UPSTREAM_BODY_LIMIT=4000\n```\n\nSet `OPENAI_COMPAT_DEBUG_LOGGING=true` to log request summaries for `/v1/responses` and `/v1/chat/completions`, plus upstream request and error diagnostics.\nSet `OPENAI_COMPAT_LOG_FORMAT=json` to emit structured JSON log lines for the `codex_openai_server.*` loggers.\nSet `OPENAI_COMPAT_LOG_PAYLOADS=true` only when you explicitly want full request bodies in logs.\nThe proxy automatically retries a `/responses` call once with a forced auth refresh after upstream `401`, `403`, or `404` responses. If that retry succeeds, the upstream logger emits `Upstream Codex request succeeded after auth refresh retry` with structured fields including `recovered_from_status_code` and `retried_with_fresh_auth=true`. If upstream still returns `404` after the retry, the proxy surfaces it as a `502` because that failure is treated as an upstream/auth state problem rather than a client payload problem.\n\n## Docker Compose\n\nThe Compose setup mounts your local Codex auth directory read-only into the container.\nBy default it pulls the published GHCR image for `codex_openai_server` pinned to the current release tag.\nThe default auth mount path can use `~/.codex`; on this Windows machine, `docker compose config` resolved that to the actual user home directory correctly.\n\nSet `LOCAL_CODEX_HOME` in `.env` to your real Codex directory, for example:\n\n```dotenv\nLOCAL_CODEX_HOME=~/.codex\n```\n\nThen run:\n\n```bash\ndocker compose up\n```\n\nIf you want to override the published image version explicitly:\n\n```dotenv\nCODEX_OPENAI_SERVER_IMAGE_VERSION=v0.1.0\n```\n\nThe default published-image tag is managed in the repo and updated by `bumpver`, so the default `pull_policy` is `missing` instead of `always`. That avoids re-pulling on every run while still giving you a version-pinned default.\n\nIf you want to build and use the image locally, use the tracked override file:\n\n```bash\ndocker compose -f docker-compose.yaml -f docker-compose.local.yaml up --build\n```\n\nThe repository Dockerfile defaults to Python 3.14 for local image builds. If you want to verify the minimum supported runtime explicitly, override the build arg, for example:\n\n```bash\ndocker build --build-arg PYTHON_VERSION=3.10 -t codex_openai_server:py310 .\n```\n\nThat override switches the image tag to `codex_openai_server:local`, sets `pull_policy: never`, bind-mounts the repository into `/workspace`, and runs `uvicorn --reload` with `PYTHONPATH=/workspace` so Python code changes are picked up without rebuilding the image.\n\nThe first run still needs `--build` so the local image exists. After that, you can usually use:\n\n```bash\ndocker compose -f docker-compose.yaml -f docker-compose.local.yaml up\n```\n\nOn Docker Desktop for Windows, the local override forces polling-based reloads so file changes inside the bind mount are detected reliably.\n\n## Release management\n\nThis project uses `bumpver` for version and tag management.\n\nPreview the next patch release:\n\n```bash\nbumpver update --patch --dry --no-fetch\n```\n\nCreate the version commit and `vX.Y.Z` tag locally with the direct bumpver flow:\n\n```bash\nbumpver update --patch --no-push\n```\n\nThat version bump also updates the default published Docker tag used in Compose.\n\nThe GitHub Actions release workflows are set up to publish Python artifacts to PyPI and Docker images to GHCR from version tags. The Docker publish workflow also smoke-tests the built image before it pushes release tags.\n\nFor publish-facing changes, keep [CHANGELOG.md](CHANGELOG.md), [README.md](README.md), and package metadata in sync so PyPI and GitHub release surfaces tell the same story.\n\n## Development\n\nRun checks locally:\n\n```bash\npre-commit run --all-files\npython -m pytest\n```\n\nContributor workflow notes are in [CONTRIBUTING.md](CONTRIBUTING.md).\n\n## Acknowledgements\n\nThanks to Simon Willison for the blog post [A pelican for GPT-5.5 via the semi-official Codex backdoor API](https://simonwillison.net/2026/Apr/23/gpt-5-5/) and for publishing [llm-openai-via-codex](https://github.com/simonw/llm-openai-via-codex), which helped inspire this OpenAI-compatible Codex proxy.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjoshuasundance-swca%2Fcodex_openai_server","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjoshuasundance-swca%2Fcodex_openai_server","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjoshuasundance-swca%2Fcodex_openai_server/lists"}