# OpenCode
Source: https://docs.tensormachine.ai/integrations/opencode

[OpenCode](https://opencode.ai) is an open-source coding agent that runs in your terminal. It
has no built-in Tensor Machine provider, but it supports **custom OpenAI-compatible
providers** — which is exactly what our endpoint is. Adding one is a config-file change; no
plugin or fork required.

## 1. Get your endpoint and key

From the console:

- **Base URL** — *API Keys* page, OpenAI format: `https://edge.tensormachine.ai/<org>/v1`
- **Key** — *Create key*, then copy the `sk-tm-…` secret (shown once)
- **Model IDs** — *My Team → Model access*, the `tm/…` aliases

Keep the key out of the config file. Export it instead:

```bash
export TENSOR_MACHINE_API_KEY="sk-tm-..."
```

Add that line to your shell profile (`~/.zshrc`, `~/.bashrc`) so it survives new terminals.

## 2. Add the provider

OpenCode reads `opencode.json` from your project root, and falls back to
`~/.config/opencode/opencode.json` for a global config. Use the global file if you want
Tensor Machine available in every project.

```json title="~/.config/opencode/opencode.json"
{
  "$schema": "https://opencode.ai/config.json",
  "provider": {
    "tensormachine": {
      "npm": "@ai-sdk/openai-compatible",
      "name": "Tensor Machine",
      "options": {
        "baseURL": "https://edge.tensormachine.ai/<org>/v1",
        "apiKey": "{env:TENSOR_MACHINE_API_KEY}"
      },
      "models": {
        "tm/qwen3-5-9b": {
          "name": "Qwen3 5 9B"
        }
      }
    }
  }
}
```

Four things decide whether this works:

- **`npm` must be `@ai-sdk/openai-compatible`.** That package targets
  `/v1/chat/completions`, which is what our OpenAI endpoint serves. The other common choice,
  `@ai-sdk/openai`, targets `/v1/responses` and will not work here. This is the single most
  common mistake.
- **`baseURL` ends at `/v1`.** OpenCode appends `/chat/completions` itself. Adding the path
  yourself produces a doubled URL and a 404.
- **Each key under `models` is a real model ID** sent verbatim to us — use the `tm/…` alias
  from *Model access*, not a display name. The `name` field is only the label in the picker.
- **`{env:…}` reads an environment variable.** If the variable isn't set, OpenCode
  substitutes an empty string rather than erroring, so a missing key surfaces later as a
  `401` — check the export first when you see one.

Add more models by adding more entries under `models`.

## 3. Select the model

Start OpenCode and run `/models`, then pick the Tensor Machine entry. To make it the default,
set the `model` key to `<provider>/<model-id>`:

```json title="~/.config/opencode/opencode.json"
{
  "model": "tensormachine/tm/qwen3-5-9b"
}
```

The provider part (`tensormachine`) is your key from the `provider` block; the rest is the
model ID. Both slashes are expected — the model ID contains one of its own.

## 4. Verify

Ask it something trivial and confirm the answer comes back:

```bash
opencode run "reply with the word: connected"
```

Then check the console: *Usage* should show the request against your team, and your balance
should have moved. If the request never reaches us, the problem is local (base URL, key, or
`npm` package) rather than a workspace setting.

## Optional: declare context limits

OpenCode tracks how much context you have left. For built-in providers it pulls those figures
automatically; for a custom provider it only knows what you declare:

```json
"models": {
  "tm/qwen3-5-9b": {
    "name": "Qwen3 5 9B",
    "limit": { "context": 32768, "output": 4096 }
  }
}
```

Set these to the real context window and max output of the model you chose — they're on the
model's card in *Model access*. The values above are placeholders, not the values for any
particular model. Getting them wrong doesn't break requests; it makes OpenCode's
remaining-context estimate wrong, so it compacts at the wrong time.

## Troubleshooting

| What you see | Usual cause |
| --- | --- |
| `401` on every request | `TENSOR_MACHINE_API_KEY` not exported in the shell that launched OpenCode, or the key was revoked or rotated |
| `402` / a payment-required error | Workspace balance is ₹0, or a spend limit is exhausted — *Billing → Add funds* |
| `403` naming the model | The model isn't in your team's allow-list — *My Team → Model access* |
| `404` on the request path | `baseURL` includes `/chat/completions`, or is missing `/v1` |
| Model missing from `/models` | The provider block didn't load — check the JSON parses and the provider key matches what you put in `model` |
| Connects, but never edits files | A model-capability problem, not a config one — try another model from your allow-list |

## What we've verified

The configuration above follows OpenCode's documented custom-provider format, and the
endpoint, auth scheme and error codes it relies on are the ones our API serves and are
covered by our own tests. We have not published a certification of any particular model's
performance as a coding agent — which model to use is a judgement call, and the
[Models](/models) page is the place to compare.
