DEV Community

Cover image for A Practical Guide to Running OpenCode with an OpenAI-Compatible Provider
Germey
Germey

Posted on Originally published at platform.acedata.cloud

A Practical Guide to Running OpenCode with an OpenAI-Compatible Provider

If you use a terminal coding agent every day, one practical problem shows up quickly: how do you keep model access reproducible, project-friendly, and easy to verify without changing the way you work?

OpenCode + Ace Data Cloud cover

OpenCode is a terminal-first coding agent from the SST team. It can read code, modify files, run commands, explain errors, and help with day-to-day development tasks from your shell. The useful part for builders is that OpenCode supports custom model providers, so you can point it at an OpenAI-compatible endpoint while keeping the normal opencode command and TUI workflow.

This guide walks through configuring OpenCode to use Ace Data Cloud as a custom provider through its OpenAI Chat Completions-compatible proxy.

What you can do

After the setup, your workflow stays familiar:

  • run opencode inside a project and choose a model from /models
  • run one-off tasks with opencode run
  • keep your API token out of the JSON config by using an environment variable
  • expose only the model IDs you want OpenCode to use
  • use either a global config or a project-level config depending on the repository

The key values from the source guide are:

  • Base URL: https://api.acedata.cloud/v1
  • Chat Completions endpoint used under the hood: https://api.acedata.cloud/v1/chat/completions
  • Provider key used in the example: provider.acedatacloud
  • API token environment variable: ACEDATACLOUD_API_KEY
  • Authorization format: Authorization: Bearer <token>
  • Model name format in OpenCode: acedatacloud/<model>

How it works

OpenCode reads opencode.json at startup. The documented load order is:

  1. global config: ~/.config/opencode/opencode.json
  2. a custom config file pointed to by OPENCODE_CONFIG
  3. project config: opencode.json in the project root, up to the Git root

Later config overrides earlier config. That makes it reasonable to keep a safe global provider definition and still customize models for a specific repository.

For this integration, OpenCode uses the Vercel AI SDK adapter @ai-sdk/openai-compatible. When you select a model such as acedatacloud/gpt-5-mini, OpenCode resolves the acedatacloud provider block, reads options.baseURL, resolves {env:ACEDATACLOUD_API_KEY}, and sends an OpenAI Chat Completions-format request to /v1/chat/completions with a bearer token.

No local proxy process is required. No wrapper CLI is required. You still run OpenCode normally; the configuration changes only the underlying API target and model list.

Install OpenCode

OpenCode supports macOS, Linux, Windows, and WSL. On macOS, Linux, or WSL, the guide lists this one-line installer:

curl -fsSL https://opencode.ai/install | bash
Enter fullscreen mode Exit fullscreen mode

If you prefer package managers, the documented alternatives are:

brew install sst/tap/opencode
npm install -g opencode-ai
Enter fullscreen mode Exit fullscreen mode

On Windows, you can use:

winget install sst.opencode
Enter fullscreen mode Exit fullscreen mode

After installing, reopen your terminal and verify the command is available:

opencode --version
Enter fullscreen mode Exit fullscreen mode

If you see command not found, the current shell probably has not loaded the new PATH yet. Close and reopen the terminal. On macOS with Homebrew, you can also check the binary path with which opencode.

Keep the token out of your config file

First, put your Ace Data Cloud API token into an environment variable:

export ACEDATACLOUD_API_KEY="{token}"
Enter fullscreen mode Exit fullscreen mode

Replace {token} with the token from your console. Put the line in ~/.zshrc, ~/.bashrc, or ~/.bash_profile, then reload it:

source ~/.zshrc
Enter fullscreen mode Exit fullscreen mode

A subtle issue: if your token lives in a .env file as ACEDATACLOUD_API_KEY=... without export, a plain source .env only creates a shell variable. Child processes such as OpenCode may not see it. Use this instead:

set -a && source .env && set +a
Enter fullscreen mode Exit fullscreen mode

The goal is for OpenCode to resolve {env:ACEDATACLOUD_API_KEY} when it starts.

Register Ace Data Cloud as a provider

Create the global config file if it does not exist:

mkdir -p ~/.config/opencode
touch ~/.config/opencode/opencode.json
Enter fullscreen mode Exit fullscreen mode

Then add a provider block like this:

{
  "$schema": "https://opencode.ai/config.json",
  "provider": {
    "acedatacloud": {
      "npm": "@ai-sdk/openai-compatible",
      "name": "Ace Data Cloud",
      "options": {
        "baseURL": "https://api.acedata.cloud/v1",
        "apiKey": "{env:ACEDATACLOUD_API_KEY}"
      },
      "models": {
        "claude-sonnet-4-6": { "name": "Claude Sonnet 4.6" },
        "claude-haiku-4-5-20251001": { "name": "Claude Haiku 4.5" },
        "claude-opus-4-7": { "name": "Claude Opus 4.7" },
        "gpt-5": { "name": "GPT-5" },
        "gpt-5-mini": { "name": "GPT-5 mini" },
        "gemini-2.5-pro": { "name": "Gemini 2.5 Pro" },
        "deepseek-v3.2-exp": { "name": "DeepSeek V3.2 Exp" }
      }
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

The important pieces are provider.acedatacloud as the local provider ID, @ai-sdk/openai-compatible as the adapter, https://api.acedata.cloud/v1 as the base URL, and {env:ACEDATACLOUD_API_KEY} as the token placeholder. The models object is the list OpenCode exposes under the provider.

Verify and run a smoke test

List the registered models:

opencode models acedatacloud
Enter fullscreen mode Exit fullscreen mode

With the example config, the output should include:

acedatacloud/claude-haiku-4-5-20251001
acedatacloud/claude-opus-4-7
acedatacloud/claude-sonnet-4-6
acedatacloud/deepseek-v3.2-exp
acedatacloud/gemini-2.5-pro
acedatacloud/gpt-5
acedatacloud/gpt-5-mini
Enter fullscreen mode Exit fullscreen mode

Now run a simple one-off task:

opencode run --model acedatacloud/claude-sonnet-4-6 "Reply: Hello from AceData via OpenCode."
Enter fullscreen mode Exit fullscreen mode

The documented test output is:

> build · claude-sonnet-4-6

Hello from AceData via OpenCode.
Enter fullscreen mode Exit fullscreen mode

For interactive work, move into a project and start the TUI:

cd /path/to/your/project
opencode
Enter fullscreen mode Exit fullscreen mode

Then use /models to pick a configured model.

Troubleshooting notes

If opencode models acedatacloud does not show your provider, OpenCode probably did not read the config file. Restart the TUI after edits, or run with --print-logs --log-level INFO and check which config path is loaded.

If you get 401 Unauthorized, check that ACEDATACLOUD_API_KEY is exported in the current shell. If opencode debug config shows "Authorization": "Bearer ", the placeholder resolved to an empty value.

If OpenCode reports Model not found: acedatacloud/..., make sure that model ID is present as a key under provider.acedatacloud.models.

For MCP-heavy sessions, the guide notes that OpenAI-series models such as gpt-5 or gpt-5-mini are a good first choice when many MCP tools are mounted, while Claude models work normally for plain conversation.

If you want the full reference, read the original OpenCode Terminal Setup Guide.

Top comments (1)

Collapse
 
marcusykim profile image
Marcus Kim

The distinction between a shell variable and an exported ACEDATACLOUD_API_KEY is the most operationally useful part here; seeing Authorization: Bearer in opencode debug config turns a vague 401 into a specific failure. I'd add one verification layer after opencode models acedatacloud: run a tiny request through each model you actually expose, because a locally registered ID proves the config loaded, not that the upstream route supports that model and response shape. Keeping a conservative global provider block and narrower project-level model lists also gives teams a clean tradeoff between convenience and reproducibility.