{"id":"e2f9b60b-731d-4122-9f9f-9c5893aeb5b2","slug":"codex-universal-proxy","kind":"mcp","name":"codex-universal-proxy","summary":"Use Ollama,OpenRouter, Gemini, cohere and moonshot ai with Codex plugins, MCP tools, tool_search and apply_patch. Use any plugin you want with any OpenAI compatible api.","owner":"bharat2808","repoUrl":"https://github.com/bharat2808/codex-universal-proxy","license":"MIT","licenseTier":"permissive","trust":"community","stars":18,"match":null,"fewStars":false,"format":"mcp","createdAt":"2026-06-24T21:38:09.000Z","addedAt":"2026-10-14T05:45:35.089Z","logoUrl":"https://avatars.githubusercontent.com/u/51085062?v=4","linkOnly":false,"collection":null,"skillPath":null,"categories":["search"],"tags":["ai-coding-agent","codex-app","codex-cli","local-llm","ollama","openai-codex","openrouter","responses-api"],"runtime":"node","local":true,"cloudCapable":false,"cloudCapability":"unknown","cloudReadyOnPlatform":false,"needsApiKey":false,"reviewed":false,"syncedAt":"2026-10-17T07:37:24.950Z","sample":false,"url":"https://conduits.dev/tools/codex-universal-proxy","language":"JavaScript","transports":["stdio"],"install":{"npm":"codex-universal-proxy"},"requirements":{"env":[],"upstreamMayCharge":false},"tools":null,"readme":"# Codex Universal Proxy\n\n[npm package](https://www.npmjs.com/package/codex-universal-proxy)\n\nUse Ollama, OpenRouter, and other OpenAI-compatible providers with Codex while preserving:\n\n* Codex plugins\n* MCP tools\n* `tool_search`\n* `apply_patch`\n* Image generation tools\n\nThe proxy runs locally, translates Codex-specific tool formats into provider-compatible function calls, and converts the responses back into the format Codex expects.\n\n> This project is unofficial and experimental. Codex tool formats may change between releases.\n\n## Supported Providers and Operating Systems\n\nBuilt-in provider profiles:\n\n* Google AI Studio and Vertex AI\n* NVIDIA\n* OpenRouter\n* Anthropic\n* OpenAI\n* Cohere\n* Z.AI\n* Moonshot\n* DeepSeek\n* xAI\n* Ollama\n\nCustom providers are also supported when they expose an OpenAI-compatible Responses API or\nChat Completions API.\n\nSupported operating systems:\n\n* macOS using launchd\n* Linux using a systemd user service\n* Windows using Task Scheduler, with a per-user startup fallback\n\n## Install\n\n```bash\nnpm install -g codex-universal-proxy\n\ncodex-universal-proxy init\ncodex-universal-proxy install\n```\n\nUpgrading from `codex-ollama-proxy` is automatic. The first universal command\nmigrates `~/.codex/ollama-shape-proxy` to\n`~/.codex/codex-universal-proxy`, copies legacy catalog/reference files\nforward, and replaces legacy background-service registrations. If the old\nruntime path is also a source checkout, only runtime-owned configuration,\npresets, and discovery cache data are copied.\n\nThe old `codex-ollama-proxy` executable remains an alias for scripts and shell\nhistory. Existing Codex tasks that name the legacy\n`ollama-launch-codex-app` provider continue to work through a compatibility\nprovider entry. Existing attachment files remain at their original paths so\nhistorical task JSONL references are not broken.\n\n`install` uses the native per-user background service for the current platform:\n\n* macOS: a launchd agent in `~/Library/LaunchAgents`\n* Linux: a systemd user service in `~/.config/systemd/user`\n* Windows: a Task Scheduler task that runs at sign-in\n\nThe `restart`, `uninstall`, and `logs` commands use the same cross-platform setup. On Linux,\nthe user systemd session must be available. To run without installing a background service,\nuse `codex-universal-proxy serve` in a terminal.\n\nIf `CODEX_HOME` is set during installation, the generated background service preserves that\ndirectory for future starts. Linux installations also honor `XDG_CONFIG_HOME` when locating\nthe systemd user-unit directory.\n\nThe local proxy listens on:\n\n```text\nhttp://127.0.0.1:11436\n```\n\n## Recommended Workflow: Provider Presets\n\nA preset saves your:\n\n* Provider endpoint\n* Text and image models\n* API key\n* Responses or Chat Completions adaptor\n* Routing and compatibility options\n\nCreate each provider once, then start it by name:\n\n```bash\ncodex-universal-proxy run PRESET_NAME\n```\n\n## Ollama Preset\n\nOllama exposes a local Responses-compatible API at `http://127.0.0.1:11434/v1`.\n\n```bash\ncodex-universal-proxy preset add ollama \\\n  --url \"http://127.0.0.1:11434/v1\" \\\n  --text-model \"MODEL\"\n\ncodex-universal-proxy run ollama\n```\n\nExample:\n\n```bash\ncodex-universal-proxy preset add glm \\\n  --url \"http://127.0.0.1:11434/v1\" \\\n  --text-model \"z-ai/glm-5.2\"\n\ncodex-universal-proxy run glm\n```\n\nGLM with Kimi auto-routing:\n\n```bash\ncodex-universal-proxy preset add glm-kimi \\\n  --url \"http://127.0.0.1:11434/v1\" \\\n  --text-model \"glm-5.2:cloud\" \\\n  --image-model \"kimi-k2.7-code:cloud\" \\\n  --auto-image\n\ncodex-universal-proxy run glm-kimi\n```\n\n## OpenRouter Preset\n\nExport your OpenRouter key:\n\n```bash\nexport OPENROUTER_API_KEY=\"sk-or-...\"\n```\n\nCreate the preset:\n\n```bash\ncodex-universal-proxy preset add openrouter \\\n  --provider openrouter \\\n  --text-model \"PROVIDER/MODEL\" \\\n  --api-key \"$OPENROUTER_API_KEY\"\n```\n\nRun it whenever you want to use OpenRouter:\n\n```bash\ncodex-universal-proxy run openrouter\n```\n\nExample:\n\n```bash\ncodex-universal-proxy preset add openrouter-glm \\\n  --url \"https://openrouter.ai/api/v1\" \\\n  --text-model \"z-ai/glm-5.2\" \\\n  --api-key \"$OPENROUTER_API_KEY\"\n\ncodex-universal-proxy run openrouter-glm\n```\n\nThe selected OpenRouter model must support the required API and tool-calling behavior.\n\n## Anthropic Preset\n\nAnthropic is supported through its OpenAI-compatible Chat Completions API. The\nproxy does not translate requests to the native Messages API.\n\n```bash\nexport ANTHROPIC_API_KEY=\"...\"\n\ncodex-universal-proxy preset add claude \\\n  --provider anthropic \\\n  --text-model \"claude-sonnet-5\" \\\n  --api-key \"$ANTHROPIC_API_KEY\"\n\ncodex-universal-proxy run claude\n```\n\n\n## OpenAI Preset\n\nOpenAI uses direct Responses API passthrough:\n\n```bash\nexport OPENAI_API_KEY=\"...\"\n\ncodex-universal-proxy preset add openai \\\n  --provider openai \\\n  --text-model \"gpt-5.6-sol\" \\\n  --api-key \"$OPENAI_API_KEY\"\n\ncodex-universal-proxy run openai\n```\n\n\n## Custom Responses API Preset\n\nFor any provider that exposes `POST /v1/responses`:\n\n```bash\nexport PROVIDER_API_KEY=\"...\"\n\ncodex-universal-proxy preset add custom-responses \\\n  --url \"https://provider.example/v1\" \\\n  --text-model \"MODEL\" \\\n  --api-key \"$PROVIDER_API_KEY\"\n\ncodex-universal-proxy run custom-responses\n```\n\n## Chat Completions Provider Preset\n\nSome providers only expose:\n\n```text\nPOST /v1/chat/completions\n```\n\nUse the built-in Chat Completions adaptor for these providers:\n\n```bash\nexport PROVIDER_API_KEY=\"...\"\n\ncodex-universal-proxy preset add custom-chat \\\n  --adaptor chat-completion \\\n  --url \"https://provider.example/v1\" \\\n  --text-model \"MODEL\" \\\n  --api-key \"$PROVIDER_API_KEY\"\n\ncodex-universal-proxy run custom-chat\n```\n\nThe adaptor converts Codex Responses API traffic into Chat Completions requests.\n\n### NVIDIA Example\n\n```bash\nexport NVIDIA_API_KEY=\"nvapi-...\"\n\ncodex-universal-proxy preset add nvidia \\\n  --provider nvidia \\\n  --text-model \"z-ai/glm-5.2\" \\\n  --image-model \"thinkingmachines/inkling\" \\\n  --auto-image \\\n  --api-key \"$NVIDIA_API_KEY\"\n\ncodex-universal-proxy run nvidia\n```\n\n## Avoid Storing API Keys\n\nTo save the provider configuration without storing its key:\n\n```bash\ncodex-universal-proxy preset add openrouter \\\n  --provider openrouter \\\n  --text-model \"PROVIDER/MODEL\"\n```\n\nSupply the key when activating the preset:\n\n```bash\ncodex-universal-proxy preset use openrouter \\\n  --api-key \"$OPENROUTER_API_KEY\"\n```\n\nUse `run PRESET_NAME` when the preset already contains its API key.\n\n## Running Presets\n\nStart a preset in the background:\n\n```bash\ncodex-universal-proxy run openrouter\n```\n\nShow live logs in the current terminal:\n\n```bash\ncodex-universal-proxy run openrouter --foreground\n```\n\nApply a preset without starting the proxy:\n\n```bash\ncodex-universal-proxy preset use openrouter --no-start\n```\n\nBoth `run` and `preset use` configure the selected provider and start or restart the required local proxy processes unless `--no-start` is used.\n\nAfter changing providers, restart Codex or open a new Codex thread.\n\n### Windows Desktop Model Picker Workaround\n\nThe Windows Codex Desktop app may fail to load the proxy-generated model picker\ncatalog. When that happens, activate the preset with a hardcoded Codex model\noverride:\n\n```bash\ncodex-universal-proxy run glm-kimi --model-override \"glm-5.2:cloud\"\n```\n\n`--model-override` writes the top-level `model = \"...\"` value in\n`~/.codex/config.toml`, forcing every Codex request to that model. It does not\nchange the proxy route `default_model`, `image_model`, or the stored preset.\nUse `--text-model` or `--default-model` only when you want to change proxy\nrouting instead.\n\n## Text and Image Models\n\nA preset can use separate text and image models:\n\n```bash\ncodex-universal-proxy preset add multimodal \\\n  --url \"https://provider.example/v1\" \\\n  --text-model \"TEXT_MODEL\" \\\n  --image-model \"IMAGE_MODEL\" \\\n  --auto-image \\\n  --api-key \"$PROVIDER_API_KEY\"\n```\n\nRun it normally:\n\n```bash\ncodex-universal-proxy run multimodal\n```\n\nWith `--auto-image`, images in the current user turn or its tool outputs are routed to the image model.\n\nUse the same model for both when the provider has one multimodal model:\n\n```bash\ncodex-universal-proxy preset add multimodal \\\n  --url \"https://provider.example/v1\" \\\n  --text-model \"MODEL\" \\\n  --image-model \"MODEL\" \\\n  --auto-image \\\n  --api-key \"$PROVIDER_API_KEY\"\n```\n\nSet `persist_inline_images = true` in `proxy-models.toml` to cache inline images\nunder `~/.codex/attachments` and replace historical pixels with path references.\nGenerated images are stored in the same session cache instead of temporary\nstorage, so their saved paths remain usable across follow-up turns.\nPersistence requires a stable session, thread, conversation, or prompt-cache\nidentifier; requests without one retain their inline images. Session caches\nunused for 30 days are removed lazily by default. Configure\n`inline_image_retention_days`, or set it to `0` to retain caches indefinitely.\nThe same settings can be changed without editing TOML directly:\n\n```bash\ncodex-universal-proxy route --persist-images --image-retention-days 30\n```\n\n## Image Generation\n\nImage generation is configured separately and applies across provider presets.\n\n### Gemini\n\n```bash\ncodex-universal-proxy imagine \\\n  --enable \\\n  --service gemini \\\n  --model \"gemini-2.5-flash-image\" \\\n  --api-key \"$GEMINI_API_KEY\"\n```\n\n### OpenAI\n\n```bash\ncodex-universal-proxy imagine \\\n  --enable \\\n  --service openai \\\n  --model \"gpt-image-2\" \\\n  --api-key \"$OPENAI_API_KEY\"\n```\n\n### Ollama\n\n```bash\ncodex-universal-proxy imagine \\\n  --enable \\\n  --service ollama \\\n  --model \"x/z-image-turbo\" \\\n  --base-url \"http://127.0.0.1:11434\"\n```\n\nCheck the image-generation configuration:\n\n```bash\ncodex-universal-proxy imagine --doctor\n```\n\nThe proxy uses Codex's existing `generate_image` tool. It does not inspect ordinary prompts and automatically turn them into image requests.\n\n## Local Voice Configuration\n\nThe active provider preset can optionally own a conversational `voice_model`.\nWhen it is empty, voice uses the model most recently routed for the same Codex\ntask, or the preset default before that task has made a completion request.\nWhisper and Kokoro remain in the separate speech configuration. The coordinator\nuses the model's lowest catalogued reasoning effort and omits reasoning when no\nsupported effort is known.\n\nTo let a lightweight model handle conversation and decide when Codex work is\nneeded, include both models in the preset:\n\n```bash\ncodex-universal-proxy preset add local-voice \\\n  --url \"http://127.0.0.1:11434/v1\" \\\n  --models \"qwen3-coder,qwen3:8b\" \\\n  --default-model \"qwen3-coder\" \\\n  --voice-model \"qwen3:8b\"\n```\n\nThe voice model receives one tool, `delegate_to_codex`. Plain model text is\nspoken directly through Kokoro. When the model includes a brief acknowledgement\nwith a tool call, Kokoro speaks it before the handoff. Calling the tool hands\nthe request to the preset's normal Codex model and tool loop.\n\nThe npm package supplies FFmpeg, Transformers.js Whisper, ONNX Runtime, Kokoro,\nand the Kokoro voice files. It does not depend on a system `ffmpeg`,\n`whisper-cli`, Python environment, or Homebrew. Speech model weights are\ndownloaded once into `~/.codex/codex-universal-proxy/voice-models` and reused\noffline afterward.\n\n```bash\n# Download, cache, and verify both speech models and packaged FFmpeg.\ncodex-universal-proxy voice --setup\n\n# Setup is also performed automatically here when needed.\ncodex-universal-proxy voice --enable\n```\n\nUse `voice --doctor` to repeat the complete runtime check. Both commands verify\nthe packaged FFmpeg `libopus` encoder, run a Whisper inference probe, and\nsynthesize a short Kokoro phrase. `voice --enable --no-setup` is available for\nconfiguration-only automation that deliberately performs preflight separately.\n\nEnabling voice writes these user-level Codex settings using the active proxy\nport:\n\n```toml\nexperimental_realtime_webrtc_call_base_url = \"http://127.0.0.1:11436/v1\"\nexperimental_realtime_ws_base_url = \"http://127.0.0.1:11436/v1\"\n\n[features]\nrealtime_conversation = true\n```\n\nCodex V3 posts the WebRTC offer to `/live` under the first URL, then connects\nthe sideband to the call-specific path returned in the response. Restart Codex\nafter enabling or disabling voice so the app-server reloads the transport\nconfiguration.\n\nThe built-in button then uses this pipeline:\n\n```text\nWebRTC microphone -> packaged FFmpeg/Opus -> packaged Whisper -> voice_model or task's active model\n  -> direct response -> Kokoro -> WebRTC speaker\n  or\n  -> delegate_to_codex -> preset default_model /v1/responses\n     -> Codex tools -> Kokoro -> WebRTC speaker\n```\n\nVoice handoff turns receive an extra developer instruction asking the selected\nmodel to speak briefly before tools and to always provide a concise spoken\nresult afterward. Normal Responses requests are unchanged.\n\nInspect the current conversational, transcription, and synthesis settings:\n\n```bash\ncodex-universal-proxy voice --status\n```\n\nThe conversational model is selected independently from the speech models.\nSet `--voice-model` when creating or updating a preset to dedicate a model to\nvoice coordination. The voice model must also occur in that preset's\n`--models` list:\n\n```bash\ncodex-universal-proxy preset add local-voice \\\n  --url \"http://127.0.0.1:11434/v1\" \\\n  --models \"qwen3-coder,qwen3:8b\" \\\n  --default-model \"qwen3-coder\" \\\n  --voice-model \"qwen3:8b\"\n```\n\nLeave the preset's `voice_model` empty to follow the model actively serving the\nsame Codex task. Before that task has sent a completion, voice uses the preset's\ndefault model. In both cases the coordinator requests the model's lowest\ncatalogued reasoning effort, or sends no reasoning effort when the catalog does\nnot declare one.\n\nChoose and preflight the Whisper speech-to-text model:\n\n```bash\ncodex-universal-proxy voice \\\n  --whisper-model \"onnx-community/whisper-base.en\" \\\n  --whisper-dtype q8 \\\n  --whisper-device cpu \\\n  --setup\n```\n\n`--whisper-model` must identify a Transformers.js-compatible ONNX Whisper\nrepository. Legacy GGML `.bin` files and `whisper-cli` models are not supported\nby the packaged in-process runtime.\n\nChoose and preflight the Kokoro text-to-speech model and speaker voice:\n\n```bash\ncodex-universal-proxy voice \\\n  --kokoro-model \"onnx-community/Kokoro-82M-v1.0-ONNX\" \\\n  --kokoro-voice \"af_heart\" \\\n  --kokoro-dtype q8 \\\n  --kokoro-device cpu \\\n  --kokoro-speed 1.1 \\\n  --setup\n```\n\nThe selected speaker name must exist in the selected Kokoro model. `--setup`\ndownloads any newly selected model files into the managed voice cache and runs\nreal transcription and synthesis probes before saving the configuration.\n\nChoose how speech playback is interrupted:\n\n```bash\n# Automatic barge-in when VAD detects that you started speaking (default).\ncodex-universal-proxy voice --interruption-mode vad\n\n# Hold Right Command to interrupt and record; release it to send the utterance.\ncodex-universal-proxy voice --interruption-mode manual --interruption-key right-command\ncodex-universal-proxy voice --interrupt\n```\n\nIn manual mode microphone audio is discarded while Right Command is up. Key\ndown interrupts current playback and starts a fresh buffer; key up commits that\nbuffer to Whisper. The first activation asks for macOS Input Monitoring\npermission. `voice --interrupt` remains available as a playback-only fallback.\nGeneral Codex tools remain in the delegated backend thread rather than running\nin the voice coordinator.\n\nDisable local routing:\n\n```bash\ncodex-universal-proxy voice --disable\n```\n\nThe proxy remembers pre-existing Realtime endpoint and feature values and\nrestores them when disabling voice. If you edit an endpoint manually after\nenabling voice, disable will leave that later edit untouched. Routing state is\nwritten before Codex configuration changes and recovered during installation\nif an enable or disable operation is interrupted.\n\nThe same public speech settings can be edited in\n`~/.codex/codex-universal-proxy/voice.toml`. Use the CLI for enable and disable\nso the managed restoration fields remain consistent.\n\n## Advanced Preset Options\n\nPresets can also save proxy compatibility options:\n\n```bash\ncodex-universal-proxy preset add tuned \\\n  --url \"https://provider.example/v1\" \\\n  --text-model \"MODEL\" \\\n  --dedupe-large-input \\\n  --dedupe-min-chars 1024 \\\n  --verbose-tools \\\n  --enable-find-skill \\\n  --no-stream-loop\n```\n\nAvailable preset toggles include:\n\n```text\n--auto-image / --no-auto-image\n--dedupe-large-input / --no-dedupe-large-input\n--dedupe-min-chars N\n--verbose-tools / --no-verbose-tools\n--log-upstream-body / --no-log-upstream-body\n--enable-find-skill / --no-enable-find-skill\n--stream-loop / --no-stream-loop\n```\n\nRuntime options such as `--foreground` remain on the `run` or `serve` command rather than being stored in the preset.\n\n## What the Proxy Fixes\n\nCodex can send plugins and MCP tools using OpenAI-specific namespace, dynamic-tool, managed-tool, and freeform-tool formats.\n\nMany custom providers reject these formats or fail with problems such as:\n\n```text\nunsupported call\nMCP tools are visible but never invoked\ntool_search aborts\nnamespace tools are rejected\napply_patch uses the wrong format\n```\n\nThe proxy translates these tools into ordinary provider-callable functions and restores the original Codex format when calls are returned.\n\n### Namespace and MCP Tools\n\nA Codex tool such as:\n\n```text\nmcp__storefront_builder.list_storefront_build_sessions\n```\n\ncan be exposed to the model as:\n\n```text\nmcp__storefront_builder__list_storefront_build_sessions\n```\n\nThe returned call is translated back into the namespace and tool name expected by Codex.\n\n### `tool_search`\n\nWhen a provider cannot call Codex's native managed `tool_search` tool, the proxy exposes a regular function shim and maps the result back into a native `tool_search_call`.\n\nDeferred tools discovered by `tool_search` are also made callable on the following request.\n\n### `apply_patch`\n\nCodex may expose `apply_patch` as a custom or freeform tool. The proxy preserves the format Codex requires while making the surrounding tool list compatible with custom providers.\n\n## Supported Providers\n\n* Ollama-compatible Responses API servers\n* OpenRouter models with compatible API behavior\n* Anthropic through its OpenAI-compatible Chat Completions API\n* OpenAI through its native Responses API\n* Custom providers exposing `POST /v1/responses`\n* Chat Completions providers through the built-in adaptor\n* Local Responses API shims\n\nImage generation can independently use Gemini, OpenAI, or Ollama.\n\n## Useful Commands\n\n```bash\ncodex-universal-proxy status\ncodex-universal-proxy upstream --status\ncodex-universal-proxy logs --tail 100\ncodex-universal-proxy restart\ncodex-universal-proxy run PRESET_NAME\ncodex-universal-proxy run PRESET_NAME --foreground\ncodex-universal-proxy switch openai\n```\n\n## Codex Skill\n\nGive Codex this skill URL:\n\n```text\nhttps://raw.githubusercontent.com/bharat2808/codex-universal-proxy/main/skills/codex-universal-proxy/SKILL.md\n```\n\nThen ask Codex:\n\n```text\nInstall this skill and use it to set up codex-universal-proxy.\n```\n\n## Configuration Files\n\nRuntime configuration and logs are stored under:\n\n```text\n~/.codex/codex-universal-proxy/proxy-models.toml\n~/.codex/codex-universal-proxy/imagine.toml\n~/.codex/codex-universal-proxy/voice.toml\n~/.codex/codex-universal-proxy/proxy.log\n```\n\nDebug logging is disabled by default:\n\n```toml\nverbose_tools = false\nlog_upstream_body = false\n```\n\nBe careful when enabling request-body logging because it may include prompts, tool arguments, or other sensitive data.\n\n## Known Limitations\n\n* This package is not affiliated with OpenAI.\n* Codex internal tool schemas may change.\n* Compatibility depends on the selected provider and model.\n* Models must support reliable tool calling for plugins and MCP tools to work well.\n* Some providers expose only Chat Completions and require the adaptor.\n* Web search falls back from Ollama cloud search, to local Ollama search, to DuckDuckGo HTML search.\n\n## Install a Specific Version\n\n```bash\nnpm install -g \\\n  https://registry.npmjs.org/codex-universal-proxy/-/codex-universal-proxy-0.5.0.tgz\n```\n\n## Uninstall\n\n```bash\ncodex-universal-proxy switch openai\ncodex-universal-proxy uninstall\nnpm uninstall -g codex-universal-proxy\n```\n"}