{"_id":"@abenvenuto/codex-openai-proxy","_rev":"2-b186a35d10ba7ba5e80f5c19095b8a5a","name":"@abenvenuto/codex-openai-proxy","dist-tags":{"latest":"1.3.0"},"versions":{"1.2.0":{"name":"@abenvenuto/codex-openai-proxy","version":"1.2.0","keywords":["openai","codex","proxy","openai-compatible","chatgpt"],"author":{"name":"shenyi","email":"thkdog@hotmail.com"},"license":"MIT","_id":"@abenvenuto/codex-openai-proxy@1.2.0","maintainers":[{"name":"abenvenuto","email":"augustocbenvenuto@gmail.com"}],"contributors":[{"name":"acba"}],"homepage":"https://github.com/acba/codex-openai-proxy#readme","bugs":{"url":"https://github.com/acba/codex-openai-proxy/issues"},"bin":{"codex-openai-proxy":"dist/cli.js"},"dist":{"shasum":"088538dd60de6c1a81e64dca361cea8e2b9be8fc","tarball":"https://registry.npmjs.org/@abenvenuto/codex-openai-proxy/-/codex-openai-proxy-1.2.0.tgz","fileCount":12,"integrity":"sha512-NbWEtfzx9l8hGl5/ucYMBdbzbpMa9d06qCr1/NFPjAWciYQodSKrQC45CfPmbtVnv/2dTyY0RwfEoFnoB9uUnw==","signatures":[{"sig":"MEYCIQDXueqI/OIQTWgqWKQJ2ujbmtuxM0L3oeXZedWxSYR9FwIhAK7P9JsceXVelQe8kjFpAXcA8HGAvzes+wT0r5Nwqr6G","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":49011},"main":"./dist/index.js","type":"module","exports":{".":"./dist/index.js"},"gitHead":"26ae9139598ed58065412c80ae2694a562290e9f","scripts":{"dev":"tsx watch src/cli.ts","test":"npm run build && node --test test/*.test.mjs","build":"tsc -p tsconfig.json","start":"node dist/cli.js","prepublishOnly":"npm run build"},"_npmUser":{"name":"abenvenuto","email":"augustocbenvenuto@gmail.com"},"repository":{"url":"git+https://github.com/acba/codex-openai-proxy.git","type":"git"},"_npmVersion":"11.18.0","description":"Use local Codex auth.json to expose an OpenAI-compatible proxy server","directories":{},"_nodeVersion":"26.4.0","dependencies":{"ws":"^8.21.1","fastify":"^5.2.1","commander":"^14.0.3"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.19.4","@types/ws":"^8.18.1","typescript":"^5.8.2","@types/node":"^24.0.0"},"_npmOperationalInternal":{"tmp":"tmp/codex-openai-proxy_1.2.0_1784142063518_0.5724746416996569","host":"s3://npm-registry-packages-npm-production"}},"1.3.0":{"name":"@abenvenuto/codex-openai-proxy","version":"1.3.0","description":"Use local Codex auth.json to expose an OpenAI-compatible proxy server","license":"MIT","author":{"name":"shenyi","email":"thkdog@hotmail.com"},"contributors":[{"name":"acba"}],"type":"module","main":"./dist/index.js","exports":{".":"./dist/index.js"},"bin":{"codex-openai-proxy":"dist/cli.js"},"keywords":["openai","codex","proxy","openai-compatible","chatgpt"],"repository":{"type":"git","url":"git+https://github.com/acba/codex-openai-proxy.git"},"homepage":"https://github.com/acba/codex-openai-proxy#readme","bugs":{"url":"https://github.com/acba/codex-openai-proxy/issues"},"scripts":{"dev":"tsx watch src/cli.ts","build":"tsc -p tsconfig.json","test":"npm run build && node --test test/*.test.mjs","start":"node dist/cli.js","prepublishOnly":"npm run build"},"dependencies":{"commander":"^14.0.3","fastify":"^5.2.1","ws":"^8.21.1"},"devDependencies":{"@types/node":"^24.0.0","@types/ws":"^8.18.1","tsx":"^4.19.4","typescript":"^5.8.2"},"gitHead":"4faced6682e8368788e5a71a01c00e99a939dc4d","_id":"@abenvenuto/codex-openai-proxy@1.3.0","_nodeVersion":"25.2.1","_npmVersion":"11.6.2","dist":{"integrity":"sha512-07UuQsY1d8Nx19lNn5knlxrEzi3bbaiLOQQmmw+i17iFXiguVgxicpiMAhFwepbuapBpGQMH4c9kwEH5x6OZ0w==","shasum":"9ae6e5d4476a773bcb206655d8cd30a7b9f925c6","tarball":"https://registry.npmjs.org/@abenvenuto/codex-openai-proxy/-/codex-openai-proxy-1.3.0.tgz","fileCount":12,"unpackedSize":51115,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIBo+b3+uTrkU9yVuaGkOlFDhKiRcgXpJYVbJNl4le8emAiBHgesug7JRax5FP2o5/YnKOQA4kZoenCseuLYZFS1d+Q=="}]},"_npmUser":{"name":"abenvenuto","email":"augustocbenvenuto@gmail.com"},"directories":{},"maintainers":[{"name":"abenvenuto","email":"augustocbenvenuto@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/codex-openai-proxy_1.3.0_1784232101936_0.20227184592606373"},"_hasShrinkwrap":false}},"time":{"created":"2026-07-15T19:01:03.255Z","modified":"2026-07-16T20:01:42.217Z","1.2.0":"2026-07-15T19:01:03.673Z","1.3.0":"2026-07-16T20:01:42.070Z"},"bugs":{"url":"https://github.com/acba/codex-openai-proxy/issues"},"author":{"name":"shenyi","email":"thkdog@hotmail.com"},"license":"MIT","homepage":"https://github.com/acba/codex-openai-proxy#readme","keywords":["openai","codex","proxy","openai-compatible","chatgpt"],"repository":{"type":"git","url":"git+https://github.com/acba/codex-openai-proxy.git"},"description":"Use local Codex auth.json to expose an OpenAI-compatible proxy server","contributors":[{"name":"acba"}],"maintainers":[{"name":"abenvenuto","email":"augustocbenvenuto@gmail.com"}],"readme":"# codex-openai-proxy\r\n\r\n> Maintained fork of [thkdog/codex-openai-proxy](https://github.com/thkdog/codex-openai-proxy),\r\n> originally created by [shenyi (thkdog)](https://github.com/thkdog). This fork preserves the\r\n> original work and adds updated Codex backend compatibility and OpenAI-compatible behavior.\r\n\r\nA local OpenAI-compatible proxy that reuses local Codex / ChatGPT auth state and forwards requests to `https://chatgpt.com/backend-api/codex/*`.\r\n\r\nIt exposes OpenAI-style endpoints so existing OpenAI SDK integrations and tools can work with minimal changes.\r\n\r\nCurrently supported:\r\n\r\n- `GET /health`\r\n- `GET /v1/models`\r\n- `POST /v1/responses`\r\n- `POST /v1/chat/completions`\r\n\r\n## Codex compatibility\r\n\r\nVersion 1.2.0 tracks the Codex CLI 0.144.1 backend protocol. It uses the current authenticated\r\nWebSocket transport, request headers, model catalog, and model-specific base instructions. The\r\ndefault model is `gpt-5.6-sol`; use `GET /v1/models` to see the models available to your account.\r\n\r\n### Supported Responses features\r\n\r\n- streaming and non-streaming Responses;\r\n- `reasoning.effort` validated against the selected model catalog;\r\n- `input_text`, PDF `input_file`, and `input_image` content parts;\r\n- `text.verbosity`;\r\n- strict `text.format.type=json_schema` Structured Outputs;\r\n- OpenAI-style error envelopes and HTTP status codes before streaming starts;\r\n- structured SSE errors for failures after streaming starts.\r\n\r\nStructured responses are buffered until their JSON Schema is validated. This intentionally delays\r\ntheir SSE deltas: invalid JSON is returned as `json_schema_validation_failed`, never as a successful\r\npartial response. The dependency-free validator supports the schema subset used by this proxy:\r\n`type`, `properties`, `required`, `additionalProperties`, `items`, `enum`, `description`, and\r\n`title`. Unsupported keywords fail with `unsupported_json_schema` instead of being ignored.\r\n\r\n## Quick Start\r\n\r\n### 1. Prerequisites\r\n\r\n- Node.js 18+\r\n- You are already signed in to Codex / ChatGPT on this machine\r\n- Default auth file path: `~/.codex/auth.json`\r\n\r\nYou can verify the auth file exists:\r\n\r\n```bash\r\nls ~/.codex/auth.json\r\n```\r\n\r\n### 2. Run with npx\r\n\r\n```bash\r\nnpx @abenvenuto/codex-openai-proxy\r\n```\r\n\r\nDefault listen address:\r\n\r\n```text\r\nhttp://127.0.0.1:8787\r\n```\r\n\r\nIf you are developing inside this repository, you can also run:\r\n\r\n```bash\r\nnpm install\r\nnpm run dev\r\n```\r\n\r\nOn startup, the server prints:\r\n\r\n- service URL\r\n- active auth file path\r\n- health check URL\r\n- models URL\r\n- OpenAI SDK `baseURL`\r\n- copy-paste `curl` commands for verification\r\n\r\n## CLI Options\r\n\r\nThis project uses command-line arguments only and does not read environment variables.\r\n\r\nShow help:\r\n\r\n```bash\r\nnpx @abenvenuto/codex-openai-proxy --help\r\n```\r\n\r\nAvailable options:\n\n- `-H, --host <host>`: listen host, default `127.0.0.1`\n- `-p, --port <port>`: listen port, default `8787`\n- `-a, --auth-file <path>`: auth file path, default `~/.codex/auth.json`\n- `--body-limit-mb <mb>`: maximum JSON request body size, default `75` MiB\n\nThe larger default body limit is required for Base64 file inputs. OpenAI accepts up to 50 MB of\nfiles per request, while Base64 expands the binary data by roughly one third. Fastify's original\n1 MiB default is therefore too small for ordinary PDF evidence. Because request bodies are parsed\nin memory, keep the listener on `127.0.0.1` and reduce this limit when large file inputs are not\nneeded.\n\r\nExamples:\r\n\r\n```bash\r\nnpx @abenvenuto/codex-openai-proxy --port 9000\n```\n\n```bash\nnpx @abenvenuto/codex-openai-proxy --body-limit-mb 75\n```\n\r\n```bash\r\nnpx @abenvenuto/codex-openai-proxy --host 0.0.0.0 --port 9000\r\n```\r\n\r\n```bash\r\nnpx @abenvenuto/codex-openai-proxy --auth-file ~/.codex/auth.json\r\n```\r\n\r\n```bash\r\nnpx @abenvenuto/codex-openai-proxy --host 0.0.0.0 --port 9000 --auth-file ~/.codex/auth.json\r\n```\r\n\r\nYou can also install it globally:\r\n\r\n```bash\r\nnpm install -g @abenvenuto/codex-openai-proxy\r\ncodex-openai-proxy --port 9000\r\n```\r\n\r\n## Verify\r\n\r\nHealth check:\r\n\r\n```bash\r\ncurl http://127.0.0.1:8787/health\r\n```\r\n\r\nList models:\r\n\r\n```bash\r\ncurl http://127.0.0.1:8787/v1/models\r\n```\r\n\r\nRoot info page:\r\n\r\n```bash\r\ncurl http://127.0.0.1:8787/\r\n```\r\n\r\n## curl Examples\r\n\r\nNon-streaming `chat/completions`:\r\n\r\n```bash\r\ncurl http://127.0.0.1:8787/v1/chat/completions \\\r\n  -H 'Content-Type: application/json' \\\r\n  -d '{\r\n    \"model\": \"gpt-5.6-sol\",\r\n    \"messages\": [\r\n      { \"role\": \"user\", \"content\": \"Reply with exactly ok\" }\r\n    ]\r\n  }'\r\n```\r\n\r\nStreaming `chat/completions`:\r\n\r\n```bash\r\ncurl -N http://127.0.0.1:8787/v1/chat/completions \\\r\n  -H 'Content-Type: application/json' \\\r\n  -d '{\r\n    \"model\": \"gpt-5.6-sol\",\r\n    \"stream\": true,\r\n    \"messages\": [\r\n      { \"role\": \"user\", \"content\": \"Reply with exactly ok\" }\r\n    ]\r\n  }'\r\n```\r\n\r\nNon-streaming `responses`:\r\n\r\n```bash\r\ncurl http://127.0.0.1:8787/v1/responses \\\r\n  -H 'Content-Type: application/json' \\\r\n  -d '{\r\n    \"model\": \"gpt-5.6-sol\",\r\n    \"input\": [\r\n      {\r\n        \"type\": \"message\",\r\n        \"role\": \"user\",\r\n        \"content\": [\r\n          { \"type\": \"input_text\", \"text\": \"Reply with exactly ok\" }\r\n        ]\r\n      }\r\n    ]\r\n  }'\r\n```\r\n\r\nStructured `responses`:\r\n\r\n```bash\r\ncurl http://127.0.0.1:8787/v1/responses \\\r\n  -H 'Content-Type: application/json' \\\r\n  -d '{\r\n    \"model\": \"gpt-5.6-luna\",\r\n    \"input\": \"Return a valid result object.\",\r\n    \"text\": {\r\n      \"format\": {\r\n        \"type\": \"json_schema\",\r\n        \"name\": \"result\",\r\n        \"strict\": true,\r\n        \"schema\": {\r\n          \"type\": \"object\",\r\n          \"additionalProperties\": false,\r\n          \"properties\": {\r\n            \"status\": { \"type\": \"string\", \"enum\": [\"completed\"] }\r\n          },\r\n          \"required\": [\"status\"]\r\n        }\r\n      }\r\n    }\r\n  }'\r\n```\r\n\r\nPDF input uses the standard data URL shape:\r\n\r\n```json\r\n{\r\n  \"type\": \"input_file\",\r\n  \"filename\": \"evidence.pdf\",\r\n  \"file_data\": \"data:application/pdf;base64,...\"\r\n}\r\n```\r\n\r\n## OpenAI SDK Example\r\n\r\nInstall the official SDK first:\r\n\r\n```bash\r\nnpm install openai\r\n```\r\n\r\n`chat/completions` example:\r\n\r\n```ts\r\nimport OpenAI from \"openai\";\r\n\r\nconst client = new OpenAI({\r\n  apiKey: \"dummy\",\r\n  baseURL: \"http://127.0.0.1:8787/v1\",\r\n});\r\n\r\nconst result = await client.chat.completions.create({\r\n  model: \"gpt-5.6-sol\",\r\n  messages: [\r\n    { role: \"user\", content: \"Reply with exactly ok\" },\r\n  ],\r\n});\r\n\r\nconsole.log(result.choices[0]?.message?.content);\r\n```\r\n\r\n`responses` example:\r\n\r\n```ts\r\nimport OpenAI from \"openai\";\r\n\r\nconst client = new OpenAI({\r\n  apiKey: \"dummy\",\r\n  baseURL: \"http://127.0.0.1:8787/v1\",\r\n});\r\n\r\nconst result = await client.responses.create({\r\n  model: \"gpt-5.6-sol\",\r\n  input: \"Reply with exactly ok\",\r\n});\r\n\r\nconsole.log(result.output_text);\r\n```\r\n\r\n## Reasoning effort\r\n\r\nUse the standard Responses API `reasoning.effort` field:\r\n\r\n```ts\r\nconst result = await client.responses.create({\r\n  model: \"gpt-5.6-luna\",\r\n  reasoning: { effort: \"xhigh\" },\r\n  input: \"Solve this difficult problem.\",\r\n});\r\n```\r\n\r\nFor Chat Completions, use `reasoning_effort`:\r\n\r\n```ts\r\nconst result = await client.chat.completions.create({\r\n  model: \"gpt-5.6-luna\",\r\n  reasoning_effort: \"high\",\r\n  messages: [{ role: \"user\", content: \"Solve this difficult problem.\" }],\r\n});\r\n```\r\n\r\nCodex 0.144.1 exposes `low`, `medium`, `high`, `xhigh`, and `max` for\r\n`gpt-5.6-luna`. A fully non-reasoning mode is not available; use `low` for the lightest reasoning.\r\n\r\n## iGovTI evidence evaluation\r\n\r\nThe iGovTI provider can use this proxy without an API key:\r\n\r\n```bash\r\nexport OPENAI_BASE_URL=http://127.0.0.1:8787/v1\r\n```\r\n\r\nRecommended evaluator route:\r\n\r\n```json\r\n{\r\n  \"provider\": \"openai\",\r\n  \"model\": \"gpt-5.6-luna\",\r\n  \"model_key\": \"gpt-5.6-luna\",\r\n  \"reasoning\": \"high\",\r\n  \"pdf2md\": false,\r\n  \"docx2html\": false\r\n}\r\n```\r\n\r\nThe proxy preserves the nested JSON Schema used by manager-comments temporal reassessments and\r\nvalidates the completed output before releasing it to the client.\r\n\r\n## Error behavior\r\n\r\nErrors use the OpenAI-compatible envelope:\r\n\r\n```json\r\n{\r\n  \"error\": {\r\n    \"message\": \"...\",\r\n    \"type\": \"rate_limit_error\",\r\n    \"code\": \"rate_limit_exceeded\"\r\n  }\r\n}\r\n```\r\n\r\nInvalid models and reasoning levels return HTTP 400. Authentication failures return 401, rate\r\nlimits return 429 when known before streaming, upstream timeouts return 504, and invalid structured\r\nmodel output returns 502. Once SSE headers have been sent, the same status is included in a\r\nstructured `type=error` event.\r\n\r\nThe service logs request metadata through Fastify but must not log access tokens, account IDs,\r\nauth file contents, full prompts, data URLs, or attachment contents.\r\n\r\n## Troubleshooting\r\n\r\nAuth file not found:\r\n\r\n- the default path is not `~/.codex/auth.json`\r\n- pass `--auth-file` explicitly\r\n- `--auth-file ~/.codex/auth.json` is supported and `~` will be expanded automatically\r\n\r\nInvalid auth file:\r\n\r\n- the file is not valid JSON\r\n- or it is missing `tokens.access_token`\r\n- or it is missing `tokens.account_id`\r\n\r\nPort issues:\r\n\r\n- `--port` must be an integer between `1` and `65535`\r\n- or the port is already in use\r\n\r\nExpired Codex auth state:\r\n\r\n- `/health` works but `/v1/models` fails\r\n- in that case you usually need to sign in to Codex / ChatGPT again so the local auth file is refreshed\r\n","readmeFilename":"README.md"}