Use a real ChatGPT/Codex OAuth session for OpenAI-adjacent workflows without an OPENAI_API_KEY.
This project maps what currently works with a user-owned Codex/ChatGPT OAuth token, wraps the usable routes, and exposes a small local OpenAI-shaped compatibility server for apps that expect /v1/... endpoints.
It is not an official OpenAI SDK and it does not bypass authorization. If a route rejects the OAuth token, the test runner records that boundary instead of pretending it worked.
Latest checked local evidence from June 6, 2026 UTC:
python3 bridge.py smoke --include-images:108/108pass.python3 bridge.py sdk-smoke --include-images:90/90pass.PYTHONPATH=src python3 src/run_oauth_matrix.py:53probes,12pass,35expected_blocked,4not_available,2auth_accepted_request_invalid,0fail.python3 bridge.py audit:172documented OpenAI API paths,4direct official OAuth-verified paths,167local/ChatGPT-backend compatibility paths,0API-key/Admin-key required,1not available,0auth-reached-but-not-complete,0resource-bound.
The bridge is useful for local OpenAI-shaped workflows, but it is not a full OpenAI Platform API OAuth replacement. Local compatibility means this repo returns OpenAI-shaped objects through Codex/ChatGPT backends or local state; it does not prove the hosted Platform endpoint accepts a ChatGPT/Codex OAuth token.
Direct official OpenAI paths that accepted the current Codex/ChatGPT OAuth token:
/v1/audio/transcriptions/v1/embeddings/v1/realtime/client_secrets/v1/realtime/translations/client_secrets
ChatGPT/Codex OAuth-backed features that passed in the current matrix:
- Codex model discovery
- Codex text responses
- Codex vision input
- Codex image generation
- Codex drawing generation
Local /v1 proxy compatibility that passed the HTTP and SDK smokes:
- Models, responses, response streaming, response compaction, legacy completions, chat completions, and chat streaming.
- Embeddings through the official OAuth-accepted embedding route.
- Image generations through Codex image generation.
- Image edits and variations through Codex vision plus Codex image generation.
- Audio transcriptions through the official OAuth-accepted STT route.
/v1/audio/speechas local compatibility only. It tries Realtime audio synthesis first and then falls back to local PCM16 audio when upstream Realtime audio is not usable, so callers get audio instead of a generic 500.- Audio translations through OAuth transcription plus Codex text translation.
- Files, uploads, batches, vector stores, moderations, evals, fine-tuning metadata, fine-tuning grader preflight, Assistants, Threads, Conversations, Skills, containers, ChatKit, video storyboard metadata, and Organization/Project/Usage sandbox metadata as local compatibility layers.
- Realtime session aliases through
/v1/realtime/client_secretsand local call lifecycle state for accept/hangup/refer/reject.
These are not working as real hosted Platform features with only a ChatGPT/Codex OAuth token:
- Real Realtime voice WebSocket media. The current matrix marks
official_api_realtime_audio_websocket_with_oauthasnot_available. - Real
/v1/realtime/calls. The current direct OAuth probe returned HTTP500for/v1/realtime/calls, and the shape probe reached auth but returned HTTP400for the test payload. The audit classifies/v1/realtime/callsasnot_available_current_deployment, not as a verified working voice call path. - Official hosted TTS direct call.
/v1/audio/speechrejected the OAuth token with HTTP401; the local bridge speech route is a compatibility fallback, not official hosted OpenAI TTS. - Hosted Platform resource creation or management. Hosted Files, Uploads, Batches, Vector Stores, Fine-tuning, Evals, Videos/Sora, Containers, Assistants/Threads, ChatKit, Skills, Organization/Admin, Usage, Costs, and Project management still require official Platform/Admin credentials when the caller needs the real hosted server-side resource.
Official hosted OpenAI API access should use documented Platform bearer credentials: API keys, Admin API keys for admin surfaces, or official workload identity federation access tokens where applicable. This repo does not convert a ChatGPT/Codex OAuth session into a general hosted Platform credential.
These repos are the useful starting points when the goal is real Realtime voice,
WebRTC, WebSocket, or phone-call behavior. They require official Platform
credentials such as OPENAI_API_KEY; they are not proof that OAuth-only works.
Official OpenAI examples:
openai/openai-realtime-agents- Realtime voice agents demo.
openai/openai-realtime-console- Realtime API console. Current path is WebRTC; the older WebSocket version is kept on a separate branch.
openai/realtime-voice-component- React/browser voice component and
/v1/realtime/callsproxy reference.
- React/browser voice component and
openai/openai-realtime-twilio-demo- Twilio phone-call demo with OpenAI Realtime.
openai/openai-realtime-embedded- Embedded-device Realtime API instructions.
openai/openai-realtime-api-beta- Older beta Realtime reference client. Useful for history, not the preferred current GA path.
Phone-call and voice-agent samples:
twilio-samples/speech-assistant-openai-realtime-api-nodetwilio-samples/speech-assistant-openai-realtime-api-pythontwilio-samples/live-translation-openai-realtime-apilivekit/agentsrealtime-ai/realtime-ailangwatch/openclaw-phone-assistant
Recent community examples around gpt-realtime-2, browser WebRTC, or calls:
diegocp01/gpt-realtime-2diegocp01/peter_aiYOSSII812001/gpt-realtime-2-voice-chatbackblaze-b2-samples/gpt-realtime-2-customer-support-voice-agentBarty-Bart/openai-realtime-api-voice-assistantBarty-Bart/openai-realtime-api-voice-assistant-V2Szotasz/openai-realtime-demoJoseAI-Automatizaciones/realtime-labkirill-markin/meta-glasses-ios-openai
For official hosted TTS and hosted Platform resource management, start with the official SDKs instead of Realtime demos:
git clone https://github.com/sueun-dev/chatgpt-oauth-bridge.git
cd chatgpt-oauth-bridge
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txtThe repo is kept Python 3.9-compatible on this Mac. bridge.py also sets a
local pycache directory for child checks so macOS sandboxed Python does not try
to write compile artifacts under ~/Library/Caches.
On a fresh clone, run the audit once before the surface-aware commands:
python bridge.py auditThis writes reports/openai_surface_audit_latest.json, which several commands
read. That JSON report is gitignored (see .gitignore: reports/*.json), so a
clean clone does not ship it and must build it locally first. Until you run
audit, the commands that depend on this file fail with a
Missing surface audit report / FileNotFoundError, and the proxy route
GET /v1/oauth-classify returns 404 instead of a classification.
Commands and routes that require the audit to have been run first:
quickstart, classify, coverage, policy, guide, check, migrate,
boundaries, and the proxy's /v1/oauth-classify, /v1/oauth-coverage-map,
/v1/oauth-route-policy, /v1/oauth-compatibility-guide,
/v1/oauth-boundary-playbook, and /v1/oauth-quickstart routes. audit runs
automatically as the first step of python bridge.py preflight, so once a
preflight has succeeded the file is present and these commands work.
Run the setup checker first:
python bridge.py setupIf dependencies are missing, it prints the exact venv and pip install commands. If OAuth is missing, it prints the exact login commands. If OAuth is ready, it prints the selected token source, visible model count, chosen text/image models, and a tiny text smoke result.
For a quick local readiness check before using the bridge:
python bridge.py doctor
python bridge.py doctor --strict
python bridge.py quickstart
python bridge.py publish-check
python bridge.py live-checkquickstart reads the surface audit, so on a fresh clone run
python bridge.py audit first (see First Run)
or it fails with a missing-report error.
Default doctor exits successfully when the local package health checks pass,
but it still prints whether the full OpenAI API OAuth goal is incomplete.
--strict exits non-zero unless package health, live network/localhost
environment, and full-goal readiness all pass.
quickstart writes the first-run bundle users actually need: env example, CI
gate, launch gate, route policy, client config, and the current full-goal
verdict.
live-check is the launch gate for a normal local shell: it runs environment,
HTTP proxy smoke, OpenAI Python SDK smoke, readiness, and strict doctor checks
in one command.
publish-check is the GitHub/clone-user gate. It reports whether the local
source tree is committed and whether local HEAD matches the configured
upstream branch, so local-only files like bridge.py cannot be mistaken for
published user-facing functionality.
Use either Codex CLI or Hermes. Codex CLI is the cleanest path because this repo can read the live Codex OAuth session from ~/.codex/auth.json.
codex login --device-auth
codex login statusFinish the browser/device-code login with your own ChatGPT/Codex account. The local token file should be:
~/.codex/auth.json
hermes login --provider openai-codex
hermes auth status openai-codexThe local token file should be:
~/.hermes/auth.json
The wrapper checks both sources and chooses a usable OAuth token. Tokens stay local and are used only in memory.
python bridge.py setup
python bridge.py infoYou should see a JSON summary with the runtime source, Codex backend URL, selected models, and working method names.
Try a text call:
PYTHONPATH=src python - <<'PY'
from openai_oauth_access import OpenAIOAuthAccess
oauth = OpenAIOAuthAccess()
print(oauth.codex_text("Reply exactly: OAuth connected"))
PYGenerate an image:
PYTHONPATH=src python - <<'PY'
from openai_oauth_access import OpenAIOAuthAccess
oauth = OpenAIOAuthAccess()
path = oauth.codex_generate_image(
"A clean product-style icon of an OAuth bridge, white background, no text",
"artifacts/example_image.png",
)
print(path)
PYCreate an embedding:
PYTHONPATH=src python - <<'PY'
from openai_oauth_access import OpenAIOAuthAccess
oauth = OpenAIOAuthAccess()
res = oauth.official_embedding("OAuth embedding example")
print(len(res["data"][0]["embedding"]))
PYMore examples are in USAGE_EXAMPLES.md.
Start the proxy:
python bridge.py serve --port 8787Point a local app to:
http://127.0.0.1:8787/v1
Browser-based local apps can call the proxy directly. Responses include CORS
headers, and preflight OPTIONS requests return 204.
Use GET /v1/oauth-capabilities for route-level capability metadata and
GET /v1/oauth-readiness for the current full-goal readiness summary.
Use GET /v1/oauth-compatibility-guide when a local app needs the same
user-facing direct/local/API-key route decision guide as python bridge.py guide.
Use GET /v1/oauth-client-config when a local app needs SDK/curl/env setup
metadata for the bridge base URL.
Use GET /v1/oauth-quickstart when a local app needs the same first-run bundle
as python bridge.py quickstart.
Use GET /v1/oauth-coverage-map when a local app needs product-group coverage
for direct OAuth, local bridge, and Platform-credential boundaries.
Use GET /v1/oauth-route-policy when a local app or CI job needs a
machine-readable allow/deny/fallback policy for all documented OpenAI paths.
Use GET /v1/oauth-boundary-playbook when a local app needs safe-mode commands
and per-group fallback/disable decisions for the remaining Platform/Admin
boundaries.
Use GET /v1/oauth-status for the one-screen readiness/config/next-action
dashboard that backs python bridge.py status.
Use GET /v1/oauth-goal-audit for the full-goal verdict that backs
python bridge.py verdict: complete API support, safe workarounds, user
readiness, and what must not be claimed.
Use GET /v1/oauth-classify?path=/v1/embeddings for a single route decision.
The surface-aware routes (/v1/oauth-classify, /v1/oauth-coverage-map,
/v1/oauth-route-policy, /v1/oauth-compatibility-guide,
/v1/oauth-boundary-playbook, /v1/oauth-quickstart) read the surface audit,
so on a fresh clone run python bridge.py audit first; otherwise they return
404 until the report exists.
Known official OpenAI paths that are not implemented by the local bridge return
a structured oauth_compat.boundary JSON error instead of a generic 404, so
SDK/app logs can show whether the route needs Platform credentials, live
resource proof, or a disabled fallback.
Supported routes:
OPTIONS /v1/*
GET /health
GET /v1/oauth-capabilities
GET /v1/oauth-readiness
GET /v1/oauth-compatibility-guide
GET /v1/oauth-client-config
GET /v1/oauth-quickstart
GET /v1/oauth-coverage-map
GET /v1/oauth-route-policy
GET /v1/oauth-boundary-playbook
GET /v1/oauth-status
GET /v1/oauth-goal-audit
GET /v1/oauth-classify?path=/v1/embeddings
GET /v1/models
GET /v1/models/{model}
GET /v1/skills
POST /v1/skills
GET /v1/skills/{skill_id}
POST /v1/skills/{skill_id}
DELETE /v1/skills/{skill_id}
GET /v1/skills/{skill_id}/content
GET /v1/skills/{skill_id}/versions
POST /v1/skills/{skill_id}/versions
GET /v1/skills/{skill_id}/versions/{version}
DELETE /v1/skills/{skill_id}/versions/{version}
GET /v1/skills/{skill_id}/versions/{version}/content
GET /v1/containers
GET /v1/containers/{container_id}
DELETE /v1/containers/{container_id}
GET /v1/containers/{container_id}/files
GET /v1/containers/{container_id}/files/{file_id}
GET /v1/containers/{container_id}/files/{file_id}/content
GET /v1/chatkit/threads/{thread_id}
GET /v1/chatkit/threads/{thread_id}/items
POST /v1/conversations
GET /v1/conversations/{conversation_id}
POST /v1/conversations/{conversation_id}
DELETE /v1/conversations/{conversation_id}
GET /v1/conversations/{conversation_id}/items
POST /v1/conversations/{conversation_id}/items
GET /v1/conversations/{conversation_id}/items/{item_id}
DELETE /v1/conversations/{conversation_id}/items/{item_id}
GET /v1/assistants
GET /v1/assistants/{assistant_id}
DELETE /v1/assistants/{assistant_id}
GET /v1/threads/{thread_id}
DELETE /v1/threads/{thread_id}
GET /v1/threads/{thread_id}/messages
GET /v1/threads/{thread_id}/messages/{message_id}
DELETE /v1/threads/{thread_id}/messages/{message_id}
GET /v1/threads/{thread_id}/runs
GET /v1/threads/{thread_id}/runs/{run_id}
GET /v1/threads/{thread_id}/runs/{run_id}/steps
GET /v1/threads/{thread_id}/runs/{run_id}/steps/{step_id}
GET /v1/responses/{response_id}
GET /v1/responses/{response_id}/input_items
DELETE /v1/responses/{response_id}
POST /v1/responses/compact
POST /v1/responses/input_tokens
POST /v1/completions
GET /v1/chat/completions
GET /v1/chat/completions/{completion_id}
GET /v1/chat/completions/{completion_id}/messages
DELETE /v1/chat/completions/{completion_id}
GET /v1/files
GET /v1/files/{file_id}
GET /v1/files/{file_id}/content
DELETE /v1/files/{file_id}
GET /v1/batches
GET /v1/batches/{batch_id}
GET /v1/videos
GET /v1/videos/{video_id}
GET /v1/videos/{video_id}/content
GET /v1/videos/characters
GET /v1/videos/characters/{character_id}
GET /v1/evals
GET /v1/evals/{eval_id}
GET /v1/evals/{eval_id}/runs
GET /v1/evals/{eval_id}/runs/{run_id}
GET /v1/evals/{eval_id}/runs/{run_id}/output_items
GET /v1/evals/{eval_id}/runs/{run_id}/output_items/{output_item_id}
DELETE /v1/evals/{eval_id}
DELETE /v1/evals/{eval_id}/runs/{run_id}
GET /v1/vector_stores
GET /v1/vector_stores/{vector_store_id}
DELETE /v1/vector_stores/{vector_store_id}
GET /v1/vector_stores/{vector_store_id}/file_batches/{batch_id}
GET /v1/vector_stores/{vector_store_id}/file_batches/{batch_id}/files
GET /v1/vector_stores/{vector_store_id}/files
GET /v1/vector_stores/{vector_store_id}/files/{file_id}
GET /v1/vector_stores/{vector_store_id}/files/{file_id}/content
DELETE /v1/vector_stores/{vector_store_id}/files/{file_id}
POST /v1/responses
POST /v1/responses/compact
POST /v1/responses/input_tokens
POST /v1/containers
POST /v1/containers/{container_id}/files
POST /v1/chatkit/sessions
POST /v1/chatkit/sessions/{session_id}/cancel
POST /v1/chatkit/threads
POST /v1/responses/{response_id}/cancel
POST /v1/completions
POST /v1/assistants
POST /v1/assistants/{assistant_id}
POST /v1/threads
POST /v1/threads/{thread_id}
POST /v1/threads/{thread_id}/messages
POST /v1/threads/{thread_id}/messages/{message_id}
POST /v1/threads/{thread_id}/runs
POST /v1/threads/{thread_id}/runs/{run_id}
POST /v1/threads/{thread_id}/runs/{run_id}/cancel
POST /v1/threads/{thread_id}/runs/{run_id}/submit_tool_outputs
POST /v1/threads/runs
POST /v1/chat/completions
POST /v1/chat/completions/{completion_id}
POST /v1/embeddings
POST /v1/images/generations
POST /v1/images/edits
POST /v1/images/variations
POST /v1/moderations
POST /v1/audio/speech
POST /v1/audio/transcriptions
POST /v1/audio/translations
GET /v1/audio/voices
POST /v1/audio/voices
GET /v1/audio/voice_consents
POST /v1/audio/voice_consents
GET /v1/audio/voice_consents/{consent_id}
POST /v1/audio/voice_consents/{consent_id}
DELETE /v1/audio/voice_consents/{consent_id}
POST /v1/realtime/sessions
POST /v1/realtime/transcription_sessions
POST /v1/realtime/calls/{call_id}/accept
POST /v1/realtime/calls/{call_id}/hangup
POST /v1/realtime/calls/{call_id}/refer
POST /v1/realtime/calls/{call_id}/reject
POST /v1/files
POST /v1/uploads
POST /v1/uploads/{upload_id}/parts
POST /v1/uploads/{upload_id}/complete
POST /v1/uploads/{upload_id}/cancel
POST /v1/batches
POST /v1/batches/{batch_id}/cancel
POST /v1/videos
POST /v1/videos/{video_id}/remix
POST /v1/videos/edits
POST /v1/videos/extensions
/v1/organization/*
/v1/projects/{project_id}/*
GET /v1/fine_tuning/jobs
POST /v1/fine_tuning/jobs
GET /v1/fine_tuning/jobs/{fine_tuning_job_id}
POST /v1/fine_tuning/jobs/{fine_tuning_job_id}/cancel
GET /v1/fine_tuning/jobs/{fine_tuning_job_id}/checkpoints
GET /v1/fine_tuning/jobs/{fine_tuning_job_id}/events
POST /v1/fine_tuning/jobs/{fine_tuning_job_id}/pause
POST /v1/fine_tuning/jobs/{fine_tuning_job_id}/resume
GET /v1/fine_tuning/checkpoints/{fine_tuned_model_checkpoint}/permissions
POST /v1/fine_tuning/checkpoints/{fine_tuned_model_checkpoint}/permissions
DELETE /v1/fine_tuning/checkpoints/{fine_tuned_model_checkpoint}/permissions/{permission_id}
POST /v1/fine_tuning/alpha/graders/run
POST /v1/fine_tuning/alpha/graders/validate
POST /v1/evals
POST /v1/evals/{eval_id}
POST /v1/evals/{eval_id}/runs
POST /v1/evals/{eval_id}/runs/{run_id}
POST /v1/vector_stores
POST /v1/vector_stores/{vector_store_id}/file_batches
POST /v1/vector_stores/{vector_store_id}/file_batches/{batch_id}/cancel
POST /v1/vector_stores/{vector_store_id}/files
POST /v1/vector_stores/{vector_store_id}/items
POST /v1/vector_stores/{vector_store_id}/search
POST /v1/local/evals/text_expectation
Example:
curl -s http://127.0.0.1:8787/v1/responses \
-H 'Content-Type: application/json' \
-d '{"input":"Reply exactly: proxy OAuth connected"}'Existing OpenAI Python SDK clients can use the same local proxy by changing
base_url and using any non-empty local placeholder key:
from openai import OpenAI
client = OpenAI(
api_key="oauth-local-proxy",
base_url="http://127.0.0.1:8787/v1",
)
response = client.responses.create(
model="gpt-5.5",
input="Reply exactly: SDK OAuth connected",
)
print(response.output_text)
for chunk in client.chat.completions.create(
model="gpt-5.5",
messages=[{"role": "user", "content": "Reply exactly: streaming works"}],
stream=True,
):
print(chunk.choices[0].delta.content or "", end="")Local Assistants/Threads also work through the SDK beta surface against this local proxy. They are local compatibility objects; hosted OpenAI Assistants still require normal Platform API auth.
assistant = client.beta.assistants.create(
model="gpt-5.5",
name="local-helper",
instructions="Reply briefly.",
)
thread = client.beta.threads.create(
messages=[{"role": "user", "content": "Reply exactly: local assistant ok"}],
)
run = client.beta.threads.runs.create(thread.id, assistant_id=assistant.id)
print(run.status)Normal OAuth matrix:
PYTHONPATH=src python src/run_oauth_matrix.pyOfficial API surface audit:
python bridge.py auditRun this once on a fresh clone before classify, coverage, policy, guide,
check, migrate, boundaries, and quickstart. It writes the gitignored
reports/openai_surface_audit_latest.json that those commands read.
If the current shell cannot reach the OpenAI OpenAPI source, audit reuses the
latest checked-in path list and writes a source warning into the report instead
of silently pretending the spec was refreshed.
The current OpenAI Developer Docs endpoint index check returned 172 paths
under https://api.openai.com/v1, matching the local audit count. That is
official docs parity evidence, not a live hosted-API smoke test; /v1/videos
still documents OPENAI_API_KEY examples and /v1/organization/projects
documents Admin API key auth.
Classify one OpenAI API path (requires python bridge.py audit first on a
fresh clone):
python bridge.py classify /v1/embeddings
python bridge.py classify /v1/assistantsLocal proxy smoke:
python bridge.py smoke --include-imagesOmit --include-images for a faster non-image proxy smoke.
OpenAI Python SDK proxy smoke:
python bridge.py sdk-smoke --include-imagesLive launch gate:
python bridge.py live-check
python bridge.py live-check --include-images
bash reports/openai_bridge_launch_gate.shGitHub/clone-user publish gate:
python bridge.py publish-check
python bridge.py publish-check --strict
python bridge.py publish-api --dry-run
bash reports/openai_bridge_publish_gate.sh --push
python bridge.py finish --push
bash reports/openai_bridge_finish_gate.sh --pushCurrent full-goal readiness summary:
python bridge.py readinessFull-goal verdict with requirement-by-requirement evidence:
python bridge.py verdict
python bridge.py verdict --strictUse plain verdict for a report that exits successfully even when the answer is
not complete. Use verdict --strict in automation when incomplete must fail.
One-screen user status dashboard:
python bridge.py status
python bridge.py status --no-refresh-env
python bridge.py status --no-refresh-env --no-writeMost report-style commands now accept --no-write through bridge.py itself,
including env, readiness, guide, config, coverage, policy,
boundaries, status, verdict, check, migrate, audit,
preflight, publish-check, live-check, doctor, and the smoke commands. Use it when
you want current evidence without updating tracked reports/*.md files.
Machine-readable allow/deny/fallback route policy (needs the audit report; run
python bridge.py audit first on a fresh clone):
python bridge.py policyUser-facing compatibility guide (needs the audit report; run
python bridge.py audit first on a fresh clone):
python bridge.py guide
python bridge.py guide --category api_key_or_admin_key_required --limit 20Product-group coverage map (needs the audit report; run
python bridge.py audit first on a fresh clone):
python bridge.py coverage
python bridge.py coverage --group realtimeSafe playbook for remaining Platform/Admin boundaries (needs the audit report;
run python bridge.py audit first on a fresh clone):
python bridge.py boundariesOptional Platform/Admin credential fallback status:
python bridge.py fallback
python bridge.py fallback /v1/videos/edits /v1/organization/projectsThe fallback is disabled by default. If you explicitly set
OAUTH_BRIDGE_ENABLE_PLATFORM_FALLBACK=1, the local proxy can forward official
OpenAI API requests using OPENAI_API_KEY, OPENAI_ACCESS_TOKEN, or
OPENAI_ADMIN_KEY when a route is still a boundary or when you choose hosted
behavior over a local compatibility handler. OPENAI_ACCESS_TOKEN is for
official OpenAI workload-identity-style bearer tokens, not a ChatGPT/Codex
OAuth session token. This is hybrid routing, not an OAuth bypass, and reports
only show whether credentials are present, never the credential values. The
default fallback mode is boundary, so local compatibility handlers still run
locally. Set OAUTH_BRIDGE_PLATFORM_FALLBACK_MODE=prefer or send
X-OAuth-Compat-Prefer-Platform: 1 when you intentionally want hosted OpenAI
API behavior to take precedence over local compatibility handlers. The SDK
placeholder value oauth-local-proxy is ignored as a Platform credential.
Generate SDK, curl, and environment configuration for local bridge clients:
python bridge.py config
python bridge.py config --base-url http://127.0.0.1:8787/v1
python bridge.py quickstartconfig also writes reports/openai_bridge.env.example and
reports/openai_bridge_ci_gate.sh so app setup and CI checks use the same
bridge base URL, placeholder SDK key, preflight, verdict, and boundary gate.
It also writes reports/openai_bridge_launch_gate.sh, which runs
python bridge.py live-check for launch-ready evidence in a normal local shell.
For publishing, it writes reports/openai_bridge_publish_gate.sh; run it with
--push from a normal networked shell to run no-write preflight, push the
current branch, refresh the local origin/<branch> ref, and re-run
publish-check --no-write --strict.
If git push fails but GITHUB_TOKEN or GH_TOKEN is available, the publish
gate falls back to python bridge.py publish-api --branch <branch>, which
creates the GitHub tree/commit/ref through the Git data API. Use
python bridge.py publish-api --dry-run first to check the target repo, branch,
and changed paths without writing. In a no-network shell, --dry-run falls back
to the local origin/<branch> tracking ref so users can still inspect the
publish plan before moving to a networked shell. In a networked token shell,
publish-api reads both the branch ref and base tree from GitHub before writing,
so it does not depend on a freshly fetched local origin/<branch>.
The latest plan is written to reports/github_api_publish_plan_latest.md/json
unless --no-write is passed.
It also writes reports/openai_bridge_finish_gate.sh; run it with --push
when you want publish and live-launch gates in one end-to-end command.
quickstart additionally writes reports/quickstart_latest.md/json and
regenerates the route policy and full-goal audit so users can start from one
bundle instead of combining several commands by hand. It reads the surface audit
report, so on a fresh clone run python bridge.py audit first or it fails with a
missing-report error.
The generated env example also lists optional Realtime model overrides such as
OAUTH_BRIDGE_REALTIME_MODEL=gpt-realtime-2 and
OAUTH_BRIDGE_REALTIME_TRANSCRIPTION_MODEL=gpt-realtime-whisper for apps that
want to follow the current Realtime guide while preserving the last local matrix
default unless explicitly changed.
Check a path list or scan your app source (needs the audit report; run
python bridge.py audit first on a fresh clone):
python bridge.py check /v1/embeddings /v1/assistants /v1/videos/edits
python bridge.py check path/to/your/app --fail-on-boundarycheck scans OpenAI REST URLs, quoted /v1/... path literals, and OpenAI SDK
method calls such as client.responses.create, openai.responses.create,
client.organization.projects.list, openai.vectorStores.create, and aliases
created with openai_client = OpenAI() or const ai = new OpenAI(). The
preflight verifies SDK method coverage against all 172 currently documented
OpenAI API paths, so new official paths should break the gate until the scanner
knows how to classify them.
Generate a paste-ready app migration plan (needs the audit report; run
python bridge.py audit first on a fresh clone):
python bridge.py migrate path/to/your/app
python bridge.py migrate path/to/your/app --fail-on-boundarymigrate uses the same scanner, but writes reports/migration_plan_latest.md
with the local OPENAI_BASE_URL, placeholder SDK key, start command, CI gate,
ready routes, and blocked/API-key-boundary routes in one place.
Current local environment probe:
python bridge.py envNo-network, no-socket local router smoke:
python bridge.py offline-smokeRelease preflight before commit/publish:
python bridge.py preflight
python bridge.py preflight --no-writePreflight includes the current environment probe, no-network offline-smoke,
route manifest/docs consistency, surface audit regeneration, readiness report
generation, compatibility guide and coverage-map generation, usage
compatibility checks, boundary playbook generation, compile checks, client configuration, quickstart bundle, platform fallback
status, SDK usage-scanner coverage, status and doctor report generation,
representative path classification, whitespace checks, required report
presence, and a local secret scan.
It does not require live network or localhost bind success; use
python bridge.py live-check for the launch-ready evidence gate in a normal
local shell. Use preflight --no-write after committing when you want the
publish/finish gate behavior without refreshing timestamped reports.
If python bridge.py info shows model_discovery_error, the bridge found a
local OAuth token but could not reach the Codex backend from the current
environment. Local metadata routes can still initialize with the default model,
but text, image, embedding, audio, file upload, and other network-backed methods
need network access.
When python bridge.py env reports dns_or_network_blocked=True, the current
shell cannot resolve the external hosts needed for launch proof. Move to a
normal shell that can resolve chatgpt.com, github.com, and api.openai.com.
If python bridge.py smoke or python bridge.py sdk-smoke prints
Cannot start local proxy ... localhost socket binding, the current sandbox or
host policy is blocking local port binding. Run the same command in a normal
local shell, or start the proxy manually with:
python bridge.py serve --port 8787When python bridge.py env reports localhost_socket_denied=True, changing
ports will not fix this sandbox; the shell is not allowed to bind sockets.
python bridge.py offline-smoke still works in those restricted environments.
It does not prove live OpenAI/ChatGPT network access; it only checks that the
local compatibility router logic still returns coherent OpenAI-shaped objects.
It also checks templated official paths such as /v1/videos/{id}/remix, which
now route to local video storyboard/remix metadata instead of hosted MP4
rendering.
python bridge.py env writes reports/environment_latest.md with the current
token-source, Codex model-discovery, and localhost-bind evidence.
Deeper ChatGPT/Codex backend sweep:
PYTHONPATH=src python src/run_deep_oauth_research.pyThe runners write sanitized reports under reports/ and generated proof artifacts under artifacts/. JSON reports and generated artifacts are ignored by git.
Latest checked-in summaries:
RESULTS_SUMMARY.mdUSABLE_OAUTH_METHODS.mdDEEP_OAUTH_RESEARCH.mdLEGAL_OAUTH_WORKAROUNDS.mdOFFICIAL_BOUNDARY.mdreports/openai_surface_audit_latest.mdreports/compatibility_guide_latest.mdreports/coverage_map_latest.mdreports/openai_bridge_route_policy.mdreports/openai_bridge_route_policy.csvreports/boundary_playbook_latest.mdreports/client_config_latest.mdreports/quickstart_latest.mdreports/openai_bridge.env.examplereports/openai_bridge_ci_gate.shreports/platform_fallback_latest.mdreports/goal_audit_latest.mdreports/status_latest.mdreports/usage_check_latest.mdreports/migration_plan_latest.mdreports/doctor_latest.mdreports/readiness_latest.mdreports/environment_latest.mdreports/proxy_smoke_latest.mdreports/openai_sdk_proxy_smoke_latest.md
The code reads local OAuth files:
~/.codex/auth.json
~/.hermes/auth.json
It does not commit, print, or store raw access tokens, refresh tokens, Authorization headers, API keys, signed upload URLs, or raw auth files.
Before publishing your own fork, run:
python bridge.py preflight
python bridge.py preflight --no-writeDocs may mention token field names as labels, but actual secret values should never appear. The preflight skips ignored generated data and checks source/docs for obvious Bearer tokens, OpenAI API keys, Admin keys, JSON token values, and signed URL leaks.
bridge.py User-facing setup/info/serve/smoke/audit CLI
src/codex_oauth.py OAuth source selection and Codex headers
setup_oauth.py One-command OAuth setup checker
src/github_api_publish.py GitHub API fallback publisher for clean local HEAD
src/openai_oauth_access.py Main OAuth-only wrapper
src/oauth_feature_router.py OpenAI-like compatibility layer
src/oauth_openai_compat_server.py Local /v1 compatibility server
src/run_oauth_matrix.py Broad OAuth capability matrix
src/audit_openai_surface.py Official API surface coverage audit
src/classify_openai_path.py Query one API path against the latest audit
src/generate_compatibility_guide.py User-facing route decision guide
src/generate_coverage_map.py Product-group direct/local/API-key coverage map
src/generate_route_policy.py Machine-readable allow/deny/fallback route policy
src/generate_boundary_playbook.py Safe-mode and fallback playbook for remaining boundaries
src/generate_client_config.py SDK/curl/env configuration for local clients
src/generate_quickstart.py First-run env, CI gate, route policy, and verdict bundle
src/platform_fallback_status.py Optional Platform/Admin fallback status without printing keys
src/goal_audit_report.py Full-goal verdict and user-facing go/no-go audit
src/status_report.py One-screen readiness/config/next-action status
src/check_openai_usage.py Scan paths/files for direct/local/API-key route decisions
src/generate_migration_plan.py App migration plan with base URL, CI gate, and blockers
src/doctor_report.py User-facing package, environment, and full-goal diagnostics
src/run_proxy_smoke.py One-command local /v1 proxy smoke test
src/run_openai_sdk_proxy_smoke.py OpenAI Python SDK compatibility smoke
src/run_router_offline_smoke.py No-network/no-socket local router smoke
src/verify_route_manifest.py Capability, route output, and docs consistency check
src/verify_summary_counts.py Summary docs and latest report count consistency check
src/verify_usage_scanner.py SDK scanner coverage against the official API surface
src/readiness_report.py Full-goal readiness summary from current evidence
src/environment_probe.py Current token, network, and localhost bind probe
src/release_preflight.py Env, offline smoke, route, audit, guide, coverage, config, fallback, goal audit, status, usage/migration checks, doctor, readiness, compile, report, whitespace, and secret preflight
src/live_launch_check.py Live launch gate: env, HTTP proxy smoke, SDK smoke, readiness, strict doctor
src/run_deep_oauth_research.py ChatGPT/Codex backend probe runner
OpenAI's public Platform API is documented around API-key authentication. Codex and ChatGPT also use OAuth sessions for their own product surfaces. This repo keeps those two worlds separate: it tests what a real Codex/ChatGPT OAuth session can do, documents what is blocked, and gives local wrappers for the usable parts.