---
title: "OpenCode"
description: "Add an OpenAI-compatible pirouter provider to opencode.json with the base URL https://api.pirouter.ai/v1, and OpenCode runs Claude, GPT and Gemini through pirouter, tool calls included."
canonical: "https://pirouter.ai/docs/integrations/opencode"
last-updated: "2026-10-18"
lang: "en"
source: "content/docs/en/integrations/opencode.mdx"
---

# OpenCode

Add an OpenAI-compatible pirouter provider to opencode.json with the base URL https://api.pirouter.ai/v1, and OpenCode runs Claude, GPT and Gemini through pirouter, tool calls included.

[OpenCode](https://github.com/anomalyco/opencode) connects to pirouter as a custom provider: add a `pirouter` provider to `opencode.json` that uses the OpenAI-compatible protocol, with the base URL `https://api.pirouter.ai/v1`. Claude, GPT and Gemini all accept the OpenAI protocol, so one provider covers models from all three.

## Prerequisites

- A pirouter API key. If you do not have one, create it with the [quickstart](https://pirouter.ai/docs/quickstart.md) and store it in an environment variable:

```bash
export PIROUTER_API_KEY="sk-pi-..."
```

- OpenCode installed. This page was verified with OpenCode 1.18; run `opencode --version` to check yours.

## Configure

Save the following as `~/.config/opencode/opencode.json`. To use it in one project only, save it as `opencode.json` in the project root instead.

`~/.config/opencode/opencode.json`:

```json
{
  "$schema": "https://opencode.ai/config.json",
  "model": "pirouter/anthropic/claude-sonnet-5.5",
  "small_model": "pirouter/anthropic/claude-haiku-5.5",
  "provider": {
    "pirouter": {
      "npm": "@ai-sdk/openai-compatible",
      "name": "pirouter",
      "options": {
        "baseURL": "https://api.pirouter.ai/v1",
        "apiKey": "{env:PIROUTER_API_KEY}"
      },
      "models": {
        "anthropic/claude-sonnet-5.5": {
          "name": "Claude Sonnet 5.5",
          "limit": { "context": 1000000, "output": 128000 }
        },
        "anthropic/claude-haiku-5.5": {
          "name": "Claude Haiku 5.5",
          "limit": { "context": 1000000, "output": 128000 }
        },
        "openai/gpt-6.1-sol": {
          "name": "GPT-6.1 Sol",
          "limit": { "context": 1050000, "output": 128000 }
        },
        "google/gemini-4-argon": {
          "name": "Gemini 4 Argon",
          "limit": { "context": 1048576, "output": 65536 }
        }
      }
    }
  }
}
```

What each part does:

- `npm` is `@ai-sdk/openai-compatible`, so requests go to `POST /v1/chat/completions`. `baseURL` must end in `/v1`.
- `apiKey` is `{env:PIROUTER_API_KEY}`: OpenCode reads the key from the environment at startup, and the file never holds it in plain text.
- `models` must be listed by hand. OpenCode does not fetch the gateway's model list, so a model you leave out cannot be picked in OpenCode. For the models you can use, see the OpenAI column of the protocol table in [Models & protocols](https://pirouter.ai/docs/models.md#which-protocols-each-model-accepts), and leave image models out.
- Every model gets a `limit`: `context` is the context window and `output` the output cap, matching what `GET https://api.pirouter.ai/v1/models` returns.
- `small_model` is Claude Haiku 5.5. Each new OpenCode session sends one extra request to write the session title. That request uses `small_model`, or your main model if `small_model` is not set.

In OpenCode, a model name is `pirouter/` followed by the full pirouter model ID, such as `pirouter/anthropic/claude-sonnet-5.5`. Pass it with `-m` on the command line, or set it as `model` in the config.

Tool calls work with all three vendors: Gemini 4 Argon also calls OpenCode's file-reading tool over the OpenAI protocol.

## Verify

In a terminal where `PIROUTER_API_KEY` is set, run:

```bash
opencode run -m pirouter/anthropic/claude-sonnet-5.5 "Reply with the single word: ok"
```

You should see the line `> build · anthropic/claude-sonnet-5.5`, followed by the model's reply, `ok`.

The request shows up in the console's [Logs](https://pirouter.ai/docs/guides/logs.md) with `/v1/chat/completions` under **Endpoint**. Next to it is a request for `anthropic/claude-haiku-5.5`: that is OpenCode writing the session title.

## Troubleshooting

### 401 invalid\_api\_key

A `401` with the error code `invalid_api_key` usually means `PIROUTER_API_KEY` is not set in the terminal that runs OpenCode. When the variable does not exist, `{env:PIROUTER_API_KEY}` becomes an empty string and the request carries no key. Check with `echo $PIROUTER_API_KEY`, then run again.

### 401 with `@ai-sdk/google`

Do not switch `npm` to `@ai-sdk/google`. That package sends the key only in the `x-goog-api-key` header, which the gateway does not read (it reads `Authorization` and `x-api-key`), so requests return `401`. Keep Gemini models in the OpenAI-compatible provider above.

### Every request carries `max_tokens: 32000`

When a model has no `limit.output`, OpenCode sends `max_tokens: 32000` on every request. Without `limit.context`, long sessions are never compacted automatically. Give every model a `limit`, using the context window and output cap from `GET https://api.pirouter.ai/v1/models`.

### An extra flagship charge on every new session

Each new OpenCode session sends one extra request to write its title. Without `small_model`, that request uses your main model, which shows up in [Logs](https://pirouter.ai/docs/guides/logs.md) as one more main-model request per session. Set `small_model` to a cheaper model such as `pirouter/anthropic/claude-haiku-5.5`.

## Related links

- [OpenCode](https://github.com/anomalyco/opencode) on GitHub
- [Providers](https://opencode.ai/docs/providers/): how OpenCode configures custom providers
- [Config](https://opencode.ai/docs/config/): where config files live and how variables are substituted
- [CLI](https://opencode.ai/docs/cli/): the options of `opencode run`
