OpenCodex Configuration
OpenCodex is a Codex fork/proxy that routes requests to multiple AI providers. It runs a local proxy and uses a JSON model catalog to define available models.
Key File Locations (Windows)
| File | Purpose |
|---|---|
~/.codex/opencodex-catalog.json |
Model catalog — defines all selectable models |
~/.codex/opencodex.config.toml |
Proxy config (base URL, catalog path, features) |
~/.codex/opencodex-journal.json |
Internal journal |
~/.opencodex/opencodex-service-task.xml |
Windows service definition |
~/.opencodex/opencodex-service.cmd |
Service start script |
Model Catalog Structure
The catalog is a JSON file with a top-level "models" array. Each entry defines one selectable model.
Required Fields for a Model Entry
{
"slug": "provider/model-name",
"display_name": "provider/model-name",
"description": "Routed via opencodex → provider (provider).",
"default_reasoning_level": "medium",
"supported_reasoning_levels": [
{"effort": "low", "description": "Fast responses with lighter reasoning"},
{"effort": "medium", "description": "Balances speed and reasoning depth for everyday tasks"},
{"effort": "high", "description": "Greater reasoning depth for complex problems"},
{"effort": "xhigh", "description": "Extra high reasoning depth for complex problems"},
{"effort": "max", "description": "Maximum reasoning depth for the hardest problems"},
{"effort": "ultra", "description": "Maximum reasoning with automatic task delegation"}
],
"shell_type": "shell_command",
"visibility": "list",
"supported_in_api": true,
"priority": 5,
"upgrade": null,
"base_instructions": "You are a coding agent powered by the MODEL_NAME model. Do not claim to be GPT-5 or made by OpenAI.",
"supports_reasoning_summaries": true,
"default_reasoning_summary": "none",
"support_verbosity": true,
"default_verbosity": "low",
"apply_patch_tool_type": "freeform",
"web_search_tool_type": "text_and_image",
"truncation_policy": {"mode": "tokens", "limit": 10000},
"supports_parallel_tool_calls": true,
"supports_image_detail_original": true,
"context_window": 272000,
"max_context_window": 272000,
"effective_context_window_percent": 95,
"experimental_supported_tools": [],
"input_modalities": ["text", "image"],
"supports_search_tool": true,
"comp_hash": "opencodex",
"auto_compact_token_limit": 244800
}
Critical Fields
| Field | Values | Effect |
|---|---|---|
visibility |
"list" |
Model appears in selector UI |
visibility |
"hide" |
Model exists but is hidden from selector |
slug |
provider/model-name |
Unique identifier, used for routing |
priority |
5 (third-party), 103 (OpenAI native) |
Sort order in UI |
Adding a New Model (via Management API — REQUIRED)
⚠️ DO NOT edit opencodex-catalog.json directly. OpenCodex regenerates/overwrites the catalog file at runtime — manual edits are silently lost. Use the management API instead.
The management API runs on the same port as the proxy (default 127.0.0.1:10100).
Add a custom model
curl -s -X POST http://127.0.0.1:10100/api/custom-models \
-H "Content-Type: application/json" \
-d '{"provider":"alibaba","modelId":"qwen3.8","displayName":"qwen3.8","contextWindow":272000,"inputModalities":["text","image"]}'
providerandmodelIdare required; the routing slug becomesprovider/modelId.displayNamemust NOT contain/— use just the model name (e.g."qwen3.8", not"alibaba/qwen3.8").- Returns
{"id":"<uuid>","provider":"...","modelId":"...",...}on success. - No restart needed — the model appears in
/v1/modelsand the UI immediately.
Verify
curl -s http://127.0.0.1:10100/v1/models | python -c "import sys,json; d=json.load(sys.stdin); print([m['id'] for m in d['data'] if 'qwen3.8' in m['id']])"
Management API endpoints
| Method | Path | Purpose |
|---|---|---|
| GET | /api/models |
All models (routed + custom + native) with disabled state |
| GET | /api/custom-models |
List custom-added models |
| POST | /api/custom-models |
Add a custom model (see above) |
| PUT | /api/custom-models/:id |
Update displayName/contextWindow/modelId |
| DELETE | /api/custom-models/:id |
Remove a custom model |
| PUT | /api/disabled-models |
Enable/disable models (body: {"models":["slug1","slug2"]}) |
| GET | /api/selected-models |
Current selection + available models |
Pitfalls
- NEVER edit
opencodex-catalog.jsonto add models. OpenCodex overwrites it at runtime. UsePOST /api/custom-modelsinstead. The catalog is useful as read-only reference for understanding routing. displayNamein the custom-models API must NOT contain/— pass just the model name, not the full slug.- The
slugformat isprovider/model-name— this is how OpenCodex routes to the correct backend. - The
opencodeCLI (opencode.ai) is a DIFFERENT tool from OpenCodex. Don't confuse them. OpenCode config is at~/.config/opencode/opencode.jsonc. - OpenCodex source lives at
~/AppData/Roaming/npm/node_modules/@bitkyc08/opencodex/— checksrc/server/management/model-routes.tsfor API details if endpoints change.
Proxy Config (opencodex.config.toml)
openai_base_url = "http://127.0.0.1:10100/v1"
model_catalog_json = "C:\\Users\\<user>\\.codex\\opencodex-catalog.json"
[features]
fast_mode = true
Verification
After adding a model via the API:
curl -s http://127.0.0.1:10100/v1/models— confirm the new slug appears in the list.- No restart needed — the model is immediately available in the UI model selector.
- If the model doesn't appear, check
GET /api/custom-modelsto confirm it was saved, andGET /api/disabled-modelsto ensure it isn't disabled.