Use Ollama, OpenRouter, and other OpenAI-compatible providers with Codex while preserving:
- Codex plugins
- MCP tools
tool_searchapply_patch- Image generation tools
The proxy runs locally, translates Codex-specific tool formats into provider-compatible function calls, and converts the responses back into the format Codex expects.
This project is unofficial and experimental. Codex tool formats may change between releases.
Built-in provider profiles:
- Google AI Studio and Vertex AI
- NVIDIA
- OpenRouter
- Anthropic
- OpenAI
- Cohere
- Z.AI
- Moonshot
- DeepSeek
- xAI
- Ollama
Custom providers are also supported when they expose an OpenAI-compatible Responses API or Chat Completions API.
Supported operating systems:
- macOS using launchd
- Linux using a systemd user service
- Windows using Task Scheduler, with a per-user startup fallback
npm install -g codex-universal-proxy
codex-universal-proxy init
codex-universal-proxy installUpgrading from codex-ollama-proxy is automatic. The first universal command
migrates ~/.codex/ollama-shape-proxy to
~/.codex/codex-universal-proxy, copies legacy catalog/reference files
forward, and replaces legacy background-service registrations. If the old
runtime path is also a source checkout, only runtime-owned configuration,
presets, and discovery cache data are copied.
The old codex-ollama-proxy executable remains an alias for scripts and shell
history. Existing Codex tasks that name the legacy
ollama-launch-codex-app provider continue to work through a compatibility
provider entry. Existing attachment files remain at their original paths so
historical task JSONL references are not broken.
install uses the native per-user background service for the current platform:
- macOS: a launchd agent in
~/Library/LaunchAgents - Linux: a systemd user service in
~/.config/systemd/user - Windows: a Task Scheduler task that runs at sign-in
The restart, uninstall, and logs commands use the same cross-platform setup. On Linux,
the user systemd session must be available. To run without installing a background service,
use codex-universal-proxy serve in a terminal.
If CODEX_HOME is set during installation, the generated background service preserves that
directory for future starts. Linux installations also honor XDG_CONFIG_HOME when locating
the systemd user-unit directory.
The local proxy listens on:
http://127.0.0.1:11436
A preset saves your:
- Provider endpoint
- Text and image models
- API key
- Responses or Chat Completions adaptor
- Routing and compatibility options
Create each provider once, then start it by name:
codex-universal-proxy run PRESET_NAMEOllama exposes a local Responses-compatible API at http://127.0.0.1:11434/v1.
codex-universal-proxy preset add ollama \
--url "http://127.0.0.1:11434/v1" \
--text-model "MODEL"
codex-universal-proxy run ollamaExample:
codex-universal-proxy preset add glm \
--url "http://127.0.0.1:11434/v1" \
--text-model "z-ai/glm-5.2"
codex-universal-proxy run glmGLM with Kimi auto-routing:
codex-universal-proxy preset add glm-kimi \
--url "http://127.0.0.1:11434/v1" \
--text-model "glm-5.2:cloud" \
--image-model "kimi-k2.7-code:cloud" \
--auto-image
codex-universal-proxy run glm-kimiExport your OpenRouter key:
export OPENROUTER_API_KEY="sk-or-..."Create the preset:
codex-universal-proxy preset add openrouter \
--provider openrouter \
--text-model "PROVIDER/MODEL" \
--api-key "$OPENROUTER_API_KEY"Run it whenever you want to use OpenRouter:
codex-universal-proxy run openrouterExample:
codex-universal-proxy preset add openrouter-glm \
--url "https://openrouter.ai/api/v1" \
--text-model "z-ai/glm-5.2" \
--api-key "$OPENROUTER_API_KEY"
codex-universal-proxy run openrouter-glmThe selected OpenRouter model must support the required API and tool-calling behavior.
Anthropic is supported through its OpenAI-compatible Chat Completions API. The proxy does not translate requests to the native Messages API.
export ANTHROPIC_API_KEY="..."
codex-universal-proxy preset add claude \
--provider anthropic \
--text-model "claude-sonnet-5" \
--api-key "$ANTHROPIC_API_KEY"
codex-universal-proxy run claudeOpenAI uses direct Responses API passthrough:
export OPENAI_API_KEY="..."
codex-universal-proxy preset add openai \
--provider openai \
--text-model "gpt-5.6-sol" \
--api-key "$OPENAI_API_KEY"
codex-universal-proxy run openaiFor any provider that exposes POST /v1/responses:
export PROVIDER_API_KEY="..."
codex-universal-proxy preset add custom-responses \
--url "https://provider.example/v1" \
--text-model "MODEL" \
--api-key "$PROVIDER_API_KEY"
codex-universal-proxy run custom-responsesSome providers only expose:
POST /v1/chat/completions
Use the built-in Chat Completions adaptor for these providers:
export PROVIDER_API_KEY="..."
codex-universal-proxy preset add custom-chat \
--adaptor chat-completion \
--url "https://provider.example/v1" \
--text-model "MODEL" \
--api-key "$PROVIDER_API_KEY"
codex-universal-proxy run custom-chatThe adaptor converts Codex Responses API traffic into Chat Completions requests.
export NVIDIA_API_KEY="nvapi-..."
codex-universal-proxy preset add nvidia \
--provider nvidia \
--text-model "z-ai/glm-5.2" \
--image-model "thinkingmachines/inkling" \
--auto-image \
--api-key "$NVIDIA_API_KEY"
codex-universal-proxy run nvidiaTo save the provider configuration without storing its key:
codex-universal-proxy preset add openrouter \
--provider openrouter \
--text-model "PROVIDER/MODEL"Supply the key when activating the preset:
codex-universal-proxy preset use openrouter \
--api-key "$OPENROUTER_API_KEY"Use run PRESET_NAME when the preset already contains its API key.
Start a preset in the background:
codex-universal-proxy run openrouterShow live logs in the current terminal:
codex-universal-proxy run openrouter --foregroundApply a preset without starting the proxy:
codex-universal-proxy preset use openrouter --no-startBoth run and preset use configure the selected provider and start or restart the required local proxy processes unless --no-start is used.
After changing providers, restart Codex or open a new Codex thread.
The Windows Codex Desktop app may fail to load the proxy-generated model picker catalog. When that happens, activate the preset with a hardcoded Codex model override:
codex-universal-proxy run glm-kimi --model-override "glm-5.2:cloud"--model-override writes the top-level model = "..." value in
~/.codex/config.toml, forcing every Codex request to that model. It does not
change the proxy route default_model, image_model, or the stored preset.
Use --text-model or --default-model only when you want to change proxy
routing instead.
A preset can use separate text and image models:
codex-universal-proxy preset add multimodal \
--url "https://provider.example/v1" \
--text-model "TEXT_MODEL" \
--image-model "IMAGE_MODEL" \
--auto-image \
--api-key "$PROVIDER_API_KEY"Run it normally:
codex-universal-proxy run multimodalWith --auto-image, images in the current user turn or its tool outputs are routed to the image model.
Use the same model for both when the provider has one multimodal model:
codex-universal-proxy preset add multimodal \
--url "https://provider.example/v1" \
--text-model "MODEL" \
--image-model "MODEL" \
--auto-image \
--api-key "$PROVIDER_API_KEY"Set persist_inline_images = true in proxy-models.toml to cache inline images
under ~/.codex/attachments and replace historical pixels with path references.
Generated images are stored in the same session cache instead of temporary
storage, so their saved paths remain usable across follow-up turns.
Persistence requires a stable session, thread, conversation, or prompt-cache
identifier; requests without one retain their inline images. Session caches
unused for 30 days are removed lazily by default. Configure
inline_image_retention_days, or set it to 0 to retain caches indefinitely.
The same settings can be changed without editing TOML directly:
codex-universal-proxy route --persist-images --image-retention-days 30Image generation is configured separately and applies across provider presets.
codex-universal-proxy imagine \
--enable \
--service gemini \
--model "gemini-2.5-flash-image" \
--api-key "$GEMINI_API_KEY"codex-universal-proxy imagine \
--enable \
--service openai \
--model "gpt-image-2" \
--api-key "$OPENAI_API_KEY"codex-universal-proxy imagine \
--enable \
--service ollama \
--model "x/z-image-turbo" \
--base-url "http://127.0.0.1:11434"Check the image-generation configuration:
codex-universal-proxy imagine --doctorThe proxy uses Codex's existing generate_image tool. It does not inspect ordinary prompts and automatically turn them into image requests.
Presets can also save proxy compatibility options:
codex-universal-proxy preset add tuned \
--url "https://provider.example/v1" \
--text-model "MODEL" \
--dedupe-large-input \
--dedupe-min-chars 1024 \
--verbose-tools \
--enable-find-skill \
--no-stream-loopAvailable preset toggles include:
--auto-image / --no-auto-image
--dedupe-large-input / --no-dedupe-large-input
--dedupe-min-chars N
--verbose-tools / --no-verbose-tools
--log-upstream-body / --no-log-upstream-body
--enable-find-skill / --no-enable-find-skill
--stream-loop / --no-stream-loop
Runtime options such as --foreground remain on the run or serve command rather than being stored in the preset.
Codex can send plugins and MCP tools using OpenAI-specific namespace, dynamic-tool, managed-tool, and freeform-tool formats.
Many custom providers reject these formats or fail with problems such as:
unsupported call
MCP tools are visible but never invoked
tool_search aborts
namespace tools are rejected
apply_patch uses the wrong format
The proxy translates these tools into ordinary provider-callable functions and restores the original Codex format when calls are returned.
A Codex tool such as:
mcp__storefront_builder.list_storefront_build_sessions
can be exposed to the model as:
mcp__storefront_builder__list_storefront_build_sessions
The returned call is translated back into the namespace and tool name expected by Codex.
When 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.
Deferred tools discovered by tool_search are also made callable on the following request.
Codex 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.
- Ollama-compatible Responses API servers
- OpenRouter models with compatible API behavior
- Anthropic through its OpenAI-compatible Chat Completions API
- OpenAI through its native Responses API
- Custom providers exposing
POST /v1/responses - Chat Completions providers through the built-in adaptor
- Local Responses API shims
Image generation can independently use Gemini, OpenAI, or Ollama.
codex-universal-proxy status
codex-universal-proxy upstream --status
codex-universal-proxy logs --tail 100
codex-universal-proxy restart
codex-universal-proxy run PRESET_NAME
codex-universal-proxy run PRESET_NAME --foreground
codex-universal-proxy switch openaiGive Codex this skill URL:
https://raw.githubusercontent.com/bharat2808/codex-universal-proxy/main/skills/codex-universal-proxy/SKILL.md
Then ask Codex:
Install this skill and use it to set up codex-universal-proxy.
Runtime configuration and logs are stored under:
~/.codex/codex-universal-proxy/proxy-models.toml
~/.codex/codex-universal-proxy/imagine.toml
~/.codex/codex-universal-proxy/proxy.log
Debug logging is disabled by default:
verbose_tools = false
log_upstream_body = falseBe careful when enabling request-body logging because it may include prompts, tool arguments, or other sensitive data.
- This package is not affiliated with OpenAI.
- Codex internal tool schemas may change.
- Compatibility depends on the selected provider and model.
- Models must support reliable tool calling for plugins and MCP tools to work well.
- Some providers expose only Chat Completions and require the adaptor.
- Web search falls back from Ollama cloud search, to local Ollama search, to DuckDuckGo HTML search.
npm install -g \
https://registry.npmjs.org/codex-universal-proxy/-/codex-universal-proxy-0.5.0.tgzcodex-universal-proxy switch openai
codex-universal-proxy uninstall
npm uninstall -g codex-universal-proxy