Running Claude Code against a non-Claude model works, and you do it on a path the providers document themselves rather than through a hack. Ollama, Moonshot and Z.ai all publish an Anthropic-compatible endpoint.
Setup comes down to three environment variables. This guide covers the steps for all three providers, how to make the configuration stick, and the errors people hit most 🔌
The Short Answer
| Provider | ANTHROPIC_BASE_URL |
|---|---|
| Ollama (local) | http://localhost:11434 |
| Moonshot / Kimi | https://api.moonshot.ai/anthropic |
| Z.ai / GLM | https://api.z.ai/api/anthropic |
| MiniMax | https://api.minimax.io/anthropic |
| Alibaba / Qwen | depends on the plan |
Add ANTHROPIC_AUTH_TOKEN and a model name and that’s the whole setup.
How It Works
Claude Code sends its requests in the Anthropic Messages API format. ANTHROPIC_BASE_URL decides where they go. If the other side speaks the same format, Claude Code can’t tell the difference.
Three variables do it:
| Variable | What it does |
|---|---|
ANTHROPIC_BASE_URL | Where the request goes |
ANTHROPIC_AUTH_TOKEN | The provider's API key |
ANTHROPIC_MODEL or --model | Which model runs |
While ANTHROPIC_AUTH_TOKEN is set, your claude.ai subscription isn’t used. The credential replaces the subscription login, the subscription’s limits stop applying, and traffic is billed to whoever owns that key.
So you can’t reach Claude models while this configuration is active. Removing the variables brings them back, covered at the end.
Ollama for a Local Model
Ollama v0.14.0 and later speak the Anthropic Messages API. The model runs on your own machine, no internet needed, no data leaving the box.
1. Install Ollama and pull a model.
ollama pull gpt-oss:20b
2. Set the variables and launch.
macOS, Linux and WSL:
export ANTHROPIC_AUTH_TOKEN=ollama
export ANTHROPIC_BASE_URL=http://localhost:11434
claude --model gpt-oss:20b
Windows PowerShell:
$env:ANTHROPIC_AUTH_TOKEN = "ollama"
$env:ANTHROPIC_BASE_URL = "http://localhost:11434"
claude --model gpt-oss:20b
The literal string ollama works as the key, since Ollama doesn’t authenticate.
The models Ollama recommends:
| Where it runs | Model |
|---|---|
| Local | gpt-oss:20b, qwen3-coder |
| Ollama cloud | glm-4.7:cloud, minimax-m2.1:cloud |
Ollama recommends a model with at least 32K context length. Claude Code sends the whole conversation, the files it read and the tool results with every request, so a narrow context window overflows on the first turn.
Cloud models always run at their full context length; on a local model you have to watch this yourself.
Using Kimi K3
Moonshot serves Kimi through an Anthropic-compatible endpoint. Keys come from the platform.kimi.ai console.
export ANTHROPIC_BASE_URL=https://api.moonshot.ai/anthropic
export ANTHROPIC_AUTH_TOKEN=<your-kimi-api-key>
export ANTHROPIC_MODEL="kimi-k3[1m]"
claude
Moonshot’s docs recommend two more settings alongside:
export CLAUDE_CODE_AUTO_COMPACT_WINDOW=1048576
export CLAUDE_CODE_EFFORT_LEVEL=max
The first makes auto-compaction work against a 1M token window, the second pushes reasoning effort to its top level.
For how Kimi K3 actually performs, there’s a separate Kimi K3 review .
Using GLM (Z.ai)
On the Z.ai side the configuration goes straight into the settings file rather than environment variables. Open ~/.claude/settings.json and add an env block:
{
"env": {
"ANTHROPIC_AUTH_TOKEN": "your_zai_api_key",
"ANTHROPIC_BASE_URL": "https://api.z.ai/api/anthropic",
"API_TIMEOUT_MS": "3000000"
}
}
Z.ai’s default mapping points all three aliases at the same model:
"ANTHROPIC_DEFAULT_OPUS_MODEL": "GLM-4.7",
"ANTHROPIC_DEFAULT_SONNET_MODEL": "GLM-4.7",
"ANTHROPIC_DEFAULT_HAIKU_MODEL": "GLM-4.7"
API_TIMEOUT_MS matters here: the default timeout isn’t enough for models that think for a long time.
To try it without paying, GLM-4.7-Flash is the free tier of GLM-4.7. Just set that as the model name; the base URL stays the same.
Using MiniMax
MiniMax’s Claude Code page puts the configuration straight into settings.json:
{
"env": {
"ANTHROPIC_BASE_URL": "https://api.minimax.io/anthropic",
"ANTHROPIC_AUTH_TOKEN": "<YOUR_MINIMAX_API_KEY>",
"ANTHROPIC_MODEL": "MiniMax-M3[1m]",
"ANTHROPIC_DEFAULT_SONNET_MODEL": "MiniMax-M3[1m]",
"ANTHROPIC_DEFAULT_OPUS_MODEL": "MiniMax-M3[1m]",
"ANTHROPIC_DEFAULT_HAIKU_MODEL": "MiniMax-M3[1m]",
"CLAUDE_CODE_AUTO_COMPACT_WINDOW": "1000000"
}
}
Connecting from China, the base URL is https://api.minimaxi.com/anthropic.
There’s also a cheaper route through Ollama’s cloud, with the model name minimax-m2.1:cloud.
Using Qwen (Alibaba Model Studio)
On the Alibaba side both the base URL and the model change with the plan you pick:
| Plan | ANTHROPIC_BASE_URL | Model |
|---|---|---|
| Coding Plan | https://coding-intl.dashscope.aliyuncs.com/apps/anthropic | qwen3.7-plus |
| Token Plan | https://token-plan.ap-southeast-1.maas.aliyuncs.com/apps/anthropic | qwen3.6-plus |
| Pay-as-you-go (China) | https://dashscope.aliyuncs.com/apps/anthropic | qwen3.6-plus |
Other model IDs the docs mention: qwen3.6-flash, qwen3.7-max.
Model Studio’s Claude Code page lists no qwen3-coder model ID; the lineup there is the qwen3.x-plus, -flash and -max family.
To run Qwen3-Coder, the route is a local Ollama setup, as in the Ollama section above: claude --model qwen3-coder.
Remap the Aliases So the Picker Works
Up to here we’ve named the model with --model every time. Here’s why: Claude Code can pull a model list from a gateway, but it keeps only entries whose ID contains claude or anthropic. gpt-oss:20b doesn’t pass that filter, so it never appears in /model.
The fix is remapping the aliases. The pattern from Moonshot’s docs:
export ANTHROPIC_DEFAULT_OPUS_MODEL="kimi-k3[1m]"
export ANTHROPIC_DEFAULT_SONNET_MODEL="kimi-k3[1m]"
export ANTHROPIC_DEFAULT_HAIKU_MODEL="kimi-k3[1m]"
export ANTHROPIC_DEFAULT_FABLE_MODEL="kimi-k3[1m]"
export CLAUDE_CODE_SUBAGENT_MODEL="kimi-k3[1m]"
With those set, typing /model opus runs Kimi, and subagents and workflow agents follow. The same pattern works for Ollama and Z.ai; just change the model name.
CLAUDE_CODE_SUBAGENT_MODEL matters most. Leave it out and your subagents still try to call a Claude model, and error.
Making It Stick: settings.json
Variables set with export disappear when you close the terminal. Two ways to keep them:
Your shell profile: add the export lines to .bashrc or .zshrc. On Windows, use setx or the Environment Variables panel.
The settings file: the env block in ~/.claude/settings.json, like the Z.ai example. This is the cleaner route, since the configuration lives in one place and doesn’t pollute your shell.
Don’t mix the two. When ANTHROPIC_BASE_URL and ANTHROPIC_AUTH_TOKEN exist as environment variables, they take priority over whatever is in settings.json.
That’s why MiniMax’s docs tell you to clear the old Anthropic variables before configuring. It’s the most common problem when moving between providers: you edit the settings file, but a stale variable in your shell wins.
What You Give Up
“It works” doesn’t mean “everything works the same”. Claude Code puts Claude-specific fields and beta headers on its requests:
| Feature | What happens |
|---|---|
| Adaptive reasoning | Claude Code treats model names it doesn't recognize as current models and sends thinking: {"type": "adaptive"}; if the upstream rejects it, 400 |
| Context management | 400 with Extra inputs are not permitted |
| Beta tool fields | 400 naming the unrecognized tool schema field |
| Effort and structured outputs | 400 naming output_config |
| Token counting | Falls back to local estimation, so context measurement is approximate |
| Extended context, interleaved thinking | Silently unavailable if the header isn't forwarded |
| Fine-grained tool streaming | Off by default behind a custom base URL |
Common Errors
404 page not found The base URL is wrong. All three end differently: Ollama is plain http://localhost:11434 (don’t append /v1), Moonshot ends in /anthropic, Z.ai in /api/anthropic.
400 errors The upstream doesn’t recognize a Claude-specific field. Most of them go quiet with one variable:
export CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS=1
It stops Claude Code from sending pre-release capabilities and their body fields. It doesn’t affect adaptive reasoning, which is selected by model rather than by beta.
connection refused The Ollama service isn’t running, or it’s on a different port. Confirm with ollama serve, and update the base URL if you changed the port.
The stream cuts off mid-response On ANTHROPIC_BASE_URL connections Claude Code counts every byte and aborts a stream that goes silent for 300 seconds by default. A slow local model hits that wall during long thinking pauses. Z.ai’s API_TIMEOUT_MS recommendation targets the same problem.
Subagents keep erroring CLAUDE_CODE_SUBAGENT_MODEL isn’t set, so subagents still call a Claude model even though the main one changed.
What Anthropic Says
The sentence in Anthropic’s documentation: it doesn’t endorse, maintain or audit third-party gateway products, and doesn’t support routing Claude Code to non-Claude models through any gateway.
“Doesn’t support” here means “we won’t stand behind it when it breaks”, not “forbidden”. ANTHROPIC_BASE_URL and ANTHROPIC_AUTH_TOKEN are documented variables in Anthropic’s own gateway protocol. The practical consequence: when something stops working, support comes from the provider, not Anthropic.
Going Back to Claude
Remove the variables and Claude Code returns to your subscription:
unset ANTHROPIC_BASE_URL ANTHROPIC_AUTH_TOKEN ANTHROPIC_MODEL
unset ANTHROPIC_DEFAULT_OPUS_MODEL ANTHROPIC_DEFAULT_SONNET_MODEL
unset ANTHROPIC_DEFAULT_HAIKU_MODEL CLAUDE_CODE_SUBAGENT_MODEL
If you used the settings file, delete the env block from ~/.claude/settings.json. Then run /status to confirm which provider you’re on.
To switch between Claude models themselves (opus, sonnet, opusplan), that’s the /model command; the slash commands guide covers all of them.
Frequently Asked Questions
Can I connect Claude Code to a local model with Ollama? Yes. Ollama v0.14.0 and later speak the Anthropic Messages API. Set ANTHROPIC_AUTH_TOKEN=ollama and ANTHROPIC_BASE_URL=http://localhost:11434, then run claude --model gpt-oss:20b. Ollama recommends a model with at least 32K context length.
How do I use Kimi K3 in Claude Code? Use https://api.moonshot.ai/anthropic as the base URL, your Kimi API key as the token, and kimi-k3[1m] as the model. Moonshot also recommends CLAUDE_CODE_AUTO_COMPACT_WINDOW=1048576 and CLAUDE_CODE_EFFORT_LEVEL=max.
How do I use Claude Code with GLM? In the env block of ~/.claude/settings.json, set ANTHROPIC_BASE_URL to https://api.z.ai/api/anthropic, ANTHROPIC_AUTH_TOKEN to your Z.ai key, and API_TIMEOUT_MS to 3000000. Z.ai maps all three model aliases to GLM-4.7 by default.
Why doesn’t my local model show up in the /model picker? Claude Code keeps only gateway-discovered entries whose ID contains claude or anthropic. gpt-oss:20b doesn’t pass that filter. Either name it with --model or remap the alias variables like ANTHROPIC_DEFAULT_OPUS_MODEL to that model.
Why am I getting a 404 page not found in Claude Code? The base URL is wrong. Ollama’s address is plain http://localhost:11434 with no /v1 appended. Moonshot must end in /anthropic and Z.ai in /api/anthropic.
How do I fix a 400 error on a local model? The upstream doesn’t recognize a Claude-specific field. Set CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS=1, which stops the pre-release capabilities and body fields and clears most of these errors.
Does this setup affect my Claude subscription? Yes. While ANTHROPIC_AUTH_TOKEN is set, your claude.ai subscription isn’t used; the credential replaces the subscription login and traffic is billed to whoever owns that key. Remove the variables to go back.
Does Anthropic forbid using local models? No. The docs say it doesn’t endorse, maintain or audit third-party gateways and doesn’t support routing to non-Claude models. That means “we won’t stand behind it when it breaks”, not “forbidden”. ANTHROPIC_BASE_URL and ANTHROPIC_AUTH_TOKEN are documented variables in Anthropic’s own gateway protocol.
Summary
Three providers, one pattern: base URL, key, model name. Ollama runs locally and free, Kimi and GLM run in the cloud on a plan.
Don’t skip two settings: without remapping the aliases the /model picker stays empty, and without CLAUDE_CODE_SUBAGENT_MODEL your subagents error out.
Set expectations correctly too. Token counting, extended context and some beta features go away, and most 400s go quiet with CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS=1. If privacy or offline work is what decides it for you, the trade makes sense đź‘€
