Wrap OpenAI's Codex to an OpenAI compatible endpoint using Cloudflare Workers
๐ค OpenAI Codex CLI Wrapper
Transform OpenAI's Codex models into OpenAI-compatible endpoints using Cloudflare Workers. Access advanced reasoning capabilities and seamless API compatibility, powered by OAuth2 authentication and the same infrastructure that drives the official OpenAI Codex CLI.
โจ Features
- ๐ OAuth2 Authentication - Uses your OpenAI account credentials via Codex CLI
- ๐ฏ OpenAI-Compatible API - Drop-in replacement for OpenAI endpoints
- ๐ OpenAI SDK Support - Works with official OpenAI SDKs and libraries
- ๐ง Advanced Reasoning - Configurable reasoning effort with
think-tagscompatibility - ๐ก๏ธ API Key Security - Optional authentication layer for endpoint access
- ๐ Third-party Integration - Compatible with Open WebUI, Cline, and more
- โก Cloudflare Workers - Global edge deployment with low latency
- ๐ Smart Token Management - Automatic token refresh with KV storage
- ๐ก Real-time Streaming - Server-sent events for live responses
- ๐ฆ Ollama Compatibility - Full Ollama API support for local model workflows
- ๐๏ธ Flexible Tool Support - OpenAI-compatible function calling
๐ Quick Start
Deployment Options
Choose your preferred deployment method:
- ๐ Cloudflare Workers (Recommended) - Serverless, global edge deployment
- ๐ณ Docker - Self-hosted with full control - See Docker Guide
Prerequisites (Cloudflare Workers)
- OpenAI Account with Codex CLI access
- Cloudflare Account with Workers enabled
- Wrangler CLI installed (
npm install -g wrangler)
Step 1: Get OAuth2 Credentials
You need OAuth2 credentials from the official OpenAI Codex CLI.
Using OpenAI Codex CLI
- Install OpenAI Codex CLI:
npm install -g @openai/codex
# Alternatively: brew install codex
- Start Codex and authenticate:
codex
Select "Sign in with ChatGPT" when prompted. You'll need a Plus, Pro, or Team ChatGPT account to access the latest models, including gpt-5, at no extra cost to your plan.
- Complete authentication:
localhost:1455. Open the provided URL in your browser to complete the authentication flow.
- Locate the credentials file:
C:\Users\USERNAME\.codex\auth.json
macOS/Linux:
~/.codex/auth.json
- Copy the credentials:
{
"tokens": {
"id_token": "eyJhbGciOiJSUzI1NiIs...",
"access_token": "sk-proj-...",
"refreshtoken": "rft...",
"account_id": "user-..."
},
"last_refresh": "2024-01-15T10:30:00.000Z"
}
Important Migration Notes
If you've used the Codex CLI before:
- Update the CLI and ensure
codex --versionis 0.20.0 or later - Delete
~/.codex/auth.json(orC:\Users\USERNAME\.codex\auth.jsonon Windows) - Run
codexand authenticate again
Headless/Remote Server Setup
If you're on a headless server or SSH'd into a remote machine:
Option 1: Copy credentials from local machine
# Authenticate locally first, then copy the auth.json file scp ~/.codex/auth.json user@remote:~/.codex/auth.json
Option 2: Port forwarding for remote authentication
# From your local machine, create an SSH tunnel ssh -L 1455:localhost:1455 user@remote-host
Then run codex in the SSH session and open localhost:1455 locally
Alternative: API Key Authentication
You can also use your OpenAI API key instead:
export OPENAIAPIKEY="your-api-key-here"
To force API key usage even when ChatGPT auth exists:
codex --config preferredauthmethod="apikey"
Step 2: Create KV Namespace
# Create a KV namespace for token caching
wrangler kv namespace create "KV"
Note the namespace ID returned and update wrangler.toml:
kv_namespaces = [ { binding = "KV", id = "your-kv-namespace-id" } ]
Step 3: Environment Setup
Create a .dev.vars file:
# Required: API key for client authentication OPENAIAPIKEY=sk-your-secret-api-key-here
Required: Codex CLI authentication JSON
OPENAICODEXAUTH={"tokens":{"idtoken":"eyJ...","accesstoken":"sk-proj-...","refreshtoken":"rft...","accountid":"user-..."},"lastrefresh":"2024-01-15T10:30:00.000Z"}
Required: ChatGPT API configuration
CHATGPTLOCALCLIENTID=yourclientidhere
CHATGPTRESPONSESURL=https://chatgpt.com/backend-api/codex/responses
Optional: Ollama integration
OLLAMAAPIURL=http://localhost:11434
Optional: Reasoning configuration
REASONING_EFFORT=medium
REASONING_SUMMARY=auto
REASONING_COMPAT=think-tags
Optional: Debug settings
VERBOSE=false
DEBUG_MODEL=
For production, set the secrets:
wrangler secret put OPENAIAPIKEY wrangler secret put OPENAICODEXAUTH wrangler secret put CHATGPTLOCALCLIENT_ID wrangler secret put CHATGPTRESPONSESURL
Step 4: Deploy
Option A: Cloudflare Workers (Recommended)
# Install dependencies
npm install
Deploy to Cloudflare Workers
npm run deploy
Or run locally for development
npm run dev
Option B: Docker Deployment
For self-hosted deployment with Docker, see the comprehensive Docker Deployment Guide.
Quick Docker start with pre-built image:
# Pull and run the latest image docker pull ghcr.io/gewoonjaap/codex-openai-wrapper:latest
Create environment file
echo "OPENAIAPIKEY=sk-your-api-key-here" > .env
echo "OPENAICODEXAUTH={...your-auth-json...}" >> .env
Run the container
docker run -d \
--name codex-openai-wrapper \
-p 8787:8787 \
--env-file .env \
ghcr.io/gewoonjaap/codex-openai-wrapper:latest
Or use Docker Compose for development:
git clone https://github.com/GewoonJaap/codex-openai-wrapper.git cd codex-openai-wrapper cp .dev.vars.example .dev.vars Edit .dev.vars with your configuration
docker-compose up -d
The service will be available at http://localhost:8787
๐ง Configuration
Environment Variables
Core Configuration
| Variable | Required | Description | |----------|----------|-------------| | OPENAIAPIKEY | โ
| API key for client authentication | | OPENAICODEXAUTH | โ
| OAuth2 credentials JSON from Codex CLI | | CHATGPTLOCALCLIENT_ID | โ
| ChatGPT client ID | | CHATGPTRESPONSESURL | โ
| ChatGPT API endpoint URL |
Reasoning & Intelligence
| Variable | Default | Description | |----------|---------|-------------| | REASONING_EFFORT | minimal | Reasoning effort level: minimal, low, medium, high | | REASONING_SUMMARY | auto | Reasoning summary mode: auto, on, off | | REASONING_COMPAT | think-tags | Reasoning output format: think-tags, standard |
Integration & Tools
| Variable | Default | Description | |----------|---------|-------------| | OLLAMAAPIURL | http://localhost:11434 | Ollama instance URL for local model integration | | DEBUG_MODEL | - | Override model for debugging purposes | | VERBOSE | false | Enable detailed debug logging |
Authentication Security
- When
OPENAIAPIKEYis set, all/v1/and/api/endpoints require authentication - Clients must include the header:
Authorization: Bearer <your-api-key> - Recommended format:
sk-followed by a random string (e.g.,sk-1234567890abcdef...) - Without this variable, endpoints are publicly accessible (not recommended for production)
OAuth Token Management
- Automatic Refresh: Tokens are automatically refreshed when they expire or are older than 28 days
- KV Persistence: Refreshed tokens are stored in Cloudflare KV for persistence across requests
- Fallback Logic: Falls back from KV โ environment โ refresh โ retry seamlessly
- Debug Logging: Comprehensive token source tracking for troubleshooting
KV Namespaces
| Binding | Purpose | |---------|---------| | KV | OAuth token caching and session management |
๐ฏ API Endpoints
Base URL
https://your-worker.your-subdomain.workers.dev
OpenAI-Compatible Endpoints
Chat Completions
POST /v1/chat/completions
Authorization: Bearer sk-your-api-key-here
Content-Type: application/json
{ "model": "gpt-4", "messages": [ { "role": "system", "content": "You are a helpful assistant." }, { "role": "user", "content": "Explain quantum computing in simple terms" } ], "stream": true }
Advanced Reasoning
Enable enhanced reasoning capabilities:{
"model": "gpt-4",
"messages": [
{
"role": "user",
"content": "Solve this step by step: What is the derivative of x^3 + 2x^2 - 5x + 3?"
}
],
"reasoning": {
"effort": "high",
"summary": "on"
}
}
Text Completions
POST /v1/completions
Authorization: Bearer sk-your-api-key-here
Content-Type: application/json
{ "model": "gpt-3.5-turbo-instruct", "prompt": "Write a Python function to calculate fibonacci numbers:", "max_tokens": 150, "stream": true }
List Models
GET /v1/models
Authorization: Bearer sk-your-api-key-here
Response:
{ "object": "list", "data": [ { "id": "gpt-4", "object": "model", "created": 1708976947, "owned_by": "openai-codex" } ] }
Ollama-Compatible Endpoints
Chat Interface
POST /api/chat
Authorization: Bearer sk-your-api-key-here
Content-Type: application/json
{ "model": "llama2", "messages": [ {"role": "user", "content": "Hello!"} ], "stream": true }
List Models
GET /api/tags
Authorization: Bearer sk-your-api-key-here
Model Information
POST /api/show
Authorization: Bearer sk-your-api-key-here
Content-Type: application/json
{ "name": "llama2" }
Utility Endpoints
Health Check
GET /health
No authentication required
Service Information
GET /
No authentication required
๐ ๏ธ Tool Calling Support
The wrapper supports OpenAI-compatible tool calling (function calling) with seamless integration.
Example Tool Call
const response = await fetch('/v1/chat/completions', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer sk-your-api-key-here'
},
body: JSON.stringify({
model: 'gpt-4',
messages: [
{ role: 'user', content: 'What is the weather in Tokyo?' }
],
tools: [
{
type: 'function',
function: {
name: 'get_weather',
description: 'Get current weather information for a location',
parameters: {
type: 'object',
properties: {
location: {
type: 'string',
description: 'City name'
},
unit: {
type: 'string',
enum: ['celsius', 'fahrenheit'],
description: 'Temperature unit'
}
},
required: ['location']
}
}
}
],
tool_choice: 'auto'
})
});
Tool Choice Options
auto: Let the model decide whether to call a functionnone: Disable function calling{"type": "function", "function": {"name": "function_name"}}: Force a specific function call
๐ป Usage Examples
Cline Integration
Cline is a powerful AI assistant extension for VS Code:
- Install Cline in VS Code from the Extensions marketplace
- Configure OpenAI API settings:
https://your-worker.workers.dev/v1
- Set API Key to: sk-your-secret-api-key-here
- Select models:
gpt-4 for complex reasoning tasks
- Use gpt-3.5-turbo for faster responses
Open WebUI Integration
- Add as OpenAI-compatible endpoint:
https://your-worker.workers.dev/v1
- API Key: sk-your-secret-api-key-here
- Auto-discovery:
/v1/models endpoint.
OpenAI SDK (Python)
from openai import OpenAI
Initialize with your worker endpoint
client = OpenAI(
base_url="https://your-worker.workers.dev/v1",
api_key="sk-your-secret-api-key-here"
)
Chat completion with reasoning
response = client.chat.completions.create(
model="gpt-4",
messages=[
{"role": "system", "content": "You are a helpful coding assistant."},
{"role": "user", "content": "Write a binary search algorithm in Python"}
],
extra_body={
"reasoning": {
"effort": "high",
"summary": "on"
}
},
stream=True
)
for chunk in response: if chunk.choices[0].delta.content: print(chunk.choices[0].delta.content, end="")
OpenAI SDK (JavaScript/TypeScript)
import OpenAI from 'openai';
const openai = new OpenAI({ baseURL: 'https://your-worker.workers.dev/v1', apiKey: 'sk-your-secret-api-key-here', });
const stream = await openai.chat.completions.create({ model: 'gpt-4', messages: [ { role: 'user', content: 'Explain async/await in JavaScript' } ], stream: true, });
for await (const chunk of stream) { const content = chunk.choices[0]?.delta?.content || ''; process.stdout.write(content); }
cURL Examples
# Chat completion
curl -X POST https://your-worker.workers.dev/v1/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer sk-your-secret-api-key-here" \
-d '{
"model": "gpt-4",
"messages": [
{"role": "user", "content": "Explain machine learning"}
]
}'
Ollama chat
curl -X POST https://your-worker.workers.dev/api/chat \
-H "Content-Type: application/json" \
-H "Authorization: Bearer sk-your-secret-api-key-here" \
-d '{
"model": "llama2",
"messages": [
{"role": "user", "content": "Hello world!"}
]
}'
LiteLLM Integration
LiteLLM works seamlessly with the wrapper:
import litellm
Configure LiteLLM to use your worker
litellm.api_base = "https://your-worker.workers.dev/v1"
litellm.api_key = "sk-your-secret-api-key-here"
Use with reasoning capabilities
response = litellm.completion(
model="gpt-4",
messages=[
{"role": "user", "content": "Solve this step by step: What is 15 * 24?"}
],
extra_body={
"reasoning": {
"effort": "medium",
"summary": "auto"
}
},
stream=True
)
for chunk in response: if chunk.choices[0].delta.content: print(chunk.choices[0].delta.content, end="")
๐ง Advanced Reasoning
The wrapper provides sophisticated reasoning capabilities with multiple configuration options:
Reasoning Modes
Effort Levels
minimal: Basic reasoning with minimal token overheadmedium: Balanced reasoning for most use caseshigh: Deep reasoning for complex problems
Summary Options
auto: Automatically decide when to include reasoning summarieson: Always include reasoning summaries in responsesoff: Never include reasoning summaries
Compatibility Formats
think-tags: Wrap reasoning in<think>tags for DeepSeek R1-style output
Configuration Examples
Environment-level configuration (applies to all requests):
REASONING_EFFORT=high REASONING_SUMMARY=on REASONING_COMPAT=think-tags
Request-level overrides:
{ "model": "gpt-4", "messages": [...], "reasoning": { "effort": "high", "summary": "on" } }
Reasoning Output Format
When reasoning is enabled, responses include structured thinking:
{
"id": "chatcmpl-123",
"object": "chat.completion.chunk",
"created": 1708976947,
"model": "gpt-4",
"choices": [{
"index": 0,
"delta": {
"content": "<think>\nLet me break this problem down step by step...\n</think>\n\nTo solve this equation..."
},
"finish_reason": null
}]
}
๐จ Troubleshooting
Common Issues
401 Authentication Error
- Verify your
OPENAIAPIKEYis correctly set - Check if client is sending
Authorization: Bearer <key>header - Ensure the API key format starts with
sk-
- Check if your
OPENAICODEXAUTHcredentials are valid - Ensure the refresh token hasn't expired
- Verify the JSON format matches the expected structure
- Confirm KV namespace is correctly configured in
wrangler.toml - Check KV namespace permissions in Cloudflare dashboard
- Verify the binding name matches (
KV)
- Check if
CHATGPTRESPONSESURLis accessible - Verify network connectivity from Cloudflare Workers
- Ensure OAuth tokens have proper scopes
Debug Endpoints
# Check authentication status
curl -X POST https://your-worker.workers.dev/debug/auth \
-H "Authorization: Bearer sk-your-api-key-here"
Test token refresh
curl -X POST https://your-worker.workers.dev/debug/refresh \
-H "Authorization: Bearer sk-your-api-key-here"
๐๏ธ How It Works
graph TD
A[Client Request] --> B[Cloudflare Worker]
B --> C[API Key Validation]
C --> D{Valid API Key?}
D -->|No| E[401 Unauthorized]
D -->|Yes| F{Token in KV Cache?}
F -->|Yes| G[Use Cached Token]
F -->|No| H[Check Environment Token]
H --> I{Token Valid?}
I -->|Yes| J[Cache & Use Token]
I -->|No| K[Refresh Token]
K --> L[Cache New Token]
G --> M[Call ChatGPT API]
J --> M
L --> M
M --> N{Success?}
N -->|No| O[Auto-retry with Refresh]
N -->|Yes| P[Apply Reasoning]
O --> P
P --> Q[Stream Response]
Q --> R[OpenAI Format]
R --> S[Client Response]
The wrapper acts as a secure translation layer, managing OAuth2 authentication automatically while providing OpenAI-compatible responses with advanced reasoning capabilities.
๐ Security Features
- API Key Authentication: Configurable endpoint protection
- OAuth2 Token Management: Secure credential handling
- Automatic Token Refresh: Seamless session management
- KV Storage Encryption: Secure token persistence
- Environment Isolation: Separate dev/prod configurations
- CORS Protection: Configurable cross-origin policies
๐ Performance
- Global Edge Deployment: Cloudflare's worldwide network
- Intelligent Caching: KV-based token management
- Streaming Responses: Real-time data delivery
- Connection Pooling: Optimized upstream connections
- Automatic Retries: Resilient error handling
๐ค Contributing
- Fork the repository: https://github.com/GewoonJaap/codex-openai-wrapper
- Create a feature branch:
git checkout -b feature-name - Make your changes and add tests
- Run linting:
npm run lint - Test thoroughly:
npm test - Commit your changes:
git commit -am 'Add feature' - Push to the branch:
git push origin feature-name - Submit a pull request
Development Setup
git clone https://github.com/GewoonJaap/codex-openai-wrapper.git
cd codex-openai-wrapper
npm install
cp .dev.vars.example .dev.vars
Edit .dev.vars with your configuration
npm run dev
Available Scripts
npm run dev # Start development server
npm run deploy # Deploy to Cloudflare Workers
npm run lint # Run ESLint and TypeScript checks
npm run format # Format code with Prettier
npm test # Run test suite
npm run build # Build the project
๐ License
This codebase is provided for personal use and self-hosting only.
Redistribution of the codebase, whether in original or modified form, is not permitted without prior written consent from the author.
You may fork and modify the repository solely for the purpose of running and self-hosting your own instance.
Any other form of distribution, sublicensing, or commercial use is strictly prohibited unless explicitly authorized.
๐ Acknowledgments
- Inspired by the official OpenAI Codex CLI
- Built on Cloudflare Workers
- Uses Hono web framework
- Token management patterns from OpenAI SDK
โ ๏ธ Important: This project uses OpenAI's Codex API which may have usage limits and terms of service. Please ensure compliance with OpenAI's policies when using this wrapper.
