- Published on
How to Add Custom Model Provider to Claude Code: 2026 Guide
- Authors

- Name
- Rakesh Tembhurne
- @tembhurnerakesh
Claude Code uses one wire protocol: the Anthropic Messages API. Any endpoint that speaks it can back Claude Code, and you switch endpoints with three environment variables. The same mechanism powers OpenRouter, DeepSeek, Kimi, a corporate LiteLLM gateway, and a local Ollama model.
Each section below is a complete recipe. For the full variable list, read the Claude Code environment variables reference.
Table of Contents
Table of Contents
- How the pieces fit
- Put the config in a settings file
- Map every alias tier
- OpenRouter
- DeepSeek
- Kimi and Moonshot
- Z.ai GLM
- Ollama (local, no API cost)
- LiteLLM gateway (many providers, one endpoint)
- Add extra headers
- Make the provider's models selectable
- Verify the setup
- Common errors
- Which approach should you use
- Frequently asked questions
- Can Claude Code use OpenRouter, DeepSeek, Kimi, and Ollama?
- Do I need a proxy for custom providers?
- Why does my custom model return model not found?
- How do I switch providers in Claude Code?
- Is LiteLLM safe to use with Claude Code?
- What Anthropic supports
- Related reading
- Closing
How the pieces fit
Every custom provider setup has four parts:
- A base URL that speaks the Anthropic Messages API.
- A credential (a bearer token or an API key).
- Model names the provider understands, mapped onto Claude Code's alias tiers.
- Optionally, extra request headers or a picker entry.
A request flow looks like this:
Claude Code
|
| POST https://provider.example/anthropic/v1/messages
| Authorization: Bearer <credential>
v
Provider endpoint (Anthropic Messages format)
|
v
Target model
Claude Code does not translate protocols. If a provider only speaks OpenAI's chat format, you need a translation layer such as a LiteLLM gateway or a router. Pointing ANTHROPIC_BASE_URL at a raw OpenAI endpoint will not work.
Put the config in a settings file
You can export variables in your shell, but a settings file is better. It applies to every launch, including background agents, and it survives new terminals.
Pick one of:
~/.claude/settings.jsonfor all your projects..claude/settings.local.jsonfor one project, gitignored.
Do not use .claude/settings.json. That file is committed, and it would leak your credential to everyone who clones the repository.
The shape is always the same:
{
"env": {
"ANTHROPIC_BASE_URL": "https://provider.example/anthropic",
"ANTHROPIC_AUTH_TOKEN": "your-key"
}
}
The env value overrides a shell export of the same variable, so the file is the source of truth once it exists.
Map every alias tier
Claude Code uses several model slots internally:
opusandsonnetfor main work, withopusplansplitting between plan and execution.haikufor small, fast, background work.fableas a fallback family.- Subagents, which follow
CLAUDE_CODE_SUBAGENT_MODEL.
If you only set the main model, background tasks and subagents keep requesting claude-... names the provider does not have, and they fail quietly. Map all of them:
{
"env": {
"ANTHROPIC_BASE_URL": "https://provider.example/anthropic",
"ANTHROPIC_AUTH_TOKEN": "your-key",
"ANTHROPIC_DEFAULT_OPUS_MODEL": "provider-strong-model",
"ANTHROPIC_DEFAULT_SONNET_MODEL": "provider-balanced-model",
"ANTHROPIC_DEFAULT_HAIKU_MODEL": "provider-fast-model",
"ANTHROPIC_DEFAULT_FABLE_MODEL": "provider-strong-model",
"CLAUDE_CODE_SUBAGENT_MODEL": "provider-balanced-model"
}
}
ANTHROPIC_MODEL sets a single main model when you do not want per-tier mapping. /model and --model override it for a session.
OpenRouter
OpenRouter exposes an Anthropic-compatible skin, so no local proxy is needed. One key reaches hundreds of models.
{
"env": {
"ANTHROPIC_BASE_URL": "https://openrouter.ai/api",
"ANTHROPIC_AUTH_TOKEN": "sk-or-v1-your-key",
"ANTHROPIC_API_KEY": "",
"CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY": "1"
}
}
Four details:
- The base URL is
https://openrouter.ai/api, not/api/v1. ANTHROPIC_API_KEYmust be explicitly empty. An unset variable is not enough, because a stale key can override the auth and silently fall back to Anthropic.- OpenRouter guarantees Anthropic-format behavior best with its first-party Anthropic provider. Set Anthropic first in your OpenRouter provider routing if tool calls misbehave on other models.
- If a cached Claude login is active, run
/logoutand relaunch, or the login can override the environment.
Model slugs come from the OpenRouter model list. Map tiers like this:
{
"env": {
"ANTHROPIC_BASE_URL": "https://openrouter.ai/api",
"ANTHROPIC_AUTH_TOKEN": "sk-or-v1-your-key",
"ANTHROPIC_API_KEY": "",
"ANTHROPIC_DEFAULT_OPUS_MODEL": "anthropic/claude-opus-4.6",
"ANTHROPIC_DEFAULT_SONNET_MODEL": "anthropic/claude-sonnet-4.6",
"ANTHROPIC_DEFAULT_HAIKU_MODEL": "google/gemini-2.5-flash"
}
}
GitHub Actions: the Claude Code action reads ANTHROPIC_BASE_URL and ANTHROPIC_CUSTOM_HEADERS from the workflow env block, and it sets the supplied key as ANTHROPIC_API_KEY, so it arrives in the x-api-key header. Pass the OpenRouter key through the action's anthropic_api_key input and set the base URL in env.
DeepSeek
DeepSeek serves an Anthropic-compatible endpoint directly, so no router is required.
{
"env": {
"ANTHROPIC_BASE_URL": "https://api.deepseek.com/anthropic",
"ANTHROPIC_AUTH_TOKEN": "sk-your-deepseek-key",
"ANTHROPIC_MODEL": "deepseek-chat",
"ANTHROPIC_DEFAULT_HAIKU_MODEL": "deepseek-chat",
"CLAUDE_CODE_SUBAGENT_MODEL": "deepseek-chat"
}
}
DeepSeek auto-maps Claude model names for common cases, but setting the tier variables explicitly avoids surprises. Check the DeepSeek API docs for the current model IDs, because the lineup changes faster than most blogs update.
Kimi and Moonshot
Moonshot AI, the maker of Kimi, publishes an Anthropic-compatible base URL.
{
"env": {
"ANTHROPIC_BASE_URL": "https://api.moonshot.ai/anthropic",
"ANTHROPIC_AUTH_TOKEN": "sk-your-moonshot-key",
"ANTHROPIC_MODEL": "kimi-k2-0905-preview",
"ANTHROPIC_DEFAULT_HAIKU_MODEL": "kimi-k2-0905-preview",
"CLAUDE_CODE_SUBAGENT_MODEL": "kimi-k2-0905-preview"
}
}
For a mainland China account, use the .cn host instead of .ai. Verify the current model name in the Moonshot platform console before you commit it to a settings file.
Z.ai GLM
Z.ai exposes an Anthropic-compatible endpoint for its GLM coding models.
{
"env": {
"ANTHROPIC_BASE_URL": "https://api.z.ai/api/anthropic",
"ANTHROPIC_AUTH_TOKEN": "your-zai-key"
}
}
Check the Z.ai console for the exact model IDs.
Ollama (local, no API cost)
Ollama added native Anthropic Messages compatibility in early 2026, so Claude Code can talk to a local model without a proxy.
{
"env": {
"ANTHROPIC_BASE_URL": "http://localhost:11434",
"ANTHROPIC_AUTH_TOKEN": "ollama",
"ANTHROPIC_MODEL": "qwen3-coder"
}
}
Ollama ignores the token value, but Claude Code expects a credential, so set a placeholder. Pull the model first with ollama pull qwen3-coder. A local model is the cleanest option for private or offline work, at the cost of speed and quality on hard tasks.
LiteLLM gateway (many providers, one endpoint)
LiteLLM is an Anthropic-compatible gateway that fronts many providers and adds budgets, cost tracking, and fallbacks. Anthropic names LiteLLM as an example gateway.
Install and configure:
pip install 'litellm[proxy]'
config.yaml:
model_list:
- model_name: anthropic-claude
litellm_params:
model: anthropic/claude-sonnet-4-6
api_key: os.environ/ANTHROPIC_API_KEY
- model_name: openai-route
litellm_params:
model: openai/gpt-5
api_key: os.environ/OPENAI_API_KEY
- model_name: gemini-route
litellm_params:
model: gemini/gemini-2.5-pro
api_key: os.environ/GEMINI_API_KEY
litellm_settings:
master_key: os.environ/LITELLM_MASTER_KEY
Start it on port 4000:
litellm --config config.yaml
Point Claude Code at it:
{
"env": {
"ANTHROPIC_BASE_URL": "http://localhost:4000",
"ANTHROPIC_AUTH_TOKEN": "sk-your-litellm-master-key",
"CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY": "1"
}
}
The gateway must expose /v1/messages and /v1/messages/count_tokens, and forward anthropic-beta and anthropic-version. Discovery populates the /model picker from the gateway's model list.
Security note: LiteLLM versions 1.82.7 and 1.82.8 on PyPI shipped credential-stealing malware. Pin a clean version and rotate any credentials that ran through those releases.
Add extra headers
Gateways often tag requests with a tenant or routing header. Add them with ANTHROPIC_CUSTOM_HEADERS, using \n between pairs in JSON.
{
"env": {
"ANTHROPIC_BASE_URL": "https://llm-gateway.example.com",
"ANTHROPIC_AUTH_TOKEN": "sk-gateway-key",
"ANTHROPIC_CUSTOM_HEADERS": "X-Org-Route: prod\nX-Tenant: example"
}
}
Make the provider's models selectable
By default the /model picker lists built-in Claude models. To fix that:
- Turn on discovery:
CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY=1. The picker fills from the gateway's model list. - Add one entry manually with
ANTHROPIC_CUSTOM_MODEL_OPTION, plus optional name and description.
{
"env": {
"ANTHROPIC_CUSTOM_MODEL_OPTION": "provider.example/strong-model",
"ANTHROPIC_CUSTOM_MODEL_OPTION_NAME": "Provider Strong",
"ANTHROPIC_CUSTOM_MODEL_OPTION_DESCRIPTION": "Routed through the provider gateway"
}
}
Verify the setup
After any change, restart Claude Code and run /status. It should show the gateway base URL and the credential source, for example Auth token: ANTHROPIC_AUTH_TOKEN. If it shows a saved login, the variable is not being read.
Then:
- Run
/modeland confirm the provider models appear. - Send a trivial prompt and confirm you get a reply, not a 401 or a model-not-found error.
- Watch a background task complete, which proves the
haikutier is mapped.
If the picker is empty, run claude --debug and look for gateway discovery lines.
Common errors
| Error | Cause | Fix |
|---|---|---|
| 401 | Credential in the wrong header | Try ANTHROPIC_AUTH_TOKEN and ensure ANTHROPIC_API_KEY is empty |
| Model not found | Unmapped alias tier | Set all ANTHROPIC_DEFAULT_*_MODEL variables |
| Requests still hit Anthropic | Saved login active | Run /logout or unset the login, then relaunch |
| Tool calls fail on a model | Endpoint lacks full tool-use support | Prefer the provider's Anthropic-compatible or first-party route |
| Empty picker | Discovery off | Set CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY=1 |
| Remote Control or voice missing | Gateway credential active | Expected; disable the gateway to restore them |
Which approach should you use
| Situation | Use |
|---|---|
| One non-Anthropic model, provider has an Anthropic endpoint | Native variables plus settings file |
| Many models, one key, no install | OpenRouter |
| Private or offline work | Ollama |
| Many providers, budgets, and cost tracking | LiteLLM gateway |
| Per-task routing and failover across agents | A router such as Claude Code Router |
| Enterprise governance | Managed settings plus an approved gateway |
Frequently asked questions
Can Claude Code use OpenRouter, DeepSeek, Kimi, and Ollama?
Yes, if the endpoint speaks the Anthropic Messages API. Set ANTHROPIC_BASE_URL and ANTHROPIC_AUTH_TOKEN, then map ANTHROPIC_DEFAULT_OPUS_MODEL, ANTHROPIC_DEFAULT_SONNET_MODEL, ANTHROPIC_DEFAULT_HAIKU_MODEL, and CLAUDE_CODE_SUBAGENT_MODEL. For OpenRouter use https://openrouter.ai/api and set ANTHROPIC_API_KEY="".
Do I need a proxy for custom providers?
Only if the provider lacks an Anthropic endpoint. DeepSeek, Moonshot/Kimi, Z.ai, and Ollama speak it natively. OpenAI-only providers need a translator such as LiteLLM (https://openrouter.ai/api) or Claude Code Router.
Why does my custom model return model not found?
Unmapped alias tiers. Claude Code still requests claude-... names for background tasks and subagents. Map all tiers explicitly. See the model configuration docs.
How do I switch providers in Claude Code?
Change the environment variables and restart. /model changes the model, not the endpoint. A local router is the only way to change providers without a restart.
Is LiteLLM safe to use with Claude Code?
LiteLLM is an Anthropic-documented gateway example, but versions 1.82.7 and 1.82.8 shipped malware. Pin a clean version and rotate credentials.
What Anthropic supports
Anthropic documents the gateway mechanism and does not endorse, maintain, or audit third-party gateways. It also does not support routing Claude Code to non-Claude models through a gateway. The base URL and credential variables are stable interfaces; the behavior of any specific model behind them is the provider's responsibility.
Sources: Claude Code gateway docs · OpenRouter Claude Code guide · DeepSeek Claude Code · Kimi Claude Code
Related reading
- Claude Code Environment Variables Reference
- Extending Claude Code with Multiple Models
- Building a Claude Code Router
Closing
Adding a provider is four lines of configuration: base URL, credential, model mapping, and an optional header or picker entry. Put it in a settings file, map every alias tier, and confirm with /status.
Start with one provider and one model. Add tiers and routing only after the first request succeeds.
Related Posts
How to Change Model in Claude Code: /model, --model, Aliases
Learn to change and switch models in Claude Code with /model, --model, ANTHROPIC_MODEL, and aliases. Persist defaults and show gateway models in picker.
Claude Code Environment Variables: Complete Reference
Learn every Claude Code env var for custom models: ANTHROPIC_BASE_URL, ANTHROPIC_AUTH_TOKEN, ANTHROPIC_CUSTOM_HEADERS, ANTHROPIC_MODEL, and settings.json.
The AI Developer Toolkit in 2026: From Claude Code to DeepSeek
A practical breakdown of 1000+ Twitter insights on AI tools, frameworks, and strategies that are reshaping how solo developers and indie hackers build products in 2026.