Skip to main content

How do you use DeepSeek V4.1 Flash and Kimi K3 in opencode through a custom OpenAI-compatible provider?

One provider block in opencode.json, four exact model IDs, a sanity check from the openai package, and the fixes for the errors you are likely to hit

Updated 7 min readMarkdown
How do you use DeepSeek V4.1 Flash and Kimi K3 in opencode through a custom OpenAI-compatible provider?

Adapted from our opencode custom-provider tutorial on dev.to.

How do you use DeepSeek V4.1 Flash and Kimi K3 in opencode through a custom OpenAI-compatible provider?

You add a provider block to opencode.json that uses the @ai-sdk/openai-compatible package, set its baseURL to https://cloudgpu.app/v1, read the key from {env:CGW_API_KEY}, and list deepseek-v4.1-flash and kimi-k3 under models; opencode then offers them as cloudgpu/deepseek-v4.1-flash and cloudgpu/kimi-k3.

The rest of this post is the copy-paste version of that sentence, with each opencode behaviour traced to the opencode docs.

Disclosure: I work on CloudGPU.

What this is based on

We ran this provider block in opencode on 2026-10-26 and both headline models replied. Everything else below about opencode itself (the /models screen, /connect, the limit block, the default model) follows the opencode docs, so read "according to the opencode docs" literally.

The four values at a glance

What Value
npm package @ai-sdk/openai-compatible
Base URL https://cloudgpu.app/v1 (keep the /v1)
API key a cgw-sk-... key, exported as CGW_API_KEY
Model IDs deepseek-v4.1-flash, kimi-k3, kimi-k2.6, glm-5.3-flash

The model IDs were checked against the model table on the live API page on 2026-10-27.

Step 1: Export the key

According to the opencode docs, config files support {env:VARIABLE_NAME} substitution, so the key can stay out of the JSON file:

export CGW_API_KEY="cgw-sk-..."   # put this in ~/.bashrc or ~/.zshrc to keep it

Step 2: Add the custom provider to opencode.json

Put this in opencode.json in your project root. According to the opencode docs, the global file lives at ~/.config/opencode/opencode.json, the project file overrides it, and "configuration files are merged together, not replaced", so the same block also works globally.

{
  "$schema": "https://opencode.ai/config.json",
  "provider": {
    "cloudgpu": {
      "npm": "@ai-sdk/openai-compatible",
      "name": "CloudGPU",
      "options": {
        "baseURL": "https://cloudgpu.app/v1",
        "apiKey": "{env:CGW_API_KEY}"
      },
      "models": {
        "deepseek-v4.1-flash": { "name": "DeepSeek V4.1 Flash" },
        "kimi-k3": { "name": "Kimi K3" },
        "kimi-k2.6": { "name": "Kimi K2.6" },
        "glm-5.3-flash": { "name": "GLM-5.3 Flash" }
      }
    }
  }
}

Field guide, according to the opencode docs (Providers → Custom provider):

  • cloudgpu is the provider ID. You choose it, and it becomes the prefix in cloudgpu/<model>.
  • npm: "@ai-sdk/openai-compatible for OpenAI-compatible providers (for /v1/chat/completions)".
  • options.baseURL is the API endpoint; options.apiKey is optional "if not using auth".
  • models: each key must be the exact ID the endpoint serves. name is only the label in the UI.

Only want the two headline models? Delete the kimi-k2.6 and glm-5.3-flash lines.

Alternative: /connect instead of apiKey

According to the opencode docs, you can run /connect, scroll to Other, enter the provider ID (cloudgpu), and paste the key. The docs warn that this "only stores a credential", so you still need the provider block, just without the apiKey line.

Step 3: Choose a model

Check from the command line that opencode sees the provider. According to the opencode CLI docs, opencode models [provider] lists models in provider/model form:

opencode models cloudgpu

The output should look like this (illustrative, not a captured run):

cloudgpu/deepseek-v4.1-flash
cloudgpu/glm-5.3-flash
cloudgpu/kimi-k2.6
cloudgpu/kimi-k3

Then pick one with -m in provider/model form. The dot in v4.1 is part of the ID:

opencode -m cloudgpu/deepseek-v4.1-flash
opencode run -m cloudgpu/kimi-k3 "Explain what this repo's main entry point does"

Inside the TUI, according to the opencode docs, you "run the /models command and your custom provider and models will appear in the selection list". To make one the default, the opencode models docs use a top-level "model" key in provider_id/model_id form, here "model": "cloudgpu/deepseek-v4.1-flash".

Which one for what? There are no benchmarks here, so try them on your own repo. All four are in the config, so comparing them takes one switch.

Step 4: Sanity-check the endpoint outside opencode

If opencode misbehaves, take it out of the loop. First, list the IDs your key can use:

curl https://cloudgpu.app/v1/models \
  -H "Authorization: Bearer $CGW_API_KEY"

Without the header this returns 401 with missing_authorization, which is expected. The API docs list it as "No Authorization header." (As of 2026-10-27, see /api/docs.)

Then send one chat request with the openai Python package:

# pip install openai
import os
from openai import OpenAI

client = OpenAI(
    base_url="https://cloudgpu.app/v1",
    api_key=os.environ["CGW_API_KEY"],
)

for model in ["deepseek-v4.1-flash", "kimi-k3"]:
    resp = client.chat.completions.create(
        model=model,
        messages=[{"role": "user", "content": "Reply with: ok"}],
    )
    print(model, resp.choices[0].finish_reason, repr(resp.choices[0].message.content))

If a model comes back with empty or None content and finish_reason is "length", the reply ran out of output tokens: leave max_tokens unset or set it higher.

Troubleshooting

1. The model doesn't show up, or you get 400 model_not_found. The keys under models must match the IDs from GET /v1/models character for character. Watch for short aliases (deepseek-flash), a missing version segment (deepseek-v4-flash vs deepseek-v4.1-flash) and capital letters. Also check that the provider ID is the same in all three places: the provider key, the ID typed into /connect (if you used it), and the cloudgpu/ prefix. According to the opencode docs, opencode auth list shows which credentials are stored.

2. The base URL is wrong. The AI SDK docs describe baseURL as the URL prefix for API calls, and their example sends chat requests to <baseURL>/chat/completions:

https://cloudgpu.app/v1                     correct
https://cloudgpu.app                        missing /v1
https://cloudgpu.app/v1/chat/completions    too specific

3. An error asking for an Authorization: Bearer header. According to the opencode docs, an unset {env:...} variable "will be replaced with an empty string", so the request goes out without a key. Check the variable in the shell you launch opencode from:

echo "${CGW_API_KEY:+set}"   # prints "set" if the variable is present

After editing ~/.bashrc or ~/.zshrc, open a new terminal or source the file. IDE terminals and desktop launchers may not read your shell profile.

4. Empty replies. Check finish_reason as in Step 4. In opencode, the per-model knob the docs describe is the optional limit block (limit.context = "maximum input tokens the model accepts", limit.output = "maximum tokens the model can generate"). If you add it, use real values from the model provider's docs, not guesses.

5. 401 invalid_api_key, 402 insufficient_balance or 429 rate_limit_exceeded. The CloudGPU API docs describe them like this (As of 2026-10-27, see /api/docs):

  • 401 invalid_api_key: "Key unknown or revoked."
  • 402 insufficient_balance: "Top up."
  • 429 rate_limit_exceeded: "Per-minute or per-day limit hit."

The documented rate limits are "Per API key, per minute: 100 requests" and "Per account, per day: 10,000 requests", and the docs add: "These defaults exist to stop abuse during the public beta. Contact us if you need them raised — happy to do it for any genuine workload, just need to know the use case."

Paying for it

Usage is billed per token from a prepaid balance (card, Alipay, Google Pay, Apple Pay or USDT). Keys, the model table and per-model rates are on the CloudGPU API page.

FAQ

Which npm package does an OpenAI-compatible custom provider use in opencode? @ai-sdk/openai-compatible. According to the opencode docs, it's the package for providers that use /v1/chat/completions.

What base URL goes in options.baseURL? https://cloudgpu.app/v1, with /v1 and nothing after it.

Can the model ID contain a dot, like deepseek-v4.1-flash? Yes. Use it exactly as listed, in provider/model form: -m cloudgpu/deepseek-v4.1-flash.

Why does a model sometimes return an empty answer? Check finish_reason. If it is "length", the reply ran out of output tokens; raise max_tokens or leave it unset.

Do I have to put the API key in opencode.json? No. Use "apiKey": "{env:CGW_API_KEY}" so the file only holds a reference. According to the opencode docs, /connect can store the credential instead.

Are there rate limits? Yes. The API docs list "Per API key, per minute: 100 requests" and "Per account, per day: 10,000 requests", and say: "These defaults exist to stop abuse during the public beta. Contact us if you need them raised — happy to do it for any genuine workload, just need to know the use case." As of 2026-10-27, see /api/docs.

No comments yet. Be the first to comment.