# OpenCode v1 on Codex Pooler

OpenCode is an open-source coding agent that brings project-aware assistance to your terminal. Connect it to Codex Pooler to use your Pool's models for code changes, questions and tool-driven tasks. This guide covers v1 and its optional OMO integration; the [OpenCode v2 guide](/clients/opencode-v2/) covers the newer configuration.

![Codex Pooler OpenCode integration](/codex-pooler-opencode.webp)

## Before you start

- Install [OpenCode v1](https://opencode.ai/docs/) and check `opencode --version`.
- Have a Codex Pooler URL reachable from the client.
- Create a [Pool API key](/getting-started/quick-start/) and choose a model available to that Pool.

<a id="provider-example"></a>

## Configure the connection

Keep the provider id as `openai` for this setup so OpenCode retains its OpenAI provider-family behavior.

Use the commands for the terminal that starts the client. Environment-variable assignments below apply to that terminal; desktop apps and services need the variables in their own launch environment.

### Config file paths

**Provider settings**

| OS | Default config file |
| --- | --- |
| macOS | `~/.config/opencode/opencode.jsonc` |
| Linux | `~/.config/opencode/opencode.jsonc` |
| Windows | `%USERPROFILE%\.config\opencode\opencode.jsonc` |

**OMO settings (optional)**

| OS | Default config file |
| --- | --- |
| macOS | `~/.config/opencode/oh-my-openagent.jsonc` |
| Linux | `~/.config/opencode/oh-my-openagent.jsonc` |
| Windows | `%USERPROFILE%\.config\opencode\oh-my-openagent.jsonc` |

If you set `XDG_CONFIG_HOME` or a client-specific config override, use that location instead.

These are the default locations. On Windows, paste the `%USERPROFILE%`, `%APPDATA%` or `%LOCALAPPDATA%` path into File Explorer's address bar. For a client installed inside WSL, use the Linux paths and commands inside WSL. Keep any custom configuration folder or profile you already use.

Merge the provider settings into `opencode.jsonc` at the path for your system. If you already use `opencode.json`, edit that file instead. Store the Pool API key outside the config and read it through environment expansion:

**macOS / Linux / WSL**

```bash
export CODEX_POOLER_API_KEY="<pool-api-key>"
```

**Windows PowerShell**

```powershell
$env:CODEX_POOLER_API_KEY = "<pool-api-key>"
```

```jsonc title="opencode.jsonc" frame="code"
{
  "$schema": "https://opencode.ai/config.json",
  "small_model": "openai/gpt-6-luna",
  "compaction": {
    "auto": true,
    "reserved": 41420
  },
  "provider": {
    "openai": {
      "npm": "@ai-sdk/openai",
      "name": "Codex Pooler",
      "options": {
        "baseURL": "https://codex-pooler.example.com/v1",
        "apiKey": "{env:CODEX_POOLER_API_KEY}"
      },
      "models": {
        "gpt-6-luna": {
          "id": "gpt-6-luna",
          "name": "GPT-6 Luna via Codex Pooler",
          "family": "gpt",
          "attachment": true,
          "reasoning": true,
          "tool_call": true,
          "temperature": false,
          "options": {
            "reasoningEffort": "high",
            "reasoningSummary": "auto",
            "textVerbosity": "medium",
            "include": ["reasoning.encrypted_content"],
            // Optional: priority processing may cost more than the default tier.
            // "serviceTier": "priority"
          },
          "modalities": {
            "input": ["text", "image"],
            "output": ["text"]
          },
          "limit": {
            "context": 828400,
            "input": 828400,
            "output": 64000
          }
        },
        "gpt-6-sol": {
          "id": "gpt-6-sol",
          "name": "GPT-6 Sol via Codex Pooler",
          "family": "gpt",
          "attachment": true,
          "reasoning": true,
          "tool_call": true,
          "temperature": false,
          "options": {
            "reasoningEffort": "high",
            "reasoningSummary": "auto",
            "textVerbosity": "medium",
            "include": ["reasoning.encrypted_content"],
            // Optional: priority processing may cost more than the default tier.
            // "serviceTier": "priority"
          },
          "modalities": {
            "input": ["text", "image"],
            "output": ["text"]
          },
          "limit": {
            "context": 828400,
            "input": 828400,
            "output": 64000
          }
        },
        "gpt-6-astra": {
          "id": "gpt-6-astra",
          "name": "GPT-6 Astra via Codex Pooler",
          "family": "gpt",
          "attachment": true,
          "reasoning": true,
          "tool_call": true,
          "temperature": false,
          "options": {
            "reasoningEffort": "high",
            "reasoningSummary": "auto",
            "textVerbosity": "medium",
            "include": ["reasoning.encrypted_content"],
            // Optional: priority processing may cost more than the default tier.
            // "serviceTier": "priority"
          },
          "modalities": {
            "input": ["text", "image"],
            "output": ["text"]
          },
          "limit": {
            "context": 828400,
            "input": 828400,
            "output": 64000
          }
        }
      }
    }
  }
}
```

Define only model ids your assigned Pool can serve. If you run Codex Pooler locally, set `baseURL` to `http://localhost:4000/v1`.

## Choose a model

Select an `openai/` model configured below the `openai` provider and available to your Pool.

OpenCode uses `small_model` for background helpers such as automatic session titles. Without an explicit override, it may infer a nano model that Codex Pools do not serve. Point `small_model` at a lightweight model assigned to your Pool. The setting remains effective when OMO is loaded.

Request-time OpenAI options belong under each model's `options` block. Keep only connection settings such as `baseURL` and `apiKey` in provider-level `options`. Use `serviceTier: "priority"` for priority processing. `fast` is an accepted equivalent request spelling, but `priority` is the canonical spelling for new configuration. Enable it only when your Pool and upstream offer it and you intentionally accept the potentially higher cost; leave it commented to use the default tier. This `/v1` route translates the request shape, while any projected provider `service_tier` response value keeps the provider's literal vocabulary.
Do not add `store`: Codex Pooler sets `store: false` on its upstream streaming request.

OpenCode subtracts its compaction reserve from `limit.input` before declaring the session full. The `828400` values above are long-profile examples for models whose selected Pool catalog source reports an 872000-token raw ceiling. Provider accounts can temporarily report different ceilings for the same model; a selected 272000-token profile exposes `258400` through `/v1/models` instead. Use each model's `/v1/models.context_length` as the authoritative value for `limit.context` and `limit.input`. With the long-profile example and `reserved: 41420`, OpenCode starts compaction at 786980 tokens. `limit.input` is the local pre-compaction boundary, not a simultaneous input-plus-output envelope. OpenCode caps request output at 32k by default; set `OPENCODE_EXPERIMENTAL_OUTPUT_TOKEN_MAX=64000` only when you want OpenCode to request the full 64k cap.

## Verify the connection

Start a new conversation with the configured model and send a short request. In Codex Pooler's request logs, match the request time, API key, model, and final status to your test. A reply alone does not confirm that the client used your Pooler instance.

If you automate OpenCode from scripts, use OpenCode's own documented headless command shape for your installed version and verify both the final response and the expected file changes. The examples on this page focus on configuration, not a full automation workflow.

## Advanced configuration

### Oh My OpenAgent (OMO) routing

If you use Oh My OpenAgent, keep the native `openai` provider configuration above and add model overrides in `oh-my-openagent.jsonc` in the same config folder. Keep the `openai/` prefix on every OMO model so delegated agents continue to use the same Codex Pooler provider.

This example assigns Luna to lightweight and background work, Sol to daily agent work, and Astra to planning and deep-reasoning roles. Each explicit fallback stays inside the model ids assigned to the Pool and preserves the primary reasoning variant.

```jsonc title="oh-my-openagent.jsonc" frame="code"
{
  "agents": {
    "sisyphus": {
      "model": "openai/gpt-6-sol",
      "variant": "high",
      "fallback_models": [{ "model": "openai/gpt-6-astra", "variant": "high" }]
    },
    "hephaestus": {
      "model": "openai/gpt-6-astra",
      "variant": "xhigh",
      "fallback_models": [{ "model": "openai/gpt-6-sol", "variant": "xhigh" }]
    },
    "oracle": {
      "model": "openai/gpt-6-astra",
      "variant": "high",
      "fallback_models": [{ "model": "openai/gpt-6-sol", "variant": "high" }]
    },
    "librarian": {
      "model": "openai/gpt-6-luna",
      "variant": "low",
      "fallback_models": [{ "model": "openai/gpt-6-sol", "variant": "low" }]
    },
    "explore": {
      "model": "openai/gpt-6-luna",
      "variant": "low",
      "fallback_models": [{ "model": "openai/gpt-6-sol", "variant": "low" }]
    },
    "multimodal-looker": {
      "model": "openai/gpt-6-sol",
      "variant": "medium",
      "fallback_models": [{ "model": "openai/gpt-6-astra", "variant": "medium" }]
    },
    "prometheus": {
      "model": "openai/gpt-6-astra",
      "variant": "high",
      "fallback_models": [{ "model": "openai/gpt-6-sol", "variant": "high" }]
    },
    "metis": {
      "model": "openai/gpt-6-astra",
      "variant": "high",
      "fallback_models": [{ "model": "openai/gpt-6-sol", "variant": "high" }]
    },
    "momus": {
      "model": "openai/gpt-6-astra",
      "variant": "xhigh",
      "fallback_models": [{ "model": "openai/gpt-6-sol", "variant": "xhigh" }]
    },
    "atlas": {
      "model": "openai/gpt-6-sol",
      "variant": "medium",
      "fallback_models": [{ "model": "openai/gpt-6-astra", "variant": "medium" }]
    },
    "sisyphus-junior": {
      "model": "openai/gpt-6-sol",
      "variant": "medium",
      "fallback_models": [{ "model": "openai/gpt-6-astra", "variant": "medium" }]
    }
  },
  "categories": {
    "visual-engineering": {
      "model": "openai/gpt-6-sol",
      "variant": "high",
      "fallback_models": [{ "model": "openai/gpt-6-astra", "variant": "high" }]
    },
    "ultrabrain": {
      "model": "openai/gpt-6-astra",
      "variant": "xhigh",
      "fallback_models": [{ "model": "openai/gpt-6-sol", "variant": "xhigh" }]
    },
    "deep": {
      "model": "openai/gpt-6-astra",
      "variant": "medium",
      "fallback_models": [{ "model": "openai/gpt-6-sol", "variant": "medium" }]
    },
    "artistry": {
      "model": "openai/gpt-6-astra",
      "variant": "xhigh",
      "fallback_models": [{ "model": "openai/gpt-6-sol", "variant": "xhigh" }]
    },
    "quick": {
      "model": "openai/gpt-6-luna",
      "variant": "low",
      "fallback_models": [{ "model": "openai/gpt-6-sol", "variant": "low" }]
    },
    "unspecified-low": {
      "model": "openai/gpt-6-luna",
      "variant": "low",
      "fallback_models": [{ "model": "openai/gpt-6-sol", "variant": "low" }]
    },
    "unspecified-high": {
      "model": "openai/gpt-6-sol",
      "variant": "high",
      "fallback_models": [{ "model": "openai/gpt-6-astra", "variant": "high" }]
    },
    "writing": {
      "model": "openai/gpt-6-sol",
      "variant": "medium",
      "fallback_models": [{ "model": "openai/gpt-6-astra", "variant": "medium" }]
    }
  }
}
```

OMO tries configured `fallback_models` before its built-in model chains. Define only model ids your assigned Pool can serve; if one tier is unavailable, replace it in both primary and fallback entries instead of leaving an unreachable model in the routing map.

Validate the OMO configuration after editing the routing map:

```bash
bunx oh-my-openagent doctor --platform=opencode --json
```

The doctor validates plugin loading, schema, and model resolution, but it does not prove that an upstream can serve the selected model. Send one bounded request through the installed OpenCode headless workflow for every model tier assigned to OMO before relying on the routing map.

<a id="remote-mcp-example"></a>

## Operator MCP (optional)

Add Codex Pooler as a remote MCP server only when the OpenCode host should inspect metadata that the operator can already see in the admin UI.

```jsonc title="opencode.jsonc" frame="code"
{
  "mcp": {
    "codex_pooler": {
      "type": "remote",
      "url": "https://codex-pooler.example.com/mcp",
      "oauth": false,
      "headers": {
        "Authorization": "Bearer <operator-mcp-token>"
      },
      "enabled": true,
      "timeout": 30000
    }
  }
}
```

Use a dedicated operator MCP token for hosts that persist remote MCP headers. Don't use a Pool API key for `/mcp`.

## Compatibility notes

Codex Pooler provides narrow OpenAI-compatible `/v1` support for selected SDK routes. Supported OpenCode traffic should stay on `/v1/responses` or `/v1/chat/completions`, depending on the OpenAI provider path OpenCode uses.

`GET /v1/responses` is narrow Responses websocket compatibility, not `/v1/realtime` support. `/v1/realtime` and OpenAI Realtime SDK websocket or session routes are unsupported.

Continuity headers such as `session-id`, `x-session-id`, and `x-session-affinity` are local routing inputs only and are not forwarded upstream.

Unsupported `/v1` routes return deterministic OpenAI-shaped unsupported endpoint errors when explicitly routed. Don't treat Codex Pooler as full OpenAI API parity.