OpenCode CLI Multi-Provider Setup: Configure All AI Providers in One Place
I was tired of managing separate configurations for each AI coding assistant. Claude here, GPT there, Gemini somewhere else. Every time I wanted to switch providers, I had to remember different config file locations, different API key formats, different model names.
Then I discovered OpenCode CLI supports multiple providers in a single configuration file. But the documentation didn’t make the setup process clear, especially for combining cloud and local models.
After several hours of trial and error, I finally got it working. Here’s what I learned.
The Problem: Juggling Multiple AI Assistants
I have accounts with Anthropic, OpenAI, and Google. I also run Ollama locally for privacy-sensitive work. Each provider has its strengths:
- Claude: Best reasoning, great for complex refactoring
- GPT: Extensive tool support, reliable for simple tasks
- Gemini: Competitive pricing, good multimodal capabilities
- Ollama: Privacy, no rate limits, free after hardware costs
Switching between them was painful. Different config files, different commands, different environment variables. I wanted a unified interface.
Understanding OpenCode Provider Architecture
OpenCode CLI uses a single opencode.json configuration file. By default, it looks for this file in:
~/.opencode/opencode.json(global)./opencode.json(project-specific)
The configuration supports two types of providers:
- Built-in providers: Anthropic, OpenAI, Google Gemini, AWS Bedrock, Azure OpenAI
- OpenAI-compatible providers: Ollama, LM Studio, llama.cpp, any custom endpoint
Here’s the architecture:
┌─────────────────────────────────────────────────────────┐│ opencode.json │├─────────────────────────────────────────────────────────┤│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ││ │ Anthropic │ │ OpenAI │ │ Gemini │ ││ │ (built-in) │ │ (built-in) │ │ (built-in) │ ││ └─────────────┘ └─────────────┘ └─────────────┘ ││ ││ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ││ │ Ollama │ │ LM Studio │ │ llama.cpp │ ││ │ (compatible)│ │ (compatible)│ │ (compatible)│ ││ └─────────────┘ └─────────────┘ └─────────────┘ │└─────────────────────────────────────────────────────────┘ │ ▼ /models command or CLI flagsSetting Up Cloud Providers
Anthropic Configuration
First, I tried to add Anthropic. The API key format was confusing at first.
# Set your API key as environment variableexport ANTHROPIC_API_KEY=sk-ant-...Then in opencode.json:
{ "$schema": "https://opencode.ai/config.json", "provider": { "anthropic": { "options": { "apiKey": "{env:ANTHROPIC_API_KEY}", "timeout": 600000 } } }}The {env:VARIABLE_NAME} syntax is critical. Never hardcode API keys directly in the config file. I made that mistake initially and almost committed my key to a public repo.
For Claude models with thinking capabilities, you need additional model configuration:
{ "provider": { "anthropic": { "options": { "apiKey": "{env:ANTHROPIC_API_KEY}" }, "models": { "claude-sonnet-4-5-20250929": { "options": { "thinking": { "type": "enabled", "budgetTokens": 16000 } } } } } }}OpenAI Configuration
OpenAI setup is similar:
export OPENAI_API_KEY=sk-...{ "provider": { "openai": { "options": { "apiKey": "{env:OPENAI_API_KEY}", "baseURL": "https://api.openai.com/v1" }, "models": { "gpt-5": { "options": { "reasoningEffort": "high", "textVerbosity": "low" } } } } }}I initially forgot the baseURL and got connection errors. It’s technically optional for OpenAI, but being explicit helps when debugging.
AWS Bedrock Configuration
Bedrock was trickier because it uses IAM profiles instead of API keys:
export AWS_PROFILE=my-aws-profileexport AWS_REGION=us-east-1{ "provider": { "amazon-bedrock": { "options": { "region": "{env:AWS_REGION}", "profile": "{env:AWS_PROFILE}", "endpoint": "https://bedrock-runtime.us-east-1.vpce-xxx.amazonaws.com" } } }}The endpoint is optional but useful if you’re using VPC endpoints for enterprise compliance.
Setting Up Local Models
This is where I had the most trouble. Local models use the @ai-sdk/openai-compatible package, which wasn’t obvious from the documentation.
Ollama Integration
First, ensure Ollama is running:
# Start Ollama serverollama serve
# Pull a modelollama pull llama2ollama pull codellamaThe configuration uses the OpenAI-compatible adapter:
{ "provider": { "ollama": { "npm": "@ai-sdk/openai-compatible", "name": "Ollama (local)", "options": { "baseURL": "http://localhost:11434/v1" }, "models": { "llama2": { "name": "Llama 2" }, "codellama": { "name": "Code Llama" } } } }}Common mistake: I initially used http://localhost:11434 (without /v1). The /v1 suffix is required because OpenCode expects an OpenAI-compatible API.
LM Studio Setup
LM Studio provides a GUI for downloading and running models. Start the local server first:
- Open LM Studio
- Go to the “Local Server” tab
- Start the server on port 1234
{ "provider": { "lmstudio": { "npm": "@ai-sdk/openai-compatible", "name": "LM Studio (local)", "options": { "baseURL": "http://127.0.0.1:1234/v1" }, "models": { "google/gemma-3n-e4b": { "name": "Gemma 3n-e4b (local)" } } } }}llama.cpp Configuration
For llama.cpp, start the server with OpenAI-compatible mode:
llama-server -m model.gguf --port 8080 --host 127.0.0.1{ "provider": { "llama.cpp": { "npm": "@ai-sdk/openai-compatible", "name": "llama-server (local)", "options": { "baseURL": "http://127.0.0.1:8080/v1" }, "models": { "qwen3-coder:a3b": { "name": "Qwen3-Coder: a3b-30b (local)", "limit": { "context": 128000, "output": 65536 } } } } }}The limit configuration is important for local models. Without it, OpenCode may request more tokens than your model supports, causing silent failures.
The Complete Multi-Provider Configuration
After all my experimentation, here’s my working configuration:
{ "$schema": "https://opencode.ai/config.json", "provider": { "anthropic": { "options": { "apiKey": "{env:ANTHROPIC_API_KEY}", "timeout": 600000 }, "models": { "claude-sonnet-4-5-20250929": { "options": { "thinking": { "type": "enabled", "budgetTokens": 16000 } } } } }, "openai": { "options": { "apiKey": "{env:OPENAI_API_KEY}", "baseURL": "https://api.openai.com/v1" }, "models": { "gpt-5": { "options": { "reasoningEffort": "high", "textVerbosity": "low" } } } }, "amazon-bedrock": { "options": { "region": "{env:AWS_REGION}", "profile": "{env:AWS_PROFILE}" } }, "ollama": { "npm": "@ai-sdk/openai-compatible", "name": "Ollama (local)", "options": { "baseURL": "http://localhost:11434/v1" }, "models": { "llama2": { "name": "Llama 2" }, "codellama": { "name": "Code Llama" } } }, "lmstudio": { "npm": "@ai-sdk/openai-compatible", "name": "LM Studio (local)", "options": { "baseURL": "http://127.0.0.1:1234/v1" }, "models": { "google/gemma-3n-e4b": { "name": "Gemma 3n-e4b (local)" } } }, "llama.cpp": { "npm": "@ai-sdk/openai-compatible", "name": "llama-server (local)", "options": { "baseURL": "http://127.0.0.1:8080/v1" }, "models": { "qwen3-coder:a3b": { "name": "Qwen3-Coder: a3b-30b (local)", "limit": { "context": 128000, "output": 65536 } } } } }}Switching Between Providers
Now comes the satisfying part. With all providers configured, switching is instant.
Interactive Mode
Inside OpenCode’s interactive session:
> /modelsThis opens a searchable list of all configured models across all providers. Select one, and you’re switched.
CLI Flags
For scripting or one-off commands:
# Use Anthropic Claudeopencode run "Explain this code" --model anthropic/claude-sonnet-4-5
# Use local Ollamaopencode run "Refactor this function" --model ollama/llama2
# List all modelsopencode models
# List models from specific provideropencode models anthropicopencode models ollamaTroubleshooting Common Issues
Connection Refused for Local Models
Symptom: ECONNREFUSED errors when using Ollama/LM Studio.
Cause: The local server isn’t running or is on a different port.
# Check if Ollama is runningcurl http://localhost:11434/api/tags
# Check if LM Studio is runningcurl http://127.0.0.1:1234/v1/modelsAPI Authentication Failures
Symptom: 401 Unauthorized or Invalid API key.
Cause: Environment variable not set or wrong variable name.
# Verify environment variablesecho $ANTHROPIC_API_KEYecho $OPENAI_API_KEY
# Common mistake: using wrong variable name# Wrong: ANTHROPIC_KEY (missing API_)# Right: ANTHROPIC_API_KEYModel Not Found
Symptom: Model not found error.
Cause: Model name in config doesn’t match what the provider exposes.
# For Ollama, list available modelsollama list
# For OpenAI-compatible endpointscurl http://localhost:11434/v1/modelsContext Limit Exceeded
Symptom: Silent failures or truncated responses from local models.
Cause: Missing limit configuration for local models.
Add the limit block to your model configuration:
{ "models": { "my-model": { "limit": { "context": 128000, "output": 4096 } } }}Security Best Practices
I almost made a critical mistake early on: hardcoding API keys in the config file. Here’s what I learned:
-
Always use environment variables: The
{env:VAR_NAME}syntax keeps secrets out of your config. -
Never commit opencode.json with keys: Even with environment variables, be careful. Use a
.gitignoreentry. -
Use separate profiles for different environments: I have different AWS profiles for dev and prod.
-
Rotate keys regularly: If you accidentally expose a key, rotate it immediately.
# Add to your shell profileexport ANTHROPIC_API_KEY=sk-ant-...export OPENAI_API_KEY=sk-...export AWS_PROFILE=my-profileexport AWS_REGION=us-east-1
# Optional: enable experimental modelsexport OPENCODE_ENABLE_EXPERIMENTAL_MODELS=trueAdding Custom OpenAI-Compatible Providers
If you use a provider not listed here, you can add it as long as it offers an OpenAI-compatible API:
{ "provider": { "myprovider": { "npm": "@ai-sdk/openai-compatible", "name": "My Custom Provider", "options": { "baseURL": "https://api.myprovider.com/v1" }, "models": { "my-model-name": { "name": "My Model Display Name" } } } }}Why This Matters
Multi-provider setup isn’t just about convenience. It’s about:
- Cost optimization: Use cheaper models for simple tasks, premium models for complex reasoning
- Reliability: When one provider has an outage, switch to another
- Privacy: Keep sensitive code on local models, use cloud for general tasks
- Flexibility: Access unique capabilities (Claude’s thinking, GPT’s tool support) as needed
The Reddit community emphasizes this flexibility as a key advantage: “The best part is having so many different inference providers that you’re never going to run out of them.”
Key Takeaways
- Use
{env:VAR_NAME}syntax for all API keys - Local models require the
@ai-sdk/openai-compatibleadapter - The
/v1suffix is required for OpenAI-compatible endpoints - Set
limitvalues for local models to prevent context overflow - Use
/modelscommand to switch providers interactively
OpenCode CLI’s multi-provider support eliminated my configuration sprawl. One file, all providers, secure by default. Start with one provider and expand as your needs grow.
Final Words + More Resources
My intention with this article was to help others share my knowledge and experience. If you want to contact me, you can contact by email: Email me
Here are also the most important links from this article along with some further resources that will help you in this scope:
- 👨💻 OpenCode Documentation
- 👨💻 Anthropic API Documentation
- 👨💻 OpenAI API Reference
- 👨💻 Ollama Documentation
- 👨💻 AI SDK Providers
Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!
Comments