# OpenCode

> Connect OpenCode to MirAPI by adding a custom @ai-sdk/openai-compatible provider to opencode.json and selecting deepseek-chat per session.

OpenCode is an open-source terminal coding agent — also available as a desktop app and IDE extensions — driven by `opencode.json`. Register MirAPI once as a provider and you can pick any MirAPI model per session, paying from your existing prepaid balance.

## What you need

| Element | Value |
|---|---|
| Base URL | `https://api.mirapi.ai/v1` |
| API key | Your MirAPI key, referenced as `{env:MIRAPI_API_KEY}` |
| Model | `deepseek-chat` under provider `mirapi` |
| Protocol | OpenAI-compatible (`/v1`) |

If you do not have a key yet, create one in the console at https://console.mirapi.ai. The key is shown only once, so copy it immediately.

:::note
Keep `/v1` in the base URL. OpenCode appends the request path (for example `/chat/completions`) itself.
:::

## Configure

1. Install OpenCode if it is not already installed:

```bash
curl -fsSL https://opencode.ai/install | bash
```

Other installers include `npm install -g opencode-ai` and `brew install anomalyco/tap/opencode`.

2. Add a provider block to `opencode.json` at your project root (or `~/.config/opencode/opencode.json` for user-wide settings; JSONC is accepted):

```json
{
  "provider": {
    "mirapi": {
      "npm": "@ai-sdk/openai-compatible",
      "name": "MirAPI",
      "options": {
        "baseURL": "https://api.mirapi.ai/v1",
        "apiKey": "{env:MIRAPI_API_KEY}"
      },
      "models": {
        "deepseek-chat": {
          "name": "DeepSeek Chat"
        }
      }
    }
  }
}
```

3. Export the key in your shell:

```bash
export MIRAPI_API_KEY=sk-...
```

### Set a default model

To skip the model picker on startup, add a top-level `model` key. OpenCode composes ids as `provider_id/model_id`, so a MirAPI model is prefixed with `mirapi/`:

```json
{
  "model": "mirapi/deepseek-chat"
}
```

You can still override it per invocation with `--model`.

## Verify with a message

```bash
opencode run "Reply with exactly: connected to MirAPI" --model mirapi/deepseek-chat
```

The reply should contain `connected to MirAPI`. In an interactive session, run `/models` and select `mirapi/deepseek-chat`.

## How it works

OpenCode runs custom providers on the Vercel AI SDK. `@ai-sdk/openai-compatible` speaks the OpenAI Chat Completions protocol, so MirAPI receives `POST /v1/chat/completions` at `https://api.mirapi.ai/v1`. Responses stream as standard SSE (`data:` lines, ending with `data: [DONE]`), which the AI SDK parses for you.

### Protocol variants

MirAPI serves the same models over three protocols. The provider above is OpenAI-compatible; if you prefer another SDK's behaviour, point the AI SDK's `@ai-sdk/anthropic` provider at `https://api.mirapi.ai` (auth `x-api-key`) or `@ai-sdk/google` at `https://api.mirapi.ai` (auth `x-goog-api-key`). Whether a given model is available on a given protocol depends on its capability flags in the catalogue.

## Errors and billing

| Status | Meaning | What to do |
|---|---|---|
| 401 | Key missing, invalid, or unknown | Check `{env:MIRAPI_API_KEY}` and the exported variable |
| 403 | Key valid but rejected — balance exhausted, model not whitelisted, quota reached, or IP not allowed | Resolve the cause, then retry |
| 413 | Request too large | Reduce the payload |
| 429 | Rate limited (no `Retry-After` header) | Retry with exponential backoff |
| 500 | Server error | Idempotent requests can be retried safely |

Every error message ends with a request ID — include it in any support ticket.

Chat usage bills per token: input, output, and cache read, per 1M tokens. Reasoning tokens bill as output. Prompt caching is automatic on OpenAI-compatible models; confirm hits via `usage.prompt_tokens_details.cached_tokens`. The balance is prepaid USD and never expires — when it runs out you get 403, and the same key resumes immediately after a top-up. Reconcile spending in the console billing log or via `GET /api/usage/token` (summary) and `GET /api/log/token` (per-request detail).

## Tool-specific pitfalls

- **`@ai-sdk/openai-compatible` is the right npm package** for OpenAI-compatible gateways; the plain `openai` package also works but keeps the SDK's default behaviours.
- **The model list is manual.** OpenCode does not auto-discover MirAPI models; add each one you want by its exact `GET /v1/models` name. The `vendor/` prefix is console-only and never part of the request name.
- **The provider prefix is `mirapi/`** — `mirapi/deepseek-chat` means the `deepseek-chat` model under the `mirapi` provider, not a model namespace.
- **403 with a valid key** usually means the model is not whitelisted for that key or the balance is exhausted. Top up or adjust the whitelist, then retry.
- **Auth errors** — check that `{env:MIRAPI_API_KEY}` matches the exported variable name exactly.
- **Config changes need a restart** — OpenCode reads `opencode.json` at startup, so restart it after editing the provider block.

## Related links

- [Quickstart](/docs/quickstart)
- [OpenAI compatibility](/docs/openai-compat)
- [Models](/docs/models)
- [Billing](/docs/billing)
- [Authentication](/docs/api-reference/authentication)
- [Integrations](/docs/integrations)