deCloud is an OpenAI-protocol-compatible gateway — any client that lets you set a custom base URL can use it. Here's how for the common ones.
Create an API key in the console (it starts with dcld-sk-) and make sure the account holds some MA, or calls come back 402. If a key is bound to specific models, calling an unbound model returns 403 model_not_allowed; a key that has spent its quota returns 403 quota_exhausted — raise the limit or reset usage in the console to restore it. Every client uses the same base URL:
https://macdecloud.com/v1The gateway natively serves OpenAI Chat Completions at POST /v1/chat/completions, the model catalog at GET /v1/models, Anthropic Messages for Claude Code at POST /v1/messages, and OpenAI Responses for Codex at POST /v1/responses. Configure the endpoint for the protocol your client actually speaks.
Terminal coding agent, speaks the OpenAI-compatible protocol.
Either the global ~/.config/opencode/opencode.json or an opencode.json in your project root. They merge, project wins.
{
"$schema": "https://opencode.ai/config.json",
"provider": {
"decloud": {
"npm": "@ai-sdk/openai-compatible",
"name": "deCloud",
"options": {
"baseURL": "https://macdecloud.com/v1",
"apiKey": "{env:DECLOUD_API_KEY}"
},
"models": {
"moonshotai/kimi-k3": {
"name": "Kimi K3",
"limit": { "context": 1048576, "output": 65536 }
}
}
}
}
}npm must be @ai-sdk/openai-compatible — @ai-sdk/openai targets /v1/responses, which deCloud does not serve. baseURL needs the /v1 but not /chat/completions; the SDK appends that itself. Without limit.context, opencode doesn't know how much fits and will either truncate early or overrun.
Keep the key out of the config file — a project-level opencode.json usually ends up in git.
export DECLOUD_API_KEY='dcld-sk-...'
opencode
# Or name the model directly:
opencode run -m decloud/moonshotai/kimi-k3 "reverse a string in Go"