Skip to content

xAI / Grok

Route Claude Code inference to xAI's Grok — either your SuperGrok / X Premium+ subscription (the grok provider, OAuth) or the xAI developer API (the xai provider, API key).

Updated View as Markdown

Two built-in providers route Claude Code to xAI’s Grok models. They differ only in how they authenticate and which xAI surface they hit — pick one:

Provider Auth Backend Billing
grok xai_oauth — your SuperGrok / X Premium+ login cli-chat-proxy.grok.com/v1 (the Grok CLI chat proxy) your subscription — no per-token charge
xai api_key (XAI_API_KEY) api.x.ai/v1 (the developer API) metered API credits

Both are kind = "responses" providers speaking xAI’s Responses dialect — the same translation path as Codex, which this page mirrors. It links out to the deeper topic pages (Effort & Context, Model Discovery, Providers) rather than repeating them.

Quick start

Let a coding agent wire it up for you — shunt add prints the setup blueprint for either path (offline and read-only; the agent edits the config, the command never does):

shunt add upstream grok --print | claude   # SuperGrok / X Premium+ subscription (OAuth)
shunt add upstream xai --print | claude    # xAI developer API (XAI_API_KEY)

Or follow the manual steps below.

How it works

shunt translates Claude Code’s Anthropic Messages request into the OpenAI Responses API, sends it to xAI, and translates the streamed reply back. The xai Responses flavor (drops params xAI rejects, keeps tools as function tools) is selected two ways: by an api.x.ai host, or by auth = "xai_oauth" (the grok proxy isn’t an x.ai host, so its dialect is keyed on the auth).

Aspect grok (subscription) xai (API key)
Endpoint cli-chat-proxy.grok.com/v1/responses api.x.ai/v1/responses
Auth Grok CLI OAuth from ~/.shunt/xai-auth.json, auto-refreshed Bearer $XAI_API_KEY
Identity headers Grok CLI headers (x-xai-token-auth, x-grok-client-identifier, x-grok-client-version) so the proxy honors the subscription none

Path A — SuperGrok subscription (grok)

1. Log in

Run shunt’s own device-code login (RFC 8628). It prints a URL and a code; approve in a browser on any device — no loopback callback server:

shunt login xai

On success shunt writes the tokens to ~/.shunt/xai-auth.json with 0600 permissions and refreshes them automatically (a 5-minute expiry buffer; xAI rotates the refresh token on every refresh, so shunt persists the rotated one under a single-flight lock). If the refresh token is gone or the response omits a rotated token, shunt tells you to run shunt login xai again.

2. The provider block (optional)

grok is built in — you don’t need to declare it. This is the full default; a partial table overrides only the keys you set (config maps deep-merge):

[providers.grok]
kind = "responses"
base_url = "https://cli-chat-proxy.grok.com/v1"   # shunt appends /responses
auth = "xai_oauth"                                # read + auto-refresh ~/.shunt/xai-auth.json
# effort = "high"                                  # optional — opt in to reasoning effort (§ Reasoning effort)

3. Route a model to grok

[[routes]]
model = "grok-4.5"
provider = "grok"
# upstream_model = "grok-4.5"   # optional: forward a different slug upstream

Path B — xAI developer API (xai)

1. Export the key

export XAI_API_KEY=xai-…

2. The provider block (optional)

[providers.xai]
kind = "responses"
base_url = "https://api.x.ai/v1"   # shunt appends /responses
auth = "api_key"
api_key_env = "XAI_API_KEY"

3. Route a model to xai

[[routes]]
model = "grok-4.5"
provider = "xai"

Model slugs

The slug catalog is xAI’s, not shunt’s — shunt forwards whatever slug you route. Current coding/frontier slugs are grok-4.5, grok-4.3, and grok-build-0.1. Use upstream_model in a route to map an alias onto a live slug without touching your Claude Code env. (Model discovery only surfaces claude-named aliases you declare, so it can’t list a raw Grok slug — reach these via ANTHROPIC_CUSTOM_MODEL_OPTION or a tier remap below.)

Select the model in Claude Code

Grok slugs don’t start with claude-, so Claude Code’s /model picker won’t list them from discovery. The mechanics are identical to Codex — add the id to the picker directly:

export ANTHROPIC_CUSTOM_MODEL_OPTION="grok-4.5"   # must resolve via [models.upstream_model], [[routes]], or [[route_prefixes]]

The same Codex section covers the rest verbatim: putting a subagent on a Grok slug via model: frontmatter, and remapping the tier aliases (ANTHROPIC_DEFAULT_SONNET_MODEL, …) onto Grok slugs for a whole session.

Reasoning effort

Unlike Codex, effort is opt-in for Grok. Several Grok models (grok-4*, grok-3, grok-code-fast, …) return 400 on a reasoning.effort field even though they reason natively, so shunt sends the dial only when you configure it on the provider or route (or pass it per request) — otherwise the model uses its native reasoning:

[providers.grok]
effort = "high"        # applies to all grok traffic

# …or per route
[[routes]]
model = "grok-4.5"
provider = "grok"
effort = "high"

grok-4.5 accepts reasoning.effort (verified live). Leave effort unset for any slug that 400s on it. Full precedence and the effort table: Effort & Context.

Context window

Claude Code sizes its context bar at a fixed 200k for a mapped id. If your Grok slug’s real window is larger, raise it — the value follows a non-claude- id automatically:

export CLAUDE_CODE_MAX_CONTEXT_TOKENS=256000   # set your slug's real window, per xAI's model docs

It’s global (one value per session); set it to the smallest real window among your mapped models, since exceeding a model’s real window causes prompt is too long overflow churn. Details and count_tokens behavior: Effort & Context.

Claude Code’s built-in web search does not work on Grok routes. xAI’s Responses API accepts only function tools, so shunt drops the hosted web_search tool on the xai flavor (both grok and xai). Use a codex or openai route when you need hosted web search.

Full example (subscription path)

shunt.toml:

[server]
bind = "127.0.0.1:3001"
default_provider = "anthropic"

[providers.grok]
effort = "high"     # optional: opt in to reasoning effort for all Grok traffic

[[routes]]
model = "grok-4.5"
provider = "grok"

Shell (both shunt and Claude Code run with these):

shunt login xai                                     # one-time device-code login
./target/release/shunt run                          # start the gateway

export ANTHROPIC_BASE_URL=http://127.0.0.1:3001
export ANTHROPIC_CUSTOM_MODEL_OPTION="grok-4.5"     # add to /model picker

Pick grok-4.5 from /model. Everything else in the session still flows to Anthropic unchanged; only the mapped model’s inference is answered by your SuperGrok subscription.

Troubleshooting

Symptom Cause / Fix
run shunt login xai on startup No ~/.shunt/xai-auth.json (or wrong $SHUNT_XAI_AUTH_FILE). Run shunt login xai.
xAI refresh response missing refresh_token; run shunt login xai The stored refresh token was consumed/rotated away. Log in again.
402 … personal-team-blocked:spending-limit / “need a Grok subscription” On the xai (developer API) path without API credits. Add credits at console.x.ai, or route to grok to use your subscription.
403 … not authorized for API access (subscription tier gate) On the grok path your subscription tier doesn’t include API access — re-logging in won’t help. Set XAI_API_KEY and use the xai path, or upgrade at x.ai/grok.
refusing to send a subscription token off-origin (from shunt check) An xai_oauth provider’s base_url host isn’t x.ai/grok.com, isn’t HTTPS, or isn’t kind = "responses". Fix the block.
400 when effort is set That Grok slug rejects reasoning.effort. Remove effort from the provider/route for it.
model <slug> is not enabled for this account Unentitled slug — confirm the slug against xAI’s catalog.
Web search returns nothing Not supported on Grok routes; shunt drops the tool. Use a codex/openai route.

See the full Troubleshooting reference for more.

Navigation

Type to search…

↑↓ navigate↵ selectEsc close