|
| 1 | +# Codex App Model Catalog Integration |
| 2 | + |
| 3 | +Date: 2026-06-20 |
| 4 | + |
| 5 | +This document records why opencodex routed models can appear in Codex App's model picker without |
| 6 | +patching Codex App itself. |
| 7 | + |
| 8 | +## Summary |
| 9 | + |
| 10 | +Codex CLI, TUI, and App share the Codex home configuration surface. opencodex integrates by writing |
| 11 | +Codex-native config and catalog files under the resolved `CODEX_HOME`: |
| 12 | + |
| 13 | +- `$CODEX_HOME/config.toml` |
| 14 | +- `$CODEX_HOME/opencodex.config.toml` |
| 15 | +- `$CODEX_HOME/opencodex-catalog.json` |
| 16 | +- `$CODEX_HOME/models_cache.json` |
| 17 | + |
| 18 | +When Codex App reads the same config/catalog state, routed opencodex models are visible because they |
| 19 | +look like valid Codex catalog entries. |
| 20 | + |
| 21 | +## Required config shape |
| 22 | + |
| 23 | +The global provider must be a root TOML key: |
| 24 | + |
| 25 | +```toml |
| 26 | +model_provider = "opencodex" |
| 27 | +``` |
| 28 | + |
| 29 | +It must not be appended under whichever TOML table happened to be last. TOML root keys after a table |
| 30 | +header become part of that table, which makes Codex ignore the provider as a global setting. |
| 31 | + |
| 32 | +The custom model catalog path must also be a root TOML key: |
| 33 | + |
| 34 | +```toml |
| 35 | +model_catalog_json = "/absolute/path/to/opencodex-catalog.json" |
| 36 | +``` |
| 37 | + |
| 38 | +The provider block must advertise a Responses-compatible provider: |
| 39 | + |
| 40 | +```toml |
| 41 | +[model_providers.opencodex] |
| 42 | +name = "OpenCodex Proxy" |
| 43 | +base_url = "http://localhost:10100/v1" |
| 44 | +wire_api = "responses" |
| 45 | +requires_openai_auth = true |
| 46 | +``` |
| 47 | + |
| 48 | +`requires_openai_auth = true` is important for Codex App/TUI account-gated behavior. Codex derives |
| 49 | +ChatGPT-account capability from the active provider; without this flag, fast-related UI can stay |
| 50 | +hidden even when the user has ChatGPT auth. |
| 51 | + |
| 52 | +## Catalog entry shape |
| 53 | + |
| 54 | +opencodex does not generate minimal JSON entries. It clones a native Codex model catalog entry and |
| 55 | +then changes the routed fields: |
| 56 | + |
| 57 | +```text |
| 58 | +slug = "<provider>/<model>" |
| 59 | +display_name = "<provider>/<model>" |
| 60 | +description = "Routed via opencodex -> <provider> ..." |
| 61 | +priority = <picker priority> |
| 62 | +visibility = "list" |
| 63 | +``` |
| 64 | + |
| 65 | +Cloning a native entry preserves fields Codex's strict parser expects, including: |
| 66 | + |
| 67 | +- `base_instructions` |
| 68 | +- `supported_reasoning_levels` |
| 69 | +- `default_reasoning_level` |
| 70 | +- `shell_type` |
| 71 | +- `supported_in_api` |
| 72 | + |
| 73 | +This is why routed entries can behave like normal picker-visible Codex models. |
| 74 | + |
| 75 | +## Fast tier handling |
| 76 | + |
| 77 | +Codex uses a split between config spelling and runtime/catalog spelling: |
| 78 | + |
| 79 | +| Surface | Value | |
| 80 | +|---|---| |
| 81 | +| `config.toml` persistence | `service_tier = "fast"` | |
| 82 | +| catalog/request tier id | `priority` | |
| 83 | +| feature gate | `[features].fast_mode = true` | |
| 84 | +| provider/account gate | `requires_openai_auth = true` | |
| 85 | + |
| 86 | +Native OpenAI passthrough models can keep fast metadata. Routed non-OpenAI models must not inherit |
| 87 | +that metadata from the native template: |
| 88 | + |
| 89 | +```text |
| 90 | +delete additional_speed_tiers |
| 91 | +delete service_tier |
| 92 | +delete service_tiers |
| 93 | +delete default_service_tier |
| 94 | +``` |
| 95 | + |
| 96 | +This prevents fast from appearing for providers where Codex/OpenAI priority processing is not a valid |
| 97 | +request option. |
| 98 | + |
| 99 | +## Cache invalidation |
| 100 | + |
| 101 | +Codex caches models in: |
| 102 | + |
| 103 | +```text |
| 104 | +$CODEX_HOME/models_cache.json |
| 105 | +``` |
| 106 | + |
| 107 | +After changing providers, hidden models, featured models, or service-tier metadata, opencodex should |
| 108 | +delete that cache so the next Codex process or model refresh sees the updated catalog. |
| 109 | + |
| 110 | +## Verification |
| 111 | + |
| 112 | +Useful probes: |
| 113 | + |
| 114 | +```bash |
| 115 | +codex doctor --json |
| 116 | +codex debug models |
| 117 | +ocx sync |
| 118 | +ocx status |
| 119 | +``` |
| 120 | + |
| 121 | +Expected high-level result: |
| 122 | + |
| 123 | +- active model provider is `opencodex` |
| 124 | +- provider uses ChatGPT auth reachability semantics |
| 125 | +- native `gpt-*` entries keep fast support |
| 126 | +- routed `<provider>/<model>` entries are `visibility = "list"` |
| 127 | +- routed entries have no fast/service-tier metadata |
0 commit comments