Configuration
shunt loads configuration from, in increasing precedence:
-
Built-in defaults — every provider (
anthropic,openai,codex, …) is preconfigured. -
A TOML file. With
--config <path>that exact file is used (a missing file is an error). Otherwise shunt takes the first file found in:./shunt.toml$XDG_CONFIG_HOME/shunt/shunt.toml(default~/.config/shunt/shunt.toml)$HOMEBREW_PREFIX/etc/shunt.toml(default/opt/homebrewand/usr/localprefixes)
Boot logs report which file was loaded, or that defaults are in use.
-
Environment variables prefixed
SHUNT_, using__for nested keys — e.g.SHUNT_SERVER__BIND=0.0.0.0:3001.
Because the defaults already define every provider, your shunt.toml only needs the parts you want to change. Start from shunt.toml.example.
Annotated example
Section titled “Annotated example”[server]bind = "127.0.0.1:3001" # address shunt listens ondefault_provider = "anthropic" # provider for any model with no route (pass-through)
# Each provider is a [providers.<name>] table.[providers.anthropic]kind = "anthropic" # forward Claude Code's own credential unchangedbase_url = "https://api.anthropic.com"
[providers.openai]kind = "responses" # translate Anthropic Messages -> OpenAI Responsesbase_url = "https://api.openai.com/v1"auth = "api_key"api_key_env = "OPENAI_API_KEY" # env var the OpenAI key is read from# effort = "high" # optional default reasoning effort for this provider
[providers.codex]kind = "responses"base_url = "https://chatgpt.com/backend-api"auth = "chatgpt_oauth" # reuses ~/.codex/auth.json# effort = "high"
# --- Routing: how a request's `model` id picks a provider ---
# Exact match wins first. `upstream_model` and `effort` are optional overrides.[[routes]]model = "gpt-5.6-sol"provider = "codex"# upstream_model = "gpt-5.6-sol"# effort = "high"
# Then prefix match.[[route_prefixes]]prefix = "gpt-"provider = "openai"
# Optional: expose Claude-named aliases in the /model picker via discovery.# The id MUST start with "claude" or "anthropic" or Claude Code ignores it.# [[models]]# id = "claude-opus-via-codex"# display_name = "Opus (via Codex)"Routing precedence
Section titled “Routing precedence”- Exact
[[routes]]match on the request’smodelid. [[route_prefixes]]prefix match.server.default_provider— by defaultanthropic, so a model with no match falls through to Anthropic unchanged.
A route can override the forwarded model id (upstream_model) and the reasoning effort (effort) per model.
Partial overrides
Section titled “Partial overrides”Config maps are deep-merged, so a partial override of a built-in provider keeps the rest of its defaults:
# Only raise codex's default effort; everything else stays at the built-in values.[providers.codex]effort = "high"Validate
Section titled “Validate”shunt check# -> prints "config ok", or a specific error (bad bind address, unknown provider, …)See the Configuration Reference for every key, and Providers for adding new backends.