# Coding agents

Point a coding agent at RouterPlus to run it on any catalog model, billed to one balance. Each tool below has the same parts: requirements, setup steps, a config snippet and its limits through the gateway.

Tools: [Claude Code](#claude-code), [Codex](#codex), [Cursor](#cursor), [Cline](#cline), [Kilo Code](#kilo-code), [OpenCode](#opencode), [Hermes Agent](#hermes-agent) and [other tools](#other-tools).

- Apps built with Replit, Lovable, Bolt or v0 have [their own page](/docs/app-builders).
- The [Playground](#playground) needs no setup.
- A coding agent can follow the [installation runbook](#the-installation-runbook) at the end of this page.
- To build the gateway into a product, give your agent the [Agent integration guide](agent-integration.md).

Every docs page is served twice: `/docs/<slug>` rendered for people, and `/docs/<slug>.md` as raw markdown for agents. The machine index is [https://demo.routerplus.com/llms.txt](https://demo.routerplus.com/llms.txt).

## Before you start

1. **Get a key.** Open [Sign up](https://demo.routerplus.com/signup), complete Clerk authentication and email verification, and save the first key shown after sign-in. Buy credits in [Billing](https://demo.routerplus.com/console/billing). Signup does not add credit.
   - An invitation link from RouterPlus (for example, at a hackathon) adds its credit and makes the account count as paid, with higher limits.
   - To create more keys, open Access > API keys in the console ([API keys](https://demo.routerplus.com/console/keys)). A key looks like `tm_vk_...`. Give each tool its own key.
2. **Pick the base URL.** Tools that speak OpenAI's format use `https://demo-api.routerplus.com/v1`. Tools that speak Anthropic's format (Claude Code) use `https://demo-api.routerplus.com`, without `/v1`.
3. **Pick a model.** These ids work in every tool. In Cursor, use the name in the second column. The live list, with every price, is [https://demo.routerplus.com/api/models.json](https://demo.routerplus.com/api/models.json).

   | Model id | Name in Cursor | Context | Max output | Input /1M | Cached /1M | Cache write /1M | Output /1M |
   |---|---|---|---|---|---|---|---|
   | `claude-opus-5-5` | `rp-opus-5-5` | 1,000,000 | 128,000 | $4 | $0.20 | $5 | $20 |
   | `claude-fable-5-1` | `rp-fable-5-1` | 1,000,000 | 128,000 | $10 | $0.25 | $12.50 | $50 |
   | `claude-sonnet-5-5` | `rp-sonnet-5-5` | 1,000,000 | 128,000 | $2 | $0.10 | $2.50 | $10 |
   | `claude-haiku-5-5` | `rp-haiku-5-5` | 1,000,000 | 128,000 | $0.10 | $0.01 | $0.125 | $0.50 |
   | `gpt-6-astra` | `gpt-6-astra` | 1,050,000 | 128,000 | $10 | $1 | $12.50 | $50 |
   | `gpt-6.1-sol` | `gpt-6.1-sol` | 1,050,000 | 128,000 | $2 | $0.10 | $2.50 | $10 |
   | `gpt-6-luna` | `gpt-6-luna` | 1,050,000 | 128,000 | $0.10 | $0.01 | $0.125 | $0.50 |
   | `gpt-5.6-terra` | `gpt-5.6-terra` | 1,050,000 | 128,000 | $2 | $0.20 | $2.50 | $12 |
   | `gpt-6-sol` | `gpt-6-sol` | 1,050,000 | 128,000 | $2 | $0.20 | $2.50 | $10 |
   | `gpt-5.6-sol` | `gpt-5.6-sol` | 1,050,000 | 128,000 | $4 | $0.40 | $5 | $20 |
   | `gpt-5.6-luna` | `gpt-5.6-luna` | 1,050,000 | 128,000 | $0.20 | $0.02 | $0.25 | $1.20 |

   The other chat models in the catalog work too: `claude-sonnet-5`, `claude-opus-5`, `claude-fable-5`, `claude-sonnet-4-5` and `claude-haiku-4-5` (in Cursor `rp-sonnet-5`, `rp-opus-5`, `rp-fable-5`, `rp-sonnet-4-5` and `rp-haiku-4-5`), and `gpt-4o`, `gpt-4o-mini` and `gpt-4.1-mini`.

### What the gateway does for coding agents

- **Full-length answers.** When an agent sends no output limit, the model gets its own maximum: 128,000 tokens on the models above, fitted to the context window on the chat surfaces. The [hold](#your-balance-and-the-hold) counts at most 32,768 of them.
- **Prompt caching on Claude.** When a conversation carries no cache marks, the gateway turns on Claude's [automatic caching](/docs/compat#automatic-caching-on-claude). The `x-tm-auto-cache` response header says whether it did.
- **Screenshots and PDFs.** Images and PDFs reach Claude from tools that speak OpenAI's format, and reach GPT models from tools that speak Anthropic's format.
- **Compaction.** A prompt longer than the model's window gets the standard error that agents compact on: `context_length_exceeded` on the OpenAI format, `prompt is too long` on the Anthropic format.
- **The provider's own words.** An error carries the provider's message, so an agent can see what the model refused. A 502 or 504 is the exception: it is Cloudflare's own short error page, without the message or `x-request-id` (see [Errors](/docs/errors)). Agents retry it by themselves.
- **Default sampling only.** The Claude 5, GPT-6 and GPT-5.6 models take only their default sampling. When a tool sends another `temperature`, or a `top_p` or `top_k`, the gateway drops it and names it in `x-tm-dropped-params`. The request does not fail.
- **Cancels.** When you stop an answer (Esc, Stop), you pay for the input and the output already streamed. You never pay the full hold.
- **Hidden thinking.** The Claude 5 models do not show their thinking. Nothing reaches the tool until the first word or tool call, so a hard turn can look stuck for a minute or more.

### Your balance and the hold

While a request runs, the gateway holds balance for the input plus the output limit. A limit that the tool sends is held in full. With no limit, the hold counts 32,768 output tokens. Agents often run several requests at once. The output part of the hold per request:

| Model | Hold for 32,768 output tokens |
|---|---|
| Claude Fable 5.1, GPT-6 Astra | $1.64 |
| Claude Opus 5.5, GPT-5.6 Sol | $0.66 |
| GPT-5.6 Terra | $0.39 |
| Claude Sonnet 5.5, GPT-6.1 Sol, GPT-6 Sol | $0.33 |
| GPT-5.6 Luna | $0.04 |
| Claude Haiku 5.5, GPT-6 Luna | $0.02 |

> [!WARNING]
> You pay for what a request used, so a long answer can cost more than its hold. A small
> balance can refuse a request (`insufficient_quota`) before it starts. Then pick a
> cheaper model, or keep the tool's output limit small (each tool's section shows how).

### When you hit a rate limit

A request over one of your limits gets a 429, or a 503 when the gateway as a whole is full. Its `retry-after` header gives the seconds to wait, from 1 to 59:

- For a one-minute limit: the time until its window has room again.
- For a limit on requests at once: 10 seconds. The limit frees when one of your running requests ends.

Most coding agents wait and try again by themselves:

| Tool | What it does on a 429 |
|---|---|
| Claude Code | waits at least `retry-after` and tries again, up to 10 times (`CLAUDE_CODE_MAX_RETRIES`, at most 15) |
| Codex | waits `retry-after` and tries again, up to `stream_max_retries` times (5 by default), showing `Reconnecting... 1/5`. To wait longer, add `stream_max_retries = 10` to `[model_providers.routerplus]` |
| Cursor | does not try again. It shows the error, so send your message again after the wait |
| Cline | waits `retry-after` and tries again, up to 5 times, with no message while it waits. A turn can pause for up to a minute |
| Kilo Code, OpenCode | wait `retry-after` and try again, up to 5 times, showing the error with a countdown |

When the tries run out, the task stops with the error. Tell the agent to continue.

Out of credit (`insufficient_quota`) is also a 429. If your own requests in flight hold the balance, it frees as they end, and retries can wait it out. If not, add credits in [Billing](https://demo.routerplus.com/console/billing). Codex stops on it at once. Claude Code stops at once on a monthly spend cap, because that 429 says not to retry.

## Claude Code

Claude Code speaks Anthropic's format, which the gateway's `/v1/messages` surface accepts as sent. It works with Claude Code's default model (Claude Opus 5.5, sent as `claude-opus-5-5`) and with every Claude id in the catalog.

### Claude Code CLI

**Requirements:** the `claude` CLI and a `tm_vk_...` key.

**Setup:**

1. Put the gateway in your user settings, `~/.claude/settings.json`:

   ```json
   {
     "env": {
       "ANTHROPIC_BASE_URL": "https://demo-api.routerplus.com",
       "ANTHROPIC_AUTH_TOKEN": "tm_vk_..."
     }
   }
   ```

2. Run `claude`. There is no login screen. The first run shows the theme, the security notes and the folder trust question, then a session on Opus 5.5 with API usage billing.
3. At the folder trust question, choose **Yes, I trust this folder**. The default, **No, exit**, closes Claude Code.
4. Run `/status` to check the base URL and `ANTHROPIC_AUTH_TOKEN`.

Do not put the key in a project's `.claude/settings.json`: that file is committed, and its `env` block applies only after the first-run screens, so the login screen still appears.

For one shell only, export the same two values:

```bash
export ANTHROPIC_BASE_URL=https://demo-api.routerplus.com
export ANTHROPIC_AUTH_TOKEN=$TM_API_KEY
claude
```

> [!WARNING]
> Use `ANTHROPIC_AUTH_TOKEN`, not `ANTHROPIC_API_KEY`. With `ANTHROPIC_API_KEY`, Claude
> Code asks once whether to use "a custom API key", and the default **No** opens the login
> screen. If that happened, choose the custom API key in `/config`. You do not need a
> claude.ai sign-in: `ANTHROPIC_AUTH_TOKEN` comes first. For headless or CI use, give
> Claude Code a fresh config directory:
> `CLAUDE_CONFIG_DIR=$(mktemp -d) ANTHROPIC_BASE_URL=https://demo-api.routerplus.com ANTHROPIC_AUTH_TOKEN=$TM_API_KEY claude -p "..."`

**How the gateway handles Claude Code:**

- `ANTHROPIC_AUTH_TOKEN` goes as `Authorization: Bearer …`, which the gateway accepts everywhere, as it does `x-api-key`.
- Query strings (`/v1/messages?beta=true`) pass through. The gateway routes on the path.
- **Dated** ids (`claude-haiku-4-5-20251001`) resolve to their model, and the original id goes to the provider (see [Models & catalog](/docs/models)). An unknown id gets a `404` that names it.
- The gateway forwards the `anthropic-beta` values Claude Code needs on the Claude 5 models (Opus 5.5, Fable 5.1, Sonnet 5.5, Haiku 5.5): effort inside a message, context editing (`context_management`), and tools added during a session. [Wire compatibility](/docs/compat) lists them all.
- Claude Code's own cache marks work as on Anthropic's API.
- Web search works, at Anthropic's price per search (see [Pricing & billing](/docs/pricing#web-search)).
- A conversation that outgrows the window gets Anthropic's `prompt is too long` error, which Claude Code compacts on.
- Every request appears in `https://demo-api.routerplus.com/v1/usage` with its token counts and `cost_usd`.
- Claude Code does not know the context windows of open models and assumes 200,000 tokens. Set `CLAUDE_CODE_MAX_CONTEXT_TOKENS` to the model's window, for example `CLAUDE_CODE_MAX_CONTEXT_TOKENS=1000000` for `moonshotai/kimi-k3`.

**Limits:**

- Remote Control does not work through the gateway. It needs a claude.ai subscription sign-in. Claude Code turns it off when `ANTHROPIC_BASE_URL` points at a host other than `api.anthropic.com`, or when `ANTHROPIC_AUTH_TOKEN` or `ANTHROPIC_API_KEY` is set. To use Remote Control, start that session without the gateway variables and sign in with claude.ai.
- Voice dictation is off while a gateway key is in use.

> [!NOTE]
> The gateway serves these buyer endpoints: `/v1/chat/completions`, `/v1/responses` and
> `/v1/responses/compact`, `/v1/messages`, `/v1/messages/count_tokens` (unbilled, models
> with an Anthropic-dialect deployment), `/v1/models`, `/v1/images/generations`,
> `/v1/decisions`, `/v1/usage`, `/v1/generation`, `/v1/route` and `/v1/limits`, plus an
> unauthenticated `/healthz`. Any other path that an authenticated tool probes gets a
> well-formed `404` with `error_type: not_found` in the caller's own dialect. It does not
> hang or return an HTML page.

### Claude Code in VS Code

**Requirements:** VS Code 1.94 or later and the Claude Code extension.

**Setup:** the setting must be in your **user** settings. Run **Preferences: Open User Settings (JSON)** and add:

```json
{
  "claudeCode.environmentVariables": [
    { "name": "ANTHROPIC_BASE_URL", "value": "https://demo-api.routerplus.com" },
    { "name": "ANTHROPIC_AUTH_TOKEN", "value": "tm_vk_..." }
  ],
  "claudeCode.disableLoginPrompt": true
}
```

`claudeCode.disableLoginPrompt` stops the sign-in prompt. The extension reads `~/.claude/settings.json` only for the process it starts, not for its own sign-in check, so put the key in `claudeCode.environmentVariables`.

**Limits:** through a gateway, the extension shows no plan usage bars, no voice dictation and no Web tab.

### Claude Code in JetBrains IDEs

**Requirements:** the Claude Code CLI. The plugin for JetBrains IDEs (IntelliJ IDEA, PyCharm, WebStorm and the others) does not include it.

**Setup:**

1. Set up the CLI as in [Claude Code CLI](#claude-code-cli). The plugin runs the `claude` command in the IDE's terminal and uses `~/.claude/settings.json`.
2. If the IDE cannot find the CLI, set its path in **Settings → Tools → Claude Code [Beta] → Claude command**.

### Claude desktop app

**Requirements:** the Claude desktop app on macOS or Windows. The app sends its requests to a gateway in third-party mode.

**Setup:**

1. **Help → Troubleshooting → Enable Developer Mode**. On Windows the Help menu is under ☰, at the top left of the sign-in screen. The app restarts with a **Developer** menu.
2. **Developer → Configure Third-Party Inference…**
3. Under **Connection**, set **Inference provider** to **Gateway**.
4. Under **Gateway credentials**, set:
   - **Gateway base URL:** `https://demo-api.routerplus.com` (without `/v1`)
   - **Gateway API key:** your `tm_vk_...` key
   - **Credential kind:** Static API key
   - **Gateway auth scheme:** Bearer
5. **Apply Changes**, then **Save & Restart**.
6. On the sign-in screen, start in third-party mode. Do not sign in to claude.ai or create an Anthropic account.

An administrator can set the same values for a whole company with managed settings: `inferenceProvider: "gateway"`, `inferenceGatewayBaseUrl`, `inferenceGatewayApiKey`, `inferenceGatewayAuthScheme: "bearer"`.

**Limits:** in third-party mode, Remote Control, Anthropic's cloud sessions, the mobile apps, voice mode, computer use and the connectors made by Anthropic do not work. Local MCP servers work. Web search works, and the gateway passes it to Anthropic.

### Output limit, auto mode and the advisor

- **Output limit and your balance.** Claude Code asks the Claude 5 models for up to 128,000 output tokens (64,000 on Fable 5.1), and the gateway accepts up to each model's `max_output_tokens`. The hold is the input plus that output: about $2.56 per request on Opus 5.5 and $3.20 on Fable 5.1.
  - You pay for the tokens the provider reports.
  - An interrupt (Esc) costs the input and the output already streamed. An interrupt while the model thinks costs the input only, because the Claude 5 models do not show their thinking.
  - On a small balance, set a lower limit:

  ```bash
  export CLAUDE_CODE_MAX_OUTPUT_TOKENS=32000
  ```

- **Auto mode.** Claude Code starts in auto mode. In auto mode and plan mode, it checks some tool calls before it runs them (a web search, for example; in tests, file edits and simple commands needed no check).
  - Each check is a separate request to `claude-sonnet-5` with the conversation, billed at the full input price. One check of a 47,000-token conversation cost about $0.12.
  - The first check shows a notice that auto mode keeps working. Press Enter. To stop the notice, set `CLAUDE_CODE_AUTO_MODE_SERVER=0`.
  - To avoid the checks, press Shift+Tab to change to another permission mode.
- **Advisor.** Do not turn on `/advisor`. It runs a second model at its own rates, so the gateway does not forward its beta, and Anthropic refuses the request with a 400 that names `Input tag 'advisor_…'`. Claude Code 2.1.280 or later then retries without the advisor and leaves it off until it exits.

### Pinning which models Claude Code uses

Claude Code picks its own model ids. Set them with the standard variables, in the shell or in the `env` block of `settings.json`, with any Claude id from the catalog:

```bash
export ANTHROPIC_MODEL=claude-sonnet-5-5               # main model
export ANTHROPIC_DEFAULT_HAIKU_MODEL=claude-haiku-5-5  # background and fast tasks
```

- Set `ANTHROPIC_DEFAULT_HAIKU_MODEL`. Otherwise, behind a gateway, background tasks run on the main model (Opus 5.5 by default).
- Aliases resolve as on Anthropic's API: `opus` is `claude-opus-5-5`, `sonnet` is `claude-sonnet-5-5`, `haiku` is `claude-haiku-5-5`, `fable` is `claude-fable-5-1`.
- `ANTHROPIC_DEFAULT_OPUS_MODEL`, `ANTHROPIC_DEFAULT_SONNET_MODEL`, `ANTHROPIC_DEFAULT_FABLE_MODEL` and `CLAUDE_CODE_SUBAGENT_MODEL` pin the others.
- `ANTHROPIC_MODEL` overrides your `/model` choice at every launch. To set only the starting model, use `ANTHROPIC_DEFAULT_MODEL` (Claude Code 2.1.236 or later).
- Inside a session, `/model` accepts any catalog id.

Spend from every session appears per request in the console under Usage ([Usage](https://demo.routerplus.com/console/usage)) and in `https://demo-api.routerplus.com/v1/usage`.

## Codex

Codex calls the Responses API, which the gateway serves at [POST /v1/responses](/docs/api-responses).

**Requirements:** Codex (the CLI, the IDE extension, or the desktop app, which is Codex in the ChatGPT desktop app). All of them read one file, `~/.codex/config.toml`. The CLI needs no sign-in for this provider.

**Setup:**

1. Add the gateway as a provider. Keys such as `model` must come before the first `[table]`:

   ```toml
   # ~/.codex/config.toml
   model = "gpt-6-luna"
   model_provider = "routerplus"

   [model_providers.routerplus]
   name = "RouterPlus"
   base_url = "https://demo-api.routerplus.com/v1"
   env_key = "TM_API_KEY"
   wire_api = "responses"
   ```

2. Start Codex with the key in the environment:

   ```bash
   export TM_API_KEY=tm_vk_...
   codex
   ```

- Use any GPT-6 or GPT-5.6 model as `model` (`gpt-6-astra`, `gpt-6.1-sol`, `gpt-6-sol`, `gpt-6-luna`, `gpt-5.6-sol`, `gpt-5.6-terra`, `gpt-5.6-luna`), or start Codex with `codex -m gpt-6-astra`.
- `wire_api = "responses"` is Codex's default, so you can leave it out. With `wire_api = "chat"`, current Codex does not start ("`wire_api = "chat"` is no longer supported").
- Do not name the provider `OpenAI`. Codex then treats it as OpenAI's own service and changes how it compacts a long conversation.

**The desktop app** may not see your shell's variables when started from the Dock or Finder. Put the key in the provider block instead of `env_key`, never both: Codex fails when `env_key` names a missing variable.

```toml
[model_providers.routerplus]
name = "RouterPlus"
base_url = "https://demo-api.routerplus.com/v1"
wire_api = "responses"
experimental_bearer_token = "tm_vk_..."
```

- The file then holds your key. Do not commit it or share it.
- To keep the key out of the file on a Mac, keep `env_key`, run `launchctl setenv TM_API_KEY tm_vk_...`, and quit and reopen the app. Do it again after a restart.
- The desktop app's model picker lists only OpenAI's own models, so set `model` in the file.

**Claude models (preview).** Codex can run Claude through the gateway's preview translation:

```toml
model = "claude-sonnet-5-5"
model_provider = "routerplus"
model_context_window = 272000
web_search = "disabled"
```

- Codex warns "Model metadata for `claude-sonnet-5-5` not found. Defaulting to fallback metadata". Only a full model catalog of your own (`model_catalog_json`) removes the warning.
- Codex caps `model_context_window` at 272,000 tokens for an unknown id, so set that.
- Codex ignores `model_max_output_tokens`, with a warning.
- `web_search = "disabled"` stops Codex from sending its hosted web search tool, which does not run on Claude (the gateway would drop it and name it in `x-tm-dropped-params`).
- `model_reasoning_effort` becomes Claude's `output_config.effort`. `minimal` becomes `low`. `none` turns thinking off on Claude Haiku 5.5, Sonnet 5 and Opus 5, and is `low` on the other Claude models. On Claude Sonnet 4.5 and Haiku 4.5 it is dropped and named in `x-tm-dropped-params`.

> [!WARNING]
> Do not sign in to ChatGPT in Codex while you use the gateway. A known bug in the
> desktop app ([openai/codex#48369](https://github.com/openai/codex/issues/48369))
> disables the send button when the ChatGPT plan's usage runs out, even for a custom
> provider such as this one.

**Limits:**

- Stored responses are not supported: `store` is always false, and `previous_response_id` is a 400. Codex is not affected: it sends `store: false` and the full conversation on every turn, and compacts with an ordinary `/v1/responses` request.
- Claude through Codex is a preview. Claude's reasoning does not carry from turn to turn.
- Codex sends no output limit (see [the hold](#your-balance-and-the-hold)).
- When your balance runs out, Codex stops with "Quota exceeded. Check your plan and billing details." This is the gateway's `insufficient_quota`. Add credits in [Billing](https://demo.routerplus.com/console/billing).
- Codex retries a rate limit only when the 429 carries `retry-after`. The gateway's 429s do.

## Cursor

Cursor's Chat and Agent can call the gateway with an OpenAI key and a base URL.

**Requirements:** a paid Cursor plan (Pro, Pro+, Ultra or Teams). On the free plan, outside keys do not work even when they are set up.

**Setup:**

1. Open **Cursor Settings → Models**, and expand **API Keys** at the bottom.
2. Under **OpenAI API Key**, paste your `tm_vk_...` key and turn on **Use OpenAI API Key**.
3. Turn on **Override OpenAI Base URL** and enter `https://demo-api.routerplus.com/v1`.
4. Add the models by name in the model field on the same page:
   - GPT models such as `gpt-6-astra`, `gpt-6.1-sol`, `gpt-6-luna` and `gpt-5.6-terra`.
   - Claude models by their `rp-` names: `rp-sonnet-5-5`, `rp-opus-5-5`, `rp-haiku-5-5` and `rp-fable-5-1`.
5. Restart Cursor, open a new chat, and pick one of these models in Chat or Agent.

Use `rp-sonnet-5-5`, not `claude-sonnet-5-5`. Cursor sends a name that starts with `claude-` with its Anthropic key, never to your base URL, and without that key it fails with "Model name is not valid". Each `rp-` name is one Claude model at its price (see [Claude names for Cursor](/docs/models#claude-names-for-cursor)).

**Limits:**

- Only Chat and Agent use your key. A subagent runs on its chat's model. Tab completion, Auto, the Cursor CLI and cloud agents always use Cursor's own models.
- While the override is on, Cursor sends every model that is not Claude or Gemini to the gateway. Its own GPT models arrive under Cursor's names and may get a 404. Its Composer and Grok models fail. Turn **Use OpenAI API Key** off to use them; your key and URL stay saved.
- If Cursor says a name you add "is already available", it is one of Cursor's own models, and with the override on it comes to the gateway under Cursor's name.
- Cursor calls the gateway from Cursor's servers, not from your computer.
- Cursor sends no output limit (see [the hold](#your-balance-and-the-hold)).
- You cannot set a context window or a reasoning effort for a custom model.
- On a Teams or Enterprise plan, Cursor charges its own fee per token on requests with your key, and an admin can hide the API Keys section.
- Cursor edits files on GPT models with a custom (free-form) tool, which the gateway supports on the GPT-6 and GPT-5.6 models. `gpt-4o`, `gpt-4o-mini` and `gpt-4.1-mini` take none, so use a GPT-6 or GPT-5.6 model for Agent.

## Cline

**Requirements:** Cline in VS Code, in a JetBrains IDE, as Cline Desktop, or as the Cline CLI (Node 20 or later). All of them share their settings in `~/.cline`.

**Setup:**

1. Pick the **OpenAI Compatible** provider and set these fields:

   | Field | Value |
   |---|---|
   | API Provider | OpenAI Compatible |
   | Base URL | `https://demo-api.routerplus.com/v1` |
   | OpenAI Compatible API Key | `tm_vk_...` |
   | Model ID | `claude-sonnet-5-5`, or any id from the catalog (**Use custom model ID…** if the list does not show it) |

2. Open **Model Configuration**. Cline assumes a 128,000-token context window for unknown models. Set:
   - **Context Window Size:** the model's window, 1,000,000 for `claude-sonnet-5-5`.
   - **Supports Images:** on, for the Claude 5, GPT-6 and GPT-5.6 models.
   - **Max Output Tokens:** leave it empty, so the model gets its maximum and the [hold](#your-balance-and-the-hold) stays at 32,768 output tokens. A number that you set is sent and held in full.
   - **Input Price** and **Output Price** (per 1M tokens): the model's prices, if you want Cline's cost display to match your bill.

Where to set it in each Cline:

- **JetBrains IDEs:** install **Cline** from **Settings → Plugins → Marketplace** and open it from **View → Tool Windows → Cline**.
- **Cline Desktop:** **Add Provider → OpenAI-Compatible Provider** takes the same base URL, key and model ids.
- **Cline CLI** takes the same values:

```bash
npm install -g cline
cline auth --provider openai-compatible --apikey tm_vk_... --modelid claude-sonnet-5-5 --baseurl https://demo-api.routerplus.com/v1
cline "Add a README for this project"
```

**Limits:**

- Cline sends no cache marks. The gateway's [automatic caching](/docs/compat#automatic-caching-on-claude) covers it on Claude.
- On a rate limit, Cline waits and tries again by itself, with no message while it waits ([When you hit a rate limit](#when-you-hit-a-rate-limit)).
- The Cline CLI's file editor takes at most 6,000 characters per edit, so a long file takes several edits and requests.
- Cline's own Anthropic and OpenAI providers go to those providers' servers. Use OpenAI Compatible.

## Kilo Code

**Requirements:** Kilo Code for VS Code, the Kilo Code plugin for JetBrains IDEs, or the Kilo CLI (`npm install -g @kilocode/cli`, then `kilo`).

**Setup in VS Code:** open **Settings** (the gear icon) → **Providers**. Find **Custom provider**, click **Connect**, fill in these fields and click **Submit**:

| Field | Value |
|---|---|
| Provider ID | `routerplus` |
| Display name | RouterPlus |
| Provider API | OpenAI Compatible |
| Base URL | `https://demo-api.routerplus.com/v1` |
| API key | `tm_vk_...` |
| Models | `claude-sonnet-5-5`, `gpt-6-luna` and any other catalog id. Turn on **Image** for the Claude 5, GPT-6 and GPT-5.6 models |

**Setup in JetBrains IDEs:** open **Settings → Kilo Code → Providers → Add custom provider**.

1. Enter the Provider ID, Display name, Base URL and API key (or the name of an environment variable that holds the key).
2. Type the model ids, separated by commas, in **Model IDs**, and click **Add**.
3. This dialog has no Image switch. Turn images on in `kilo.jsonc` (below).

**Config:** set the context window and output limit in `~/.config/kilo/kilo.jsonc`, which the VS Code extension, the JetBrains plugin and the Kilo CLI all read. The settings screen has neither, and without a context window Kilo Code compacts only after the gateway refuses a prompt as too long:

```json
{
  "provider": {
    "routerplus": {
      "npm": "@ai-sdk/openai-compatible",
      "name": "RouterPlus",
      "options": {
        "baseURL": "https://demo-api.routerplus.com/v1",
        "apiKey": "tm_vk_..."
      },
      "models": {
        "claude-sonnet-5-5": { "name": "Claude Sonnet 5.5", "modalities": { "input": ["text", "image"], "output": ["text"] }, "limit": { "context": 1000000, "output": 128000 } },
        "gpt-6-luna": { "name": "GPT-6 Luna", "modalities": { "input": ["text", "image"], "output": ["text"] }, "limit": { "context": 1050000, "output": 128000 } }
      }
    }
  },
  "model": "routerplus/claude-sonnet-5-5"
}
```

**Limits:**

- Keep `modalities` on each model. Without it, Kilo Code sends no images.
- Kilo Code sends `limit.output` as `max_tokens`, up to 32,000 unless you set `KILO_EXPERIMENTAL_OUTPUT_TOKEN_MAX` (128,000 is the models' maximum). A lower number keeps the [hold](#your-balance-and-the-hold) small.

> [!NOTE]
> Roo Code was shut down in May 2026, and its repository is archived. Use Kilo Code or
> Cline instead.

## OpenCode

**Requirements:** OpenCode, the CLI or the desktop app. Both read providers from `opencode.json`, globally at `~/.config/opencode/opencode.json` or in a project's root.

**Setup:**

1. Add the gateway with the OpenAI-compatible package, and list the models you want with their limits:

   ```json
   {
     "$schema": "https://opencode.ai/config.json",
     "provider": {
       "routerplus": {
         "npm": "@ai-sdk/openai-compatible",
         "name": "RouterPlus",
         "options": {
           "baseURL": "https://demo-api.routerplus.com/v1",
           "apiKey": "{env:TM_API_KEY}"
         },
         "models": {
           "claude-sonnet-5-5": { "name": "Claude Sonnet 5.5", "attachment": true, "modalities": { "input": ["text", "image"], "output": ["text"] }, "limit": { "context": 1000000, "output": 128000 } },
           "claude-opus-5-5": { "name": "Claude Opus 5.5", "attachment": true, "modalities": { "input": ["text", "image"], "output": ["text"] }, "limit": { "context": 1000000, "output": 128000 } },
           "gpt-6-luna": { "name": "GPT-6 Luna", "attachment": true, "modalities": { "input": ["text", "image"], "output": ["text"] }, "limit": { "context": 1050000, "output": 128000 } }
         }
       }
     },
     "model": "routerplus/claude-sonnet-5-5"
   }
   ```

2. Give OpenCode the key in one of two ways:
   - Export `TM_API_KEY` before you start OpenCode. The desktop app reads your login shell's variables.
   - Store the key: run `/connect` in OpenCode (or `opencode auth login` in a shell), choose **Other**, enter the provider id `routerplus`, paste the key, and leave `apiKey` out of the file.
3. Pick a model with `/models`, or start with `opencode -m routerplus/claude-sonnet-5-5`.

**Limits:**

- Screenshots need both `"attachment": true` and `"modalities": { "input": ["text", "image"], "output": ["text"] }` on the model. Without `modalities`, OpenCode sends no image.
- OpenCode asks for at most 32,000 output tokens, even when `limit.output` is higher, unless you set `OPENCODE_EXPERIMENTAL_OUTPUT_TOKEN_MAX`. That also keeps the hold small.
- `@ai-sdk/openai-compatible` calls `/v1/chat/completions`, which serves every model.

## Hermes Agent

**Requirements:** Hermes Agent. It reads its endpoint from `config.yaml` in its home folder (`~/.hermes`, or the folder in `HERMES_HOME`).

**Setup:**

1. Add the gateway as a custom endpoint in `config.yaml`:

   ```yaml
   model:
     provider: custom
     base_url: https://demo-api.routerplus.com/v1
     api_key: ${TM_API_KEY}
     default: claude-sonnet-5-5
   ```

2. Run Hermes with the key in the environment:

   ```bash
   export TM_API_KEY=tm_vk_...
   hermes
   ```

- Hermes calls `/v1/chat/completions` with the key as a bearer token. Every catalog model works, for example `moonshotai/kimi-k3` or `deepseek/deepseek-v4.1-flash`.
- Hermes reads each model's context window from `GET /v1/models`. To set it yourself, add `context_length:` with the model's window.
- To call Claude on `/v1/messages`, set `base_url: https://demo-api.routerplus.com` and add `api_mode: anthropic_messages`.
- For one task without a session, run `hermes chat -q "..."`. Add `--yolo` only if you accept that shell commands run without a prompt.

**Limits:** Hermes sends no output limit, so the [hold](#your-balance-and-the-hold) counts at most 32,768 output tokens.

## Other tools

Most tools that speak "OpenAI-compatible" take the same two values: **base URL** `https://demo-api.routerplus.com/v1` and **API key** `tm_vk_...`. Where a tool asks for the model's limits, use the table in [Before you start](#before-you-start).

### Goose

**Requirements:** the Goose desktop app or the Goose CLI.

**Setup in the desktop app:** open **Settings → Models → Configure providers → Add Custom Provider**.

1. Choose the provider type **OpenAI Compatible**.
2. Enter a display name such as RouterPlus, the API URL `https://demo-api.routerplus.com/v1/chat/completions`, your key, and the model ids you want (for example `claude-sonnet-5-5, gpt-6-luna`), with streaming on.
3. Click **Create Provider**.

**Setup in the CLI:** `goose configure` → **Custom Providers** → **Add A Custom Provider** asks for the same values.

**Config:** Goose stores each custom provider as a file in `~/.config/goose/custom_providers/`. This one reads the key from `TM_API_KEY`:

```json
{
  "name": "custom_routerplus",
  "engine": "openai",
  "display_name": "RouterPlus",
  "description": "RouterPlus gateway",
  "api_key_env": "TM_API_KEY",
  "base_url": "https://demo-api.routerplus.com/v1/chat/completions",
  "models": [
    { "name": "claude-sonnet-5-5", "context_limit": 1000000 },
    { "name": "gpt-6-luna", "context_limit": 1050000 }
  ],
  "supports_streaming": true,
  "requires_auth": true
}
```

Start a session with `goose session --provider custom_routerplus --model claude-sonnet-5-5`.

**Limits:**

- Goose calls GPT-6 and GPT-5 models on `/v1/responses` by itself, which the gateway serves.
- Set `GOOSE_MAX_TOKENS` to give Goose an output limit.

### Zed

**Requirements:** Zed's agent.

**Setup:**

1. Add an OpenAI-compatible provider to Zed's `settings.json` (below). `max_tokens` is the model's context window.
2. Enter the key in **Settings → AI → LLM Providers** (Zed keeps it in the system keychain), or set `ROUTERPLUS_API_KEY` in the environment. Do not put the key in `settings.json`.

```json
{
  "language_models": {
    "openai_compatible": {
      "routerplus": {
        "api_url": "https://demo-api.routerplus.com/v1",
        "available_models": [
          {
            "name": "claude-sonnet-5-5",
            "display_name": "Claude Sonnet 5.5",
            "max_tokens": 1000000,
            "max_output_tokens": 128000,
            "capabilities": { "tools": true, "images": true }
          },
          {
            "name": "gpt-6-luna",
            "display_name": "GPT-6 Luna",
            "max_tokens": 1050000,
            "max_output_tokens": 128000,
            "capabilities": { "tools": true, "images": true }
          }
        ]
      }
    }
  }
}
```

For Claude in Anthropic's format, Zed also has `anthropic_compatible` providers. They have the same shape, with `api_url` set to `https://demo-api.routerplus.com`, without `/v1`.

### VS Code chat with your own key

**Requirements:** VS Code 1.122 or later. VS Code's built-in chat takes your own key, with no GitHub account and no Copilot plan.

**Setup:**

1. In the model picker, choose **Manage Language Models** → **Add Models** → **Custom Endpoint**.
2. Give it a name and your key, and pick the API type.
3. VS Code opens `chatLanguageModels.json`. Add the models there:

```json
[
  {
    "name": "RouterPlus",
    "vendor": "customendpoint",
    "apiKey": "${input:routerplusApiKey}",
    "models": [
      {
        "id": "claude-sonnet-5-5",
        "name": "Claude Sonnet 5.5",
        "url": "https://demo-api.routerplus.com/v1/messages",
        "apiType": "messages",
        "toolCalling": true,
        "vision": true,
        "maxInputTokens": 872000,
        "maxOutputTokens": 128000
      },
      {
        "id": "gpt-6-luna",
        "name": "GPT-6 Luna",
        "url": "https://demo-api.routerplus.com/v1/responses",
        "apiType": "responses",
        "toolCalling": true,
        "vision": true,
        "maxInputTokens": 922000,
        "maxOutputTokens": 128000
      }
    ]
  }
]
```

- `maxInputTokens` plus `maxOutputTokens` must fit the model's context window.
- `toolCalling: true` puts a model in agent mode.

**Limits:** without a GitHub account, inline suggestions and semantic search do not work. Set `chat.utilityModel` to one of these models for titles and commit messages.

### Continue

**Requirements:** Continue. Agent mode needs `tool_use`.

**Config:** in `~/.continue/config.yaml`:

```yaml
name: RouterPlus
version: 1.0.0
schema: v1
models:
  - name: Claude Sonnet 5.5
    provider: openai
    model: claude-sonnet-5-5
    apiBase: https://demo-api.routerplus.com/v1
    apiKey: tm_vk_...
    roles: [chat, edit, apply]
    capabilities: [tool_use]
    defaultCompletionOptions:
      contextLength: 1000000
      maxTokens: 32000
```

To keep the key out of the file, put `TM_API_KEY=tm_vk_...` in `~/.continue/.env` and refer to it from `apiKey` with Continue's secrets syntax.

### aider

**Setup:**

```bash
export OPENAI_API_BASE=https://demo-api.routerplus.com/v1
export OPENAI_API_KEY=tm_vk_...
aider --model openai/claude-sonnet-5-5
```

**Config:** aider warns that it does not know the model. To give it the limits, put a `.aider.model.metadata.json` in your home folder or the repository:

```json
{
  "openai/claude-sonnet-5-5": {
    "max_tokens": 128000,
    "max_input_tokens": 1000000,
    "max_output_tokens": 128000,
    "litellm_provider": "openai",
    "mode": "chat"
  }
}
```

For aider's diff edits, add `.aider.model.settings.yml`:

```yaml
- name: openai/claude-sonnet-5-5
  edit_format: diff
  use_repo_map: true
```

**Limits:** aider sends no output limit (see [the hold](#your-balance-and-the-hold)).

### Anything else

If a tool has a "base URL" box next to its OpenAI key box, set those two values.

## Playground

The [Playground](https://demo.routerplus.com/playground) runs in the browser. Compare any catalog models' answers, costs and providers side by side. Sending a prompt needs an account. See [Playground](/docs/playground).

## SDKs inside the project your agent is editing

| Client | Change |
|---|---|
| OpenAI SDK (any language) | `base_url = "https://demo-api.routerplus.com/v1"`, `api_key = TM_API_KEY` |
| Anthropic SDK (any language) | `base_url = "https://demo-api.routerplus.com"`, `api_key = TM_API_KEY` |
| Raw HTTP | host → `https://demo-api.routerplus.com`, key in `Authorization: Bearer` or `x-api-key` |

- Streaming examples for both surfaces: [Quickstart](/docs/quickstart).
- The Responses API: [POST /v1/responses](/docs/api-responses).
- Migrating a codebase in one prompt: [Migrate](/docs/migration).

## The installation runbook

A coding agent can run this section. Give it to your agent (`read https://demo.routerplus.com/docs/install.md and get me set up`), or follow it yourself.

**Objective:** this environment makes a successful, streamed, billed model call through the gateway.

**Done when:** a streamed completion ends with a usage object that has a `cost` field, and `https://demo-api.routerplus.com/v1/usage` shows the request.

1. **Get a key** (skip if `TM_API_KEY` is already set).
   - The user opens [Sign up](https://demo.routerplus.com/signup), completes Clerk authentication and email verification, and saves the first key shown after sign-in.
   - Signup does not grant free credit. The user adds paid credits in [Billing](https://demo.routerplus.com/console/billing).
   - Existing customers sign in at [https://demo.routerplus.com/login](https://demo.routerplus.com/login) with the same verified email. They create a key at [API keys](https://demo.routerplus.com/console/keys), or copy an existing one from its row.
   - Account creation has no terminal API. Signup and sign-in use Clerk in the browser, and a public signup response has no `dev_verify_link`. Do not call the retired `POST /v1/signup` or local `POST /login` routes, or the retired magic-link submission. Continue client setup when the key is available.

2. **Export the key**, and write it to the project's `.env` if one exists (never commit it):

   ```bash
   export TM_API_KEY=tm_vk_...
   ```

3. **Discover the models.** Any id in this file works in step 4:

   ```bash
   curl -s https://demo.routerplus.com/api/models.json
   ```

4. **Make the test call** on the OpenAI-compatible surface. It works for every chat model, including Claude models, because the gateway translates:

   ```bash
   curl -N https://demo-api.routerplus.com/v1/chat/completions \
     -H "Authorization: Bearer $TM_API_KEY" \
     -H "content-type: application/json" \
     -d '{"model":"claude-haiku-5-5","stream":true,"max_tokens":40,"messages":[{"role":"user","content":"Reply with exactly: MARKETPLACE OK"}]}'
   ```

   Expected: an SSE stream that ends with a usage chunk with a `cost` field, then `data: [DONE]`.

   On HTTP `429` with `error_type: insufficient_quota`, stop. Ask the user to check their balance and spend caps in [Billing](https://demo.routerplus.com/console/billing). Retry **once** after they fix the cause, never in a loop. [Errors](/docs/errors) gives the retry rules for each error class.

5. **Wire the user's stack.** Apply every branch that matches this environment:
   - the OpenAI SDK, Anthropic SDK and raw-HTTP changes from the table above
   - each coding tool the user has, as its section on this page shows (Claude Code, Codex, Cursor, Cline, Kilo Code, OpenCode, the others)

   Edit a tool's settings file only with the user's consent. Never write the key into a file that is committed.

6. **Verify billing.** This is the done-when condition:

   ```bash
   curl -s -H "Authorization: Bearer $TM_API_KEY" https://demo-api.routerplus.com/v1/usage
   ```

   The test call must appear in `recent_attempts` with its token counts and `cost_usd`.

7. **Optional, recommended:** add attribution headers to the user's app: `HTTP-Referer: https://the-users-app.example` and `X-Title: The App Name`. They identify the app for per-app analytics and carry no content.

Finally, report to the user: the org id, where the key is stored, which stacks and tools were wired, and the cost of the test call.

## /llms.txt: start here if you are an agent

```bash
curl -s https://demo.routerplus.com/llms.txt
```

`/llms.txt` has the gateway base URL, browser signup instructions, a raw-markdown link to every doc page, and the model catalog. Its first link is the [Agent integration guide](https://demo.routerplus.com/docs/agent-integration.md). [https://demo.routerplus.com/llms-full.txt](https://demo.routerplus.com/llms-full.txt) has every page in one fetch.

## Next steps

- [Quickstart](/docs/quickstart): the same flow by hand, with streaming examples on both surfaces
- [Migrate](/docs/migration): the one-prompt migration for an existing codebase
- [Apps from Replit, Lovable, Bolt and v0](/docs/app-builders): the prompt that wires an app you build there
- [Errors](/docs/errors): every `error_type`, and the retry rules agents should follow
- [Rate limits & spend caps](/docs/limits): trial RPM, monthly caps, and the 429 with a reset time
