# Coding Agents & Harnesses

Set up Claude Code, Codex CLI, OpenCode and other agent clients with one command, or point them at the gateway by hand.


One command sets up most harnesses for you. For anything else, if your client lets you set a base URL and an API key, it works here: pick its section under [Set up by hand](#set-up-by-hand), paste the snippet, and send a request.

Running the agent in an isolated machine instead of on your laptop? The [Sandbox](/docs/sandbox) image ships Claude Code, Codex and OpenCode already configured for Boundless.

Laya, our System One model, cannot be a harness's model, but a harness can call it before each tool call. [System One](/docs/system-one#gate-tool-calls-in-claude-code) has a Claude Code hook that asks before a destructive command runs.

## Set up with one command

Run this in a terminal on macOS or Linux:

```bash
curl -fsSL https://boundless.md/install | sh
```

The script runs the setup package with your Node.js 22 or later, or downloads a private copy of Node into `~/.boundless` first. On Windows, or to skip the script, run the package yourself:

```bash
npx -y @boundless.md/setup@latest
```

It signs you in through your browser, creates a key on your account, and asks which harnesses to configure. On a machine with no browser, such as over SSH, it shows a code you approve from any other device. It stores the key in the macOS Keychain, the Linux Secret Service or a private file, and exports it as `BOUNDLESS_API_KEY` from your shell profile without writing the key into the profile. Hermes, Codex and OpenClaw also get it in their own `.env` file, because their desktop apps and background services never read a shell profile. You pick a main and a background model from the live catalog, with prices. Every file it changes is backed up first, and it finishes with one small request per model and wire format, showing what each cost.

It offers every harness in [Set up by hand](#set-up-by-hand). Where a harness keeps its configuration in a file, setup writes it; where it lives in an app's settings, as in Cursor, setup prints the steps from that harness's section.

- For Claude Code you can keep your Anthropic login: choose **Anthropic account + Boundless**, and `/model` lists the Boundless models beside Anthropic's. It needs Claude Code 2.1.282 or later and is a preview on Linux and Windows.
- Project scope keeps the key in `.boundless/api-key`, ignored by git, and writes project-level configuration where the harness has one.

To put everything back the way it was before the first run:

```bash
curl -fsSL https://boundless.md/install | sh -s -- --revert
```

The key stays on your account until you revoke it in [API Keys](/api-keys). To have your coding agent do the setup instead, point it at [the setup guide](/setup.md): the same steps, written for an agent.

## Set up by hand

The API speaks [three wire formats](/docs/api-compatibility). Your client's format decides which base URL you give it:

| Wire format | Base URL | Credential |
| --- | --- | --- |
| OpenAI chat completions | `https://api.inference.boundless.network/v1` | `Authorization: Bearer <key>` |
| OpenAI Responses (Codex-compatible) | `https://api.inference.boundless.network/v1` | `Authorization: Bearer <key>` |
| Anthropic Messages | `https://api.inference.boundless.network` | `x-api-key: <key>` or `Authorization: Bearer <key>` |

> Anthropic clients append `/v1/messages` themselves, so that row takes the root. Need a key first? [Mint a trial key](/docs/quickstart#try-it-without-an-account) or create one in [API Keys](/api-keys).

### Claude Code

Anthropic Messages format. Put the configuration in `~/.claude/settings.json` so it applies everywhere. Exit Claude Code before changing this file; start a fresh session afterward.

```json
{
  "model": "deepseek-v4.1-flash",
  "env": {
    "ANTHROPIC_BASE_URL": "https://api.inference.boundless.network",
    "ANTHROPIC_AUTH_TOKEN": "your-boundless-key",
    "ANTHROPIC_MODEL": "deepseek-v4.1-flash",
    "ANTHROPIC_DEFAULT_OPUS_MODEL": "deepseek-v4.1-flash",
    "ANTHROPIC_DEFAULT_SONNET_MODEL": "deepseek-v4.1-flash",
    "ANTHROPIC_DEFAULT_HAIKU_MODEL": "dsv4",
    "CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC": "1",
    "CLAUDE_CODE_DISABLE_UNKNOWN_MODEL_WINDOW_ENFORCEMENT": "1"
  }
}
```

- Use `ANTHROPIC_AUTH_TOKEN` (sends as `Authorization: Bearer`, works immediately) rather than `ANTHROPIC_API_KEY` (sends as `x-api-key`, requires interactive approval first).
- Set every model slot. Claude Code can pick its saved model or a family model for foreground and background work.
- Claude Code 2.1.27x refuses model ids missing from its built-in catalog, which is every model here. `CLAUDE_CODE_DISABLE_UNKNOWN_MODEL_WINDOW_ENFORCEMENT=1` restores the earlier behaviour of asking the API.
- The credential replaces your claude.ai login while set. Remove it from `settings.json` to go back. To keep the key out of the file, drop `ANTHROPIC_AUTH_TOKEN` and use [`apiKeyHelper`](https://code.claude.com/docs/en/settings-reference) instead.

```bash
claude --model "deepseek-v4.1-flash" -p 'Use the Bash tool to run printf boundless, then report the output.'
```

### Claude Desktop

Set Claude Desktop up with the [setup command](#set-up-with-one-command), and choose **Claude Desktop** and user scope:

```bash
curl -fsSL https://boundless.md/install | sh
```

Desktop only lists Claude model IDs, so setup installs a small local bridge that gives the other models IDs it accepts. It then adds a "Boundless" entry to Desktop's third-party inference configuration and applies it, leaving your other entries alone. Quit and reopen Desktop afterwards, and start a new conversation with the model you want.

While the Boundless entry is applied, Desktop runs its separate third-party profile, so your claude.ai chats, projects, connectors and MCP servers are hidden there, not deleted. Picking another configuration in Desktop, or running setup with `--revert`, brings them back.

### OpenAI SDK

Works unchanged against chat completions. This example forces one tool call, assembles streamed arguments, returns the local result, then streams the final answer. The last chunk carries exact token counts.

```python
import json
import os
from openai import OpenAI

client = OpenAI(
    api_key=os.environ["BOUNDLESS_API_KEY"],
    base_url="https://api.inference.boundless.network/v1",
)
messages = [{"role": "user", "content": "What is 20 + 22? Use the add tool."}]
tools = [{
    "type": "function",
    "function": {
        "name": "add",
        "description": "Add two integers.",
        "parameters": {
            "type": "object",
            "properties": {
                "a": {"type": "integer"},
                "b": {"type": "integer"},
            },
            "required": ["a", "b"],
            "additionalProperties": False,
        },
    },
}]

stream = client.chat.completions.create(
    model="deepseek-v4.1-flash",
    messages=messages,
    max_tokens=1024,
    tools=tools,
    tool_choice={"type": "function", "function": {"name": "add"}},
    stream=True,
    stream_options={"include_usage": True},
)

tool_call = {"id": "", "type": "function", "function": {"name": "", "arguments": ""}}
for chunk in stream:
    if chunk.usage:
        print(f"first request: {chunk.usage}")
    if not chunk.choices:
        continue
    for delta_call in chunk.choices[0].delta.tool_calls or []:
        if delta_call.id:
            tool_call["id"] = delta_call.id
        if delta_call.function.name:
            tool_call["function"]["name"] = delta_call.function.name
        if delta_call.function.arguments:
            tool_call["function"]["arguments"] += delta_call.function.arguments

arguments = json.loads(tool_call["function"]["arguments"])
messages.extend([
    {"role": "assistant", "tool_calls": [tool_call]},
    {
        "role": "tool",
        "tool_call_id": tool_call["id"],
        "content": json.dumps({"result": arguments["a"] + arguments["b"]}),
    },
])

stream = client.chat.completions.create(
    model="deepseek-v4.1-flash",
    messages=messages,
    max_tokens=1024,
    tools=tools,
    stream=True,
    stream_options={"include_usage": True},
)
for chunk in stream:
    if chunk.choices and chunk.choices[0].delta.content:
        print(chunk.choices[0].delta.content, end="", flush=True)
    if chunk.usage:
        print(f"\nfinal request: {chunk.usage}")
```

### omp (Oh My Pi)

Declare a provider in `~/.omp/agent/models.yml`:

```yaml
providers:
  boundless:
    baseUrl: https://api.inference.boundless.network/v1
    api: openai-completions
    apiKey: BOUNDLESS_API_KEY
    discovery:
      type: litellm
    compat:
      reasoningContentField: reasoning_content

modelRoles:
  default: boundless/deepseek-v4.1-flash
  tiny: boundless/dsv4
```

The file lists no models or prices, because `discovery` fetches both from `GET /v1/model/info` at startup. New models and price changes reach you on the next start without editing it. `apiKey` is read as an environment variable name before it is tried as a literal token, which keeps your key out of the file.

### Hermes

OpenAI format, in `~/.hermes/config.yaml`. `key_env` names the variable to read:

```yaml
providers:
  boundless:
    api: https://api.inference.boundless.network/v1
    key_env: BOUNDLESS_API_KEY
    transport: chat_completions
    models:
      deepseek-v4.1-flash:
        context_length: 1048576

model:
  provider: custom:boundless
  default: deepseek-v4.1-flash
```

Hermes Desktop never reads your shell profile, so put the key in `~/.hermes/.env`, which every Hermes process loads:

```bash
echo 'BOUNDLESS_API_KEY=YOUR_API_KEY' >> ~/.hermes/.env
```

A key added with `hermes auth add boundless` takes precedence over `key_env`; remove it with `hermes auth remove boundless <id>` (ids from `hermes auth list`).

```bash
hermes chat --toolsets terminal -q 'Use the terminal tool to run printf boundless, then report the output.'
```

### Hermes Desktop

The desktop app runs the same agent on the same `~/.hermes/config.yaml` as the CLI:

```yaml
providers:
  boundless:
    api: https://api.inference.boundless.network/v1
    key_env: BOUNDLESS_API_KEY
    transport: chat_completions
    models:
      deepseek-v4.1-flash:
        context_length: 1048576

model:
  provider: custom:boundless
  default: deepseek-v4.1-flash
```

An app opened from the Dock or a launcher never sees the variables your shell exports, so the key goes in `~/.hermes/.env`, which every Hermes process loads:

```bash
echo 'BOUNDLESS_API_KEY=YOUR_API_KEY' >> ~/.hermes/.env
```

Quit the app fully and reopen it; the running backend keeps the settings it started with. The [setup command](#set-up-with-one-command) writes both files when you choose **Hermes Desktop**.

### OpenCode

A custom provider in `opencode.json`, either in your project or `~/.config/opencode/opencode.json`. `model` is the default for every session and `small_model` handles titles, summaries and other light work:

```json
{
  "$schema": "https://opencode.ai/config.json",
  "model": "boundless/deepseek-v4.1-flash",
  "small_model": "boundless/dsv4",
  "provider": {
    "boundless": {
      "npm": "@ai-sdk/openai-compatible",
      "name": "Boundless",
      "options": {
        "baseURL": "https://api.inference.boundless.network/v1",
        "apiKey": "{env:BOUNDLESS_API_KEY}"
      },
      "models": {
        "dsv4": {
          "name": "DeepSeek V4 Flash",
          "limit": { "context": 1048576, "output": 32000 },
          "reasoning": true,
          "tool_call": true
        },
        "deepseek-v4.1-flash": {
          "name": "DeepSeek V4.1 Flash",
          "limit": { "context": 1048576, "output": 32000 },
          "reasoning": true,
          "tool_call": true,
          "modalities": { "input": ["text", "image"] }
        },
        "qwen3.6": {
          "name": "Qwen3.6-35B-A3B",
          "limit": { "context": 262144, "output": 32000 },
          "reasoning": true,
          "tool_call": true,
          "modalities": { "input": ["text", "image"] }
        },
        "nemotron3-super": {
          "name": "Nemotron 3 Super",
          "limit": { "context": 262144, "output": 32000 },
          "reasoning": true,
          "tool_call": true
        },
        "kimi-k3": {
          "name": "Kimi K3",
          "limit": { "context": 1048576, "output": 32000 },
          "reasoning": true,
          "tool_call": true,
          "modalities": { "input": ["text", "image"] }
        },
        "qwen3.8-flash": {
          "name": "Qwen3.8 Flash",
          "limit": { "context": 1000000, "output": 32000 },
          "reasoning": true,
          "tool_call": true,
          "modalities": { "input": ["text", "image"] }
        },
        "glm-5.3": {
          "name": "GLM-5.3",
          "limit": { "context": 1048576, "output": 32000 },
          "reasoning": true,
          "tool_call": true
        },
        "glm-5.3-flash": {
          "name": "GLM-5.3 Flash",
          "limit": { "context": 1048576, "output": 32000 },
          "reasoning": true,
          "tool_call": true,
          "modalities": { "input": ["text", "image", "video"] }
        },
        "gpt-6-luna": {
          "name": "GPT-6 Luna",
          "limit": { "context": 1050000, "output": 128000 },
          "reasoning": true,
          "tool_call": true,
          "modalities": { "input": ["text", "image"] }
        },
        "gpt-6-sol": {
          "name": "GPT-6 Sol",
          "limit": { "context": 1050000, "output": 128000 },
          "reasoning": true,
          "tool_call": true,
          "modalities": { "input": ["text", "image"] }
        },
        "claude-opus-5.5": {
          "name": "Claude Opus 5.5",
          "limit": { "context": 1000000, "output": 128000 },
          "reasoning": true,
          "tool_call": true,
          "modalities": { "input": ["text", "image"] }
        },
        "claude-fable-5.1": {
          "name": "Claude Fable 5.1",
          "limit": { "context": 262144, "output": 32000 },
          "reasoning": true,
          "tool_call": true
        },
        "deepseek-v4-pro-0813": {
          "name": "DeepSeek V4 Pro",
          "limit": { "context": 1048576, "output": 32000 },
          "reasoning": true,
          "tool_call": true
        },
        "mimo-v2.6-pro": {
          "name": "MiMo-V2.6 Pro",
          "limit": { "context": 1048576, "output": 32000 },
          "reasoning": true,
          "tool_call": true,
          "modalities": { "input": ["text", "image", "audio", "video"] }
        },
        "mimo-v2.6-flash": {
          "name": "MiMo-V2.6 Flash",
          "limit": { "context": 1048576, "output": 32000 },
          "reasoning": true,
          "tool_call": true,
          "modalities": { "input": ["text", "image", "audio", "video"] }
        },
        "minimax-m3": {
          "name": "MiniMax M3",
          "limit": { "context": 1048576, "output": 32000 },
          "reasoning": true,
          "tool_call": true,
          "modalities": { "input": ["text", "image", "video"] }
        },
        "minimax-m3-free": {
          "name": "MiniMax M3 (free)",
          "limit": { "context": 1048576, "output": 32000 },
          "reasoning": true,
          "tool_call": true,
          "modalities": { "input": ["text", "image", "video"] }
        }
      }
    }
  }
}
```

A custom provider inherits nothing from OpenCode's catalog, so each model needs its own `limit`. Undeclared `reasoning` and `tool_call` read as false. A key saved for `boundless` through `/connect` takes precedence over `apiKey`; remove it with `opencode auth logout boundless`.

```bash
opencode run --auto 'Use the bash tool to run printf boundless, then report the output.'
```

### Codex CLI

Add to `~/.codex/config.toml`. Codex requires custom providers to use the Responses wire API:

```toml
model = "deepseek-v4.1-flash"
model_provider = "boundless"
model_reasoning_effort = "low"
model_reasoning_summary = "none"

[model_providers.boundless]
name = "Boundless"
base_url = "https://api.inference.boundless.network/v1"
env_key = "BOUNDLESS_API_KEY"
wire_api = "responses"
```

```bash
export BOUNDLESS_API_KEY="YOUR_API_KEY"
codex
```

Codex compacts locally, so the provider does not need `/v1/responses/compact`.

### Codex app

The Codex desktop app reads the same `~/.codex/config.toml` as the CLI:

```toml
model = "deepseek-v4.1-flash"
model_provider = "boundless"

[model_providers.boundless]
name = "Boundless"
base_url = "https://api.inference.boundless.network/v1"
env_key = "BOUNDLESS_API_KEY"
wire_api = "responses"
```

An app started from your desktop never reads your shell profile, so put the key in `~/.codex/.env`, which every Codex process loads:

```bash
echo 'BOUNDLESS_API_KEY=YOUR_API_KEY' >> ~/.codex/.env
```

The app talks to Codex's background server, which keeps the settings it started with. After changing either file, close open Codex sessions and restart it:

```bash
codex app-server daemon restart
```

### Cursor

Settings → Models. Fill in **Override OpenAI Base URL**, put your key in **OpenAI API Key** (sent to whatever base URL you set), and add the model under **Custom models**.

```json
{
  "model": "deepseek-v4.1-flash",
  "baseURL": "https://api.inference.boundless.network/v1",
  "apiKey": "your-boundless-key"
}
```

Two things stay on Cursor's backend. Tab completion always uses a Cursor model, and Composer and Cursor's agent models refuse a custom key, so select your custom model explicitly instead of leaving the picker on Auto.

### GitHub Copilot

In VS Code, Copilot Chat reaches a custom endpoint through the **Custom Endpoint** BYOK provider. Run **Chat: Manage Language Models** from the command palette, choose Custom Endpoint, and give it the base URL and key.

In the GitHub Copilot desktop app, open **Settings → Model providers**, click **Add provider**, choose the OpenAI-compatible endpoint, and enter the same base URL and key. The provider's models then appear in the app's model picker beside GitHub's. The app needs a GitHub sign-in but no Copilot plan when you bring your own provider.

For the CLI:

```bash
export COPILOT_PROVIDER_BASE_URL="https://api.inference.boundless.network/v1"
export COPILOT_PROVIDER_API_KEY="your-boundless-key"
export COPILOT_MODEL="deepseek-v4.1-flash"
```

- BYOK covers chat and agent sessions only. Inline suggestions keep using Copilot's models.
- On Business/Enterprise, an admin must enable "Bring Your Own Language Model Key in VS Code" first. The desktop app needs the Copilot CLI enabled in policy settings.
- Provider support in the desktop app is a public preview.
- If the model list fails to load, the base URL is wrong. It has to end at `/v1`.

### JetBrains AI & Junie

AI Assistant's chat takes an OpenAI-compatible provider. Open **Settings | Tools | AI Assistant | Providers & API keys**, add an OpenAI-compatible provider under **Third-party AI providers**, and give it the base URL and key:

```yaml
url: https://api.inference.boundless.network/v1
api_key: your-boundless-key
```

Turn on **Tool calling**, then click **Test Connection** and **Apply**. The models appear in the AI Chat model picker, and **Models Assignment** can put one on the other AI Assistant features. Code completion does not use this provider.

Junie inside the IDE only runs on a JetBrains AI subscription, so it cannot use this provider. The Junie CLI can. Save a profile as `~/.junie/models/boundless.json`:

```json
{
  "displayName": "Boundless",
  "baseUrl": "https://api.inference.boundless.network/v1/chat/completions",
  "apiType": "OpenAICompletion",
  "apiKey": "${BOUNDLESS_API_KEY}",
  "id": "deepseek-v4.1-flash",
  "maxContextLength": 1048576,
  "fasterModel": { "id": "dsv4" }
}
```

`baseUrl` is the full chat-completions URL, because Junie does not append a path to it. `fasterModel` handles summaries and other helper work. The file name is the profile id:

```bash
export BOUNDLESS_API_KEY="YOUR_API_KEY"
junie --model custom:boundless
```

### OpenHands

The model name carries its own routing prefix. In `config.toml`:

```toml
[llm]
model = "openai/deepseek-v4.1-flash"
base_url = "https://api.inference.boundless.network/v1"
api_key = "your-boundless-key"
```

Leave off the `openai/` prefix and the run fails before reaching us.

### Cline

Choose **OpenAI Compatible** as the API provider:

```yaml
base_url: https://api.inference.boundless.network/v1
api_key: your-boundless-key
model_id: deepseek-v4.1-flash
```

Cline's **Model Configuration** panel sets context window and max output tokens. Its defaults are conservative; the [model lineup](/models) has the real values.

### Mastra

An OpenAI-compatible provider from the AI SDK:

```typescript
import { Agent } from "@mastra/core/agent";
import { createOpenAICompatible } from "@ai-sdk/openai-compatible";

const boundless = createOpenAICompatible({
  name: "boundless",
  baseURL: "https://api.inference.boundless.network/v1",
  apiKey: process.env.BOUNDLESS_API_KEY,
});

export const assistant = new Agent({
  name: "assistant",
  instructions: "You are a helpful coding assistant.",
  model: boundless("deepseek-v4.1-flash"),
});
```

Keep `@ai-sdk/openai-compatible` on the same AI SDK major version as `@mastra/core`.

### OpenClaw

A custom provider in `~/.openclaw/openclaw.json`. The gateway is declared once under `models.providers`, and the agent's default model names it by prefix:

```json
{
  "agents": {
    "defaults": {
      "model": {
        "primary": "boundless/deepseek-v4.1-flash"
      }
    }
  },
  "models": {
    "providers": {
      "boundless": {
        "baseUrl": "https://api.inference.boundless.network/v1",
        "apiKey": "${BOUNDLESS_API_KEY}",
        "api": "openai-completions",
        "models": [
          {
            "id": "dsv4",
            "name": "DeepSeek V4 Flash",
            "reasoning": true,
            "contextWindow": 1048576,
            "maxTokens": 32000
          },
          {
            "id": "deepseek-v4.1-flash",
            "name": "DeepSeek V4.1 Flash",
            "reasoning": true,
            "contextWindow": 1048576,
            "maxTokens": 32000
          },
          {
            "id": "qwen3.6",
            "name": "Qwen3.6-35B-A3B",
            "reasoning": true,
            "contextWindow": 262144,
            "maxTokens": 32000
          },
          {
            "id": "nemotron3-super",
            "name": "Nemotron 3 Super",
            "reasoning": true,
            "contextWindow": 262144,
            "maxTokens": 32000
          },
          {
            "id": "kimi-k3",
            "name": "Kimi K3",
            "reasoning": true,
            "contextWindow": 1048576,
            "maxTokens": 32000
          },
          {
            "id": "qwen3.8-flash",
            "name": "Qwen3.8 Flash",
            "reasoning": true,
            "contextWindow": 1000000,
            "maxTokens": 32000
          },
          {
            "id": "glm-5.3",
            "name": "GLM-5.3",
            "reasoning": true,
            "contextWindow": 1048576,
            "maxTokens": 32000
          },
          {
            "id": "glm-5.3-flash",
            "name": "GLM-5.3 Flash",
            "reasoning": true,
            "contextWindow": 1048576,
            "maxTokens": 32000
          },
          {
            "id": "gpt-6-luna",
            "name": "GPT-6 Luna",
            "reasoning": true,
            "contextWindow": 1050000,
            "maxTokens": 128000
          },
          {
            "id": "gpt-6-sol",
            "name": "GPT-6 Sol",
            "reasoning": true,
            "contextWindow": 1050000,
            "maxTokens": 128000
          },
          {
            "id": "claude-opus-5.5",
            "name": "Claude Opus 5.5",
            "reasoning": true,
            "contextWindow": 1000000,
            "maxTokens": 128000
          },
          {
            "id": "claude-fable-5.1",
            "name": "Claude Fable 5.1",
            "reasoning": true,
            "contextWindow": 262144,
            "maxTokens": 32000
          },
          {
            "id": "deepseek-v4-pro-0813",
            "name": "DeepSeek V4 Pro",
            "reasoning": true,
            "contextWindow": 1048576,
            "maxTokens": 32000
          },
          {
            "id": "mimo-v2.6-pro",
            "name": "MiMo-V2.6 Pro",
            "reasoning": true,
            "contextWindow": 1048576,
            "maxTokens": 32000
          },
          {
            "id": "mimo-v2.6-flash",
            "name": "MiMo-V2.6 Flash",
            "reasoning": true,
            "contextWindow": 1048576,
            "maxTokens": 32000
          },
          {
            "id": "minimax-m3",
            "name": "MiniMax M3",
            "reasoning": true,
            "contextWindow": 1048576,
            "maxTokens": 32000
          },
          {
            "id": "minimax-m3-free",
            "name": "MiniMax M3 (free)",
            "reasoning": true,
            "contextWindow": 1048576,
            "maxTokens": 32000
          }
        ]
      }
    }
  }
}
```

`apiKey` takes an environment variable in `${...}` form, so the key stays out of the file. Declare every model you want OpenClaw to switch between in `models`, because it has no catalog of ours to fall back on. `utilityModel` and `fallbacks` under `agents.defaults` take the same `boundless/<id>` spelling.

The gateway runs as a background service that never reads your shell profile, so put the key in `~/.openclaw/.env`, which OpenClaw loads in every process, then restart the gateway:

```bash
echo 'BOUNDLESS_API_KEY=YOUR_API_KEY' >> ~/.openclaw/.env
openclaw gateway restart
```

### Kilo Code

Kilo's CLI and extension share one config, `kilo.jsonc` in your project or `~/.config/kilo/kilo.jsonc`. It is OpenCode's format with Kilo's schema:

```json
{
  "$schema": "https://app.kilo.ai/config.json",
  "model": "boundless/deepseek-v4.1-flash",
  "small_model": "boundless/dsv4",
  "provider": {
    "boundless": {
      "npm": "@ai-sdk/openai-compatible",
      "name": "Boundless",
      "options": {
        "baseURL": "https://api.inference.boundless.network/v1",
        "apiKey": "{env:BOUNDLESS_API_KEY}"
      },
      "models": {
        "dsv4": {
          "name": "DeepSeek V4 Flash",
          "limit": {
            "context": 1048576,
            "output": 32000
          },
          "reasoning": true,
          "tool_call": true
        },
        "deepseek-v4.1-flash": {
          "name": "DeepSeek V4.1 Flash",
          "limit": {
            "context": 1048576,
            "output": 32000
          },
          "reasoning": true,
          "tool_call": true,
          "modalities": {
            "input": [
              "text",
              "image"
            ]
          }
        },
        "qwen3.6": {
          "name": "Qwen3.6-35B-A3B",
          "limit": {
            "context": 262144,
            "output": 32000
          },
          "reasoning": true,
          "tool_call": true,
          "modalities": {
            "input": [
              "text",
              "image"
            ]
          }
        },
        "nemotron3-super": {
          "name": "Nemotron 3 Super",
          "limit": {
            "context": 262144,
            "output": 32000
          },
          "reasoning": true,
          "tool_call": true
        },
        "kimi-k3": {
          "name": "Kimi K3",
          "limit": {
            "context": 1048576,
            "output": 32000
          },
          "reasoning": true,
          "tool_call": true,
          "modalities": {
            "input": [
              "text",
              "image"
            ]
          }
        },
        "qwen3.8-flash": {
          "name": "Qwen3.8 Flash",
          "limit": {
            "context": 1000000,
            "output": 32000
          },
          "reasoning": true,
          "tool_call": true,
          "modalities": {
            "input": [
              "text",
              "image"
            ]
          }
        },
        "glm-5.3": {
          "name": "GLM-5.3",
          "limit": {
            "context": 1048576,
            "output": 32000
          },
          "reasoning": true,
          "tool_call": true
        },
        "glm-5.3-flash": {
          "name": "GLM-5.3 Flash",
          "limit": {
            "context": 1048576,
            "output": 32000
          },
          "reasoning": true,
          "tool_call": true,
          "modalities": {
            "input": [
              "text",
              "image",
              "video"
            ]
          }
        },
        "gpt-6-luna": {
          "name": "GPT-6 Luna",
          "limit": {
            "context": 1050000,
            "output": 128000
          },
          "reasoning": true,
          "tool_call": true,
          "modalities": {
            "input": [
              "text",
              "image"
            ]
          }
        },
        "gpt-6-sol": {
          "name": "GPT-6 Sol",
          "limit": {
            "context": 1050000,
            "output": 128000
          },
          "reasoning": true,
          "tool_call": true,
          "modalities": {
            "input": [
              "text",
              "image"
            ]
          }
        },
        "claude-opus-5.5": {
          "name": "Claude Opus 5.5",
          "limit": {
            "context": 1000000,
            "output": 128000
          },
          "reasoning": true,
          "tool_call": true,
          "modalities": {
            "input": [
              "text",
              "image"
            ]
          }
        },
        "claude-fable-5.1": {
          "name": "Claude Fable 5.1",
          "limit": {
            "context": 262144,
            "output": 32000
          },
          "reasoning": true,
          "tool_call": true
        },
        "deepseek-v4-pro-0813": {
          "name": "DeepSeek V4 Pro",
          "limit": {
            "context": 1048576,
            "output": 32000
          },
          "reasoning": true,
          "tool_call": true
        },
        "mimo-v2.6-pro": {
          "name": "MiMo-V2.6 Pro",
          "limit": {
            "context": 1048576,
            "output": 32000
          },
          "reasoning": true,
          "tool_call": true,
          "modalities": {
            "input": [
              "text",
              "image",
              "audio",
              "video"
            ]
          }
        },
        "mimo-v2.6-flash": {
          "name": "MiMo-V2.6 Flash",
          "limit": {
            "context": 1048576,
            "output": 32000
          },
          "reasoning": true,
          "tool_call": true,
          "modalities": {
            "input": [
              "text",
              "image",
              "audio",
              "video"
            ]
          }
        },
        "minimax-m3": {
          "name": "MiniMax M3",
          "limit": {
            "context": 1048576,
            "output": 32000
          },
          "reasoning": true,
          "tool_call": true,
          "modalities": {
            "input": [
              "text",
              "image",
              "video"
            ]
          }
        },
        "minimax-m3-free": {
          "name": "MiniMax M3 (free)",
          "limit": {
            "context": 1048576,
            "output": 32000
          },
          "reasoning": true,
          "tool_call": true,
          "modalities": {
            "input": [
              "text",
              "image",
              "video"
            ]
          }
        }
      }
    }
  }
}
```

`small_model` is what Kilo uses for session titles, commit messages and prompt enhancement. Leave it unset while signed in to Kilo's own gateway and those go there instead. In the extension the same provider can be added by hand: **Settings → Providers → Custom provider**, with Provider API left on **OpenAI Compatible**.

### Cherry Studio

**Settings → Model Provider → Add Provider**, endpoint type **OpenAI**:

```yaml
api_address: https://api.inference.boundless.network
api_key: your-boundless-key
model: deepseek-v4.1-flash
```

Enter the API address without `/v1`. Cherry appends the version path itself, so pasting `/v1` doubles it. It leaves a host alone if the host already carries a version path or ends in `#`.

Saving the provider opens a setup wizard: it takes the key, then lists what `GET /v1/models` returns under **Choose models**. Select all of them so the whole lineup appears in every picker; the model above is only the one to start on. **Verify and enable** makes one request against a selected model and switches the provider on; skip that check and the provider stays off until you enable it by hand.

Only chat follows this provider. **Settings → Default Model** holds **Default Assistant Model** and **Quick Model** (used for conversation naming and keyword extraction), and translation keeps its own model in the translate panel. Point all three at a model here, or they go on asking for a provider you have not configured.

Cherry Studio 2.x keeps providers, models and preferences in SQLite (`~/Library/Application Support/CherryStudio/Data/cherrystudio.sqlite` on macOS) rather than a config file, and there is no CLI. Nothing in it expands an environment variable, so the key is stored in that database as plaintext; it cannot hold a `BOUNDLESS_API_KEY` reference. Quit the app before editing the file: it holds the database open and writes back what is already in memory.

For a check without clicking, **Code Mate → Unified Gateway** hosts a local OpenAI-compatible server on `127.0.0.1:23333` that routes through the provider you just configured. `GET /v1/models` there lists your models as `<provider-id>:<model-id>`, and a chat completion with one of them exercises the whole path. It needs the app running, and its own key rather than yours.

### CodeBuddy

CodeBuddy's IDE, editor plugins and the CodeBuddy Code CLI all read `~/.codebuddy/models.json`. `url` is the full chat-completions path, not a base URL:

```json
{
  "models": [
    {
      "id": "deepseek-v4.1-flash",
      "name": "deepseek-v4.1-flash",
      "vendor": "Boundless",
      "url": "https://api.inference.boundless.network/v1/chat/completions",
      "apiKey": "${BOUNDLESS_API_KEY}",
      "maxInputTokens": 1000000,
      "maxOutputTokens": 32000,
      "supportsToolCall": true,
      "supportsReasoning": true
    }
  ],
  "availableModels": ["deepseek-v4.1-flash"]
}
```

```bash
export BOUNDLESS_API_KEY="YOUR_API_KEY"
codebuddy --model "deepseek-v4.1-flash"
```

The model appears in the IDE's picker tagged `custom`. A custom model inherits none of CodeBuddy's built-in fast and reasoning companions; If you want them, name them in `relatedModels` on the entry.

### MiMo Code

A fork of OpenCode, so the config is OpenCode's: `mimocode.jsonc` in your project or `~/.config/mimocode/mimocode.jsonc`:

```json
{
  "$schema": "https://mimo.xiaomi.com/mimocode/config.json",
  "model": "boundless/deepseek-v4.1-flash",
  "small_model": "boundless/dsv4",
  "provider": {
    "boundless": {
      "npm": "@ai-sdk/openai-compatible",
      "name": "Boundless",
      "options": {
        "baseURL": "https://api.inference.boundless.network/v1",
        "apiKey": "{env:BOUNDLESS_API_KEY}"
      },
      "models": {
        "dsv4": {
          "name": "DeepSeek V4 Flash",
          "limit": {
            "context": 1048576,
            "output": 32000
          },
          "reasoning": true,
          "tool_call": true
        },
        "deepseek-v4.1-flash": {
          "name": "DeepSeek V4.1 Flash",
          "limit": {
            "context": 1048576,
            "output": 32000
          },
          "reasoning": true,
          "tool_call": true,
          "modalities": {
            "input": [
              "text",
              "image"
            ]
          }
        },
        "qwen3.6": {
          "name": "Qwen3.6-35B-A3B",
          "limit": {
            "context": 262144,
            "output": 32000
          },
          "reasoning": true,
          "tool_call": true,
          "modalities": {
            "input": [
              "text",
              "image"
            ]
          }
        },
        "nemotron3-super": {
          "name": "Nemotron 3 Super",
          "limit": {
            "context": 262144,
            "output": 32000
          },
          "reasoning": true,
          "tool_call": true
        },
        "kimi-k3": {
          "name": "Kimi K3",
          "limit": {
            "context": 1048576,
            "output": 32000
          },
          "reasoning": true,
          "tool_call": true,
          "modalities": {
            "input": [
              "text",
              "image"
            ]
          }
        },
        "qwen3.8-flash": {
          "name": "Qwen3.8 Flash",
          "limit": {
            "context": 1000000,
            "output": 32000
          },
          "reasoning": true,
          "tool_call": true,
          "modalities": {
            "input": [
              "text",
              "image"
            ]
          }
        },
        "glm-5.3": {
          "name": "GLM-5.3",
          "limit": {
            "context": 1048576,
            "output": 32000
          },
          "reasoning": true,
          "tool_call": true
        },
        "glm-5.3-flash": {
          "name": "GLM-5.3 Flash",
          "limit": {
            "context": 1048576,
            "output": 32000
          },
          "reasoning": true,
          "tool_call": true,
          "modalities": {
            "input": [
              "text",
              "image",
              "video"
            ]
          }
        },
        "gpt-6-luna": {
          "name": "GPT-6 Luna",
          "limit": {
            "context": 1050000,
            "output": 128000
          },
          "reasoning": true,
          "tool_call": true,
          "modalities": {
            "input": [
              "text",
              "image"
            ]
          }
        },
        "gpt-6-sol": {
          "name": "GPT-6 Sol",
          "limit": {
            "context": 1050000,
            "output": 128000
          },
          "reasoning": true,
          "tool_call": true,
          "modalities": {
            "input": [
              "text",
              "image"
            ]
          }
        },
        "claude-opus-5.5": {
          "name": "Claude Opus 5.5",
          "limit": {
            "context": 1000000,
            "output": 128000
          },
          "reasoning": true,
          "tool_call": true,
          "modalities": {
            "input": [
              "text",
              "image"
            ]
          }
        },
        "claude-fable-5.1": {
          "name": "Claude Fable 5.1",
          "limit": {
            "context": 262144,
            "output": 32000
          },
          "reasoning": true,
          "tool_call": true
        },
        "deepseek-v4-pro-0813": {
          "name": "DeepSeek V4 Pro",
          "limit": {
            "context": 1048576,
            "output": 32000
          },
          "reasoning": true,
          "tool_call": true
        },
        "mimo-v2.6-pro": {
          "name": "MiMo-V2.6 Pro",
          "limit": {
            "context": 1048576,
            "output": 32000
          },
          "reasoning": true,
          "tool_call": true,
          "modalities": {
            "input": [
              "text",
              "image",
              "audio",
              "video"
            ]
          }
        },
        "mimo-v2.6-flash": {
          "name": "MiMo-V2.6 Flash",
          "limit": {
            "context": 1048576,
            "output": 32000
          },
          "reasoning": true,
          "tool_call": true,
          "modalities": {
            "input": [
              "text",
              "image",
              "audio",
              "video"
            ]
          }
        },
        "minimax-m3": {
          "name": "MiniMax M3",
          "limit": {
            "context": 1048576,
            "output": 32000
          },
          "reasoning": true,
          "tool_call": true,
          "modalities": {
            "input": [
              "text",
              "image",
              "video"
            ]
          }
        },
        "minimax-m3-free": {
          "name": "MiniMax M3 (free)",
          "limit": {
            "context": 1048576,
            "output": 32000
          },
          "reasoning": true,
          "tool_call": true,
          "modalities": {
            "input": [
              "text",
              "image",
              "video"
            ]
          }
        }
      }
    }
  }
}
```

No sign-in is needed for a custom provider. `small_model` handles titles and other light work; `mimo models` lists what the config declares.

### Qwen Code

Declare the models under `modelProviders` in `~/.qwen/settings.json` and put the key in the environment. `envKey` names the variable to read:

```json
{
  "modelProviders": {
    "openai": [
      {
        "id": "deepseek-v4.1-flash",
        "name": "deepseek-v4.1-flash",
        "envKey": "BOUNDLESS_API_KEY",
        "baseUrl": "https://api.inference.boundless.network/v1"
      }
    ]
  },
  "model": { "name": "deepseek-v4.1-flash" },
  "security": { "auth": { "selectedType": "openai" } }
}
```

`modelProviders.openai` is a list: repeat the entry once for each id from `GET https://api.inference.boundless.network/v1/models` and the whole lineup shows up in `/model`. `model.name` is then what picks the active one; leave it out and the first entry in the list wins. Give every model a distinct `id`; two entries that share an id can only be told apart by `model.baseUrl`.

```bash
export BOUNDLESS_API_KEY="YOUR_API_KEY"
qwen
```

The variable can also live in `~/.qwen/.env`. `security.auth.apiKey` and `security.auth.baseUrl` still work but are deprecated in favour of this shape; `/doctor` shows which auth is active.

### Command Code

Add a provider to `~/.commandcode/providers.json`. If the file exists, add `boundless` to its `provider` object:

```json
{
  "provider": {
    "boundless": {
      "name": "Boundless",
      "baseURL": "https://api.inference.boundless.network/v1",
      "apiKey": "$BOUNDLESS_API_KEY",
      "models": {
        "deepseek-v4.1-flash": {
          "name": "DeepSeek V4.1 Flash",
          "contextWindow": 1048576,
          "maxOutput": 32000,
          "reasoning": true
        }
      }
    }
  }
}
```

`apiKey` must be an environment variable reference; Command Code refuses a raw key in this file. Add an entry under `models` for each model you want, with its context window, since the default is 200K. A key saved for the provider through `/connect` takes precedence over the variable. Custom providers are in beta.

```bash
export BOUNDLESS_API_KEY="YOUR_API_KEY"
command-code
```

Run `/model` and pick the model under **Boundless**. Reopen `/model` after editing the file to load the change.

### Muse

Muse Code has no documented setting for another provider. The binary accepts a base URL override, and reads its key from `META_API_KEY`:

```bash
export META_API_KEY="YOUR_API_KEY"
muse --provider meta --base-url "https://api.inference.boundless.network/v1" --model "deepseek-v4.1-flash"
```

Both flags are undocumented and unverified against this gateway. If Muse rejects the host or the response shape, there is nothing more to configure here, so report it to Meta.

### Everything else

Roo Code, Continue, Aider, Zed and most other OpenAI-compatible clients take the same three values:

```yaml
base_url: https://api.inference.boundless.network/v1
api_key: your-boundless-key
model: deepseek-v4.1-flash
```

We serve `GET /v1/models`, so tools that fetch the list populate their own picker.

Two agents cannot be pointed here:

- [Devin](https://docs.devin.ai/cli/models): Devin Cloud, the Devin CLI and Devin Desktop (formerly Windsurf) choose only among models Cognition hosts, and Cognition [does not support third-party LLM API keys](https://docs.devin.ai/enterprise/deployment/overview).
- [Google Antigravity](https://antigravity.google/docs/plans): the IDE and CLI take no bring-your-own key or endpoint. The Antigravity SDK accepts an OpenAI-compatible `base_url` but sends no API key, so it cannot authenticate here either.

## When something doesn't work

Read the error body as well as the status: three different problems share HTTP 429.

| What you see | What it usually is |
| --- | --- |
| `401` on every request | Wrong header. Switch between `Authorization: Bearer` and `x-api-key`. |
| An error naming a model you never chose | The harness is sending its default. Set the model explicitly, including small/background slots. |
| Empty reply, `stop_reason: max_tokens` | The output budget has to cover thinking too. Give reasoning models 1024+. |
| `429` with `budget_exceeded` | Credits or [key budget](/docs/billing#key-budgets) reached zero. |
| `429` with rate-limit message | At one of your team's [admission caps](/docs/rate-limits). |

None of those? [Send us the model ID and a timestamp](/support).
