Use with Claude Code
July 2, 2026 ยท View on GitHub
Claude Code speaks the Anthropic Messages API and lets
you redirect it at any compatible endpoint with a couple of environment
variables. Otari exposes that surface (POST /v1/messages and
POST /v1/messages/count_tokens) in both standalone and hybrid modes, so you
can route Claude Code through Otari to get budgets, usage tracking, and traces
without changing how you use the CLI.
Quick start
Claude Code appends /v1/messages and /v1/messages/count_tokens to
ANTHROPIC_BASE_URL itself, so the base URL must be the Otari root, not
/v1. For local development, use http://localhost:8000.
Connected to otari.ai
export ANTHROPIC_BASE_URL="https://api.otari.ai" # your Otari base URL, no /v1
export ANTHROPIC_AUTH_TOKEN="tk_your_otari_token" # sent as Authorization: Bearer
export ANTHROPIC_MODEL="anthropic:claude-sonnet-4-6"
claude
Standalone
Claude Code attaches its own metadata.user_id to every request. In standalone
mode Otari binds spend to the API key's own user and, by default, rejects a
request that names a different user (403 permission_error). Set
reject_user_mismatch: false in your config so Claude Code's user_id is
ignored and spend is still bound to the key's user.
reject_user_mismatch: false
Then run Claude Code against your local Otari:
export ANTHROPIC_BASE_URL="http://localhost:8000"
export ANTHROPIC_AUTH_TOKEN="<your-otari-api-key>"
export ANTHROPIC_MODEL="anthropic:claude-sonnet-4-6"
claude
Use ANTHROPIC_AUTH_TOKEN (not ANTHROPIC_API_KEY): it is sent as
Authorization: Bearer <token>, which is the scheme Otari accepts for
both standalone API keys and connected user tokens. ANTHROPIC_API_KEY sends an
x-api-key header instead, which Otari does not read.
settings.json
The same configuration works in ~/.claude/settings.json (or a project-level
.claude/settings.json). Replace the values with your deployment's URL, token,
and model defaults:
{
"env": {
"ANTHROPIC_BASE_URL": "https://api.otari.ai",
"ANTHROPIC_AUTH_TOKEN": "tk_your_otari_token",
"ANTHROPIC_DEFAULT_OPUS_MODEL": "anthropic:claude-opus-4-8",
"ANTHROPIC_DEFAULT_SONNET_MODEL": "anthropic:claude-sonnet-4-6",
"ANTHROPIC_DEFAULT_HAIKU_MODEL": "anthropic:claude-haiku-4-5"
}
}
Choosing a model
Claude Code speaks the Anthropic wire format, but the model field is just a
string Otari forwards to any-llm.
Examples in this page use provider:model; Otari also accepts
provider/model in both standalone and connected mode.
- Claude models:
anthropic:claude-sonnet-4-6,anthropic:claude-opus-4-8,anthropic:claude-haiku-4-5 - Standalone, any configured provider:
openai:gpt-4o,mistral:mistral-large-latest,anthropic:claude-sonnet-4-6 - Connected to otari.ai, managed models:
mzai:<catalog-id>, for examplemzai:moonshotai/Kimi-K2.6. These run only through otari.ai's hosted gateway. - Connected to otari.ai, your own provider keys:
openai:gpt-4o,mistral:mistral-large-latest,anthropic:claude-sonnet-4-6
If you use Claude Code's opus, sonnet, or haiku aliases, set the matching
ANTHROPIC_DEFAULT_*_MODEL variables so Claude Code does not fall back to a
model your Otari deployment does not serve.
Non-Claude models
Otari can route Claude Code to non-Claude models, but Claude Code is tuned for Claude. Expect weaker tool use on some models, and expect Anthropic-specific features such as extended thinking or prompt caching to be dropped when the target provider does not support them.
See also
- Modes for standalone vs connected behavior
- API reference for the Messages endpoints and auth rules