OpenCode is an open-source terminal coding agent built on the AI SDK provider packages. It connects to Tokens through @ai-sdk/openai-compatible, which sends chat completions to https://tokens.bd/v1.
Quick setup with the Tokens CLI#
The Tokens CLI signs you in through the browser, creates a key, lets you pick a default model and adds a tokens provider to OpenCode. It needs Node 18 or newer.
curl -fsSL https://tokens.bd/cli/tokens.mjs -o tokens.mjs && node tokens.mjs setup --base-url https://tokens.bd --agents opencodeiwr https://tokens.bd/cli/tokens.mjs -OutFile tokens.mjs; node tokens.mjs setup --base-url https://tokens.bd --agents opencodeIt merges the provider into ~/.config/opencode/opencode.json, sets "model": "tokens/<your model>", and backs up the old file as opencode.json.tokens-backup-<timestamp>. Two things to know:
- The key is written into the file as
options.apiKey. That's fine for a file in your home folder; don't copy it into a repository. - It doesn't set
limiton the model. Add real context and output limits afterwards (see below), or OpenCode can't compact long sessions properly.
If your opencode.json contains comments, the CLI won't risk rewriting it and points you to /dashboard/connect for the snippet instead.
Configure opencode.json manually#
Install OpenCode if you haven't:
curl -fsSL https://opencode.ai/install | bash
# or
npm install -g opencode-aiExport your key (API keys explains how to create one with a spend cap):
export TOKENS_API_KEY="tok_live_your_key"$env:TOKENS_API_KEY = "tok_live_your_key" # this window
setx TOKENS_API_KEY "tok_live_your_key" # new windowsThen add the provider. The global file is ~/.config/opencode/opencode.json; a project can also have its own opencode.json in the repo root, and OPENCODE_CONFIG points at a custom path. OpenCode merges these files rather than replacing one with another.
{
"$schema": "https://opencode.ai/config.json",
"provider": {
"tokens": {
"npm": "@ai-sdk/openai-compatible",
"name": "Tokens",
"options": {
"baseURL": "https://tokens.bd/v1",
"apiKey": "{env:TOKENS_API_KEY}"
},
"models": {
"deepseek/deepseek-v4.1-flash": {
"name": "DeepSeek V4.1 Flash",
"limit": { "context": 128000, "output": 8192 }
}
}
}
},
"model": "tokens/deepseek/deepseek-v4.1-flash"
}{env:TOKENS_API_KEY} makes OpenCode read the key from the environment, so the file is safe to commit. The limit numbers are placeholders: copy the real context window and max output for the model from its page in /models.
The model reference is provider_id/model_id. Our model ids already contain a slash, so the full reference becomes tokens/deepseek/deepseek-v4.1-flash.
Generate the config#
Pick a model and this generator fills in the provider block for you:
{
"provider": {
"tokens": {
"npm": "@ai-sdk/openai-compatible",
"options": {
"baseURL": "https://tokens.bd/v1",
"apiKey": "tok_live_your_key"
},
"models": {
"deepseek/deepseek-v4.1-flash": {}
}
}
}
}Project or global configuration for OpenCode CLI / IDE agent.
{
"env": {
"ANTHROPIC_BASE_URL": "https://tokens.bd",
"ANTHROPIC_AUTH_TOKEN": "tok_live_your_key",
"ANTHROPIC_MODEL": "deepseek/deepseek-v4.1-flash"
}
}Configure Claude Code CLI via ~/.claude/settings.json or environment exports.
# ~/.codex/config.toml model = "deepseek/deepseek-v4.1-flash" model_provider = "tokens" [model_providers.tokens] name = "Tokens" base_url = "https://tokens.bd/v1" env_key = "TOKENS_API_KEY" wire_api = "responses" # In your shell profile (~/.bashrc, ~/.zshrc): export TOKENS_API_KEY="tok_live_your_key"
Add a custom model provider to ~/.codex/config.toml and export the key in your shell.
export OPENAI_API_BASE="https://tokens.bd/v1" export OPENAI_API_KEY="tok_live_your_key" aider --model openai/deepseek/deepseek-v4.1-flash
Run Aider terminal pair programmer against the Tokens gateway.
from openai import OpenAI
client = OpenAI(
base_url="https://tokens.bd/v1",
api_key="tok_live_your_key",
)
response = client.chat.completions.create(
model="deepseek/deepseek-v4.1-flash",
messages=[
{"role": "system", "content": "You are an expert coding assistant."},
{"role": "user", "content": "Write a quick hello world in Python"},
],
temperature=0.7,
)
print(response.choices[0].message.content)Official OpenAI Python library pointing to Tokens endpoint.
import OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://tokens.bd/v1",
apiKey: "tok_live_your_key",
});
async function main() {
const response = await client.chat.completions.create({
model: "deepseek/deepseek-v4.1-flash",
messages: [
{ role: "system", content: "You are an expert coding assistant." },
{ role: "user", content: "Write a quick hello world in Python" },
],
temperature: 0.7,
});
console.log(response.choices[0]?.message?.content);
}
main().catch(console.error);Official OpenAI Node.js SDK pointing to Tokens endpoint.
curl -X POST "https://tokens.bd/v1/chat/completions" \
-H "Authorization: Bearer tok_live_your_key" \
-H "Content-Type: application/json" \
-d '{
"model": "deepseek/deepseek-v4.1-flash",
"messages": [
{"role": "system", "content": "You are an expert coding assistant."},
{"role": "user", "content": "Write a quick hello world in Python"}
],
"temperature": 0.7
}'Raw HTTP POST request to OpenAI-compatible chat completions.
Store the key with /connect instead#
You can also keep the key out of the environment: run /connect in the OpenCode TUI, choose "Other", enter the provider id tokens and paste the key. OpenCode stores it in ~/.local/share/opencode/auth.json. The provider id must match the one in your config, and you can then drop apiKey from options.
Switch models#
Add more entries under provider.tokens.models, one per model id from /models or GET /v1/models:
"models": {
"deepseek/deepseek-v4.1-flash": { "name": "DeepSeek V4.1 Flash", "limit": { "context": 128000, "output": 8192 } },
"moonshotai/kimi-k3": { "name": "Kimi K3", "limit": { "context": 128000, "output": 8192 } }
}The second id is an example; check the exact id in /models. Then switch in the TUI with /models, change the top-level model, or pass --model for a single run. small_model takes the same tokens/... form if you want a cheaper model for OpenCode's lightweight tasks. Choosing a model helps with the choice.
Verify it works#
opencode models tokens
opencode run --model tokens/deepseek/deepseek-v4.1-flash "Reply with OK"The first command should list your Tokens models; the second should print a short answer. In the TUI, /models shows the same list.
Troubleshooting#
401 missing_api_key. {env:TOKENS_API_KEY} resolved to an empty string because the variable isn't set in the shell that started OpenCode. After setx on Windows, open a new terminal.
The model isn't listed, or you get 404 model_not_found. Check that the key under models matches the Tokens id exactly and that model is tokens/ followed by that id. OpenCode's docs don't explicitly cover model ids that contain a slash; the pattern is the same one OpenRouter-style ids use, so a typo is the more likely cause.
Wrong package. Use @ai-sdk/openai-compatible, which speaks chat completions. @ai-sdk/openai targets the Responses API, which not every upstream supports (see Responses API).
Long sessions fail instead of compacting. Set limit.context and limit.output to the model's real values.
/connect key ignored. The provider id you typed in /connect must be exactly tokens.
The CLI skipped OpenCode. Your file has comments or invalid JSON. Copy the block above in by hand.
For 402, 403 and 429 errors, see Troubleshooting.