Skip to content

Changelog

Every notable change to shunt, dated, with breaking changes flagged.

Updated View as Markdown

Curated release notes, newest first. shunt is pre-1.0, so a minor bump (0.44 → 0.45) may carry breaking changes; a patch bump usually does not, but check any entry marked Breaking — that is where the exceptions are named. Every breaking entry below names who it affects, what to do, and the release it landed in.

This page covers 0.35.0 onward. Releases before that are in the generated changelog only.

0.45.1 — 2026-09-14

Native tool search is enabled for gpt-6-astra

Fixed — gpt-6-astra now negotiates the upstream’s own tool-search capability instead of falling back to the translated form. See Effort & Context.

0.45.0 — 2026-09-14

Admin JSON and mutation routes moved to /admin/api/*

Changed · Breaking, effective 0.45.0 — Affects every scripted caller of the admin API. All 13 JSON and mutation routes gained one /api segment after /admin, and the old paths were removed rather than aliased, so each caller must be updated. /admin, /admin/login and /admin/oidc/callback are unchanged — the full before/after table is in Admin path migration.

GET /admin returns the SPA shell instead of redirecting

Changed · Breaking, effective 0.45.0 — Affects scripts that read the 303 to /admin/login as “not signed in”. An unauthenticated GET /admin now answers 200 with the embedded shell, which is one static file identical for every visitor and carries no operator data; the redirect moved into the bundle, which follows a 401 from GET /admin/api/session. Read that bootstrap endpoint to test for a session. See HTTP Endpoints.

Read keys can open a browser session

Changed · Breaking, effective 0.45.0 — Affects deployments that relied on “read keys cannot open a browser session” as a revocation property. POST /admin/login now answers 303 with a read-tier session cookie for a [server.admin] read_keys credential where it previously answered 401; every mutation still answers 403, so the cookie grants no permission the key lacked, but it carries its own lifetime. Because browser sessions validate against the in-memory store alone, rotating a compromised read key stops its header credential at the next reload while its cookie reads on until session_ttl_secs (default 1h) elapses — restart rather than reload to drop it.

Embedded admin SPA behind --features ui

Added — The admin dashboard is now a compiled SPA bundle embedded at build time and served from /admin, replacing the server-rendered string literals. A binary built without --features ui answers 404 on the shell routes, naming the feature. See Admin & Remote Provisioning.

Graceful shutdown drain is bounded and configurable

Added — After the first SIGTERM/SIGINT, active HTTP/SSE/WebSocket work drains for shutdown_timeout_seconds (default 30, range 1–3600) before the remainder is cancelled. Changing it requires a restart. See [server].

h2 updated for an empty-frame denial of service

Security — The h2 dependency was updated to remediate a denial of service reachable by flooding a connection with empty frames. Upgrade to 0.45.0 or later; no configuration change is needed.

Optional function parameters survive translation

Fixed — OpenAI backends normalize function tools without an explicit strict toward strict mode, where a closed parameter object makes every property behave as required and the model fills in values the caller never set. shunt now pins strict:false on forwarded function tools, keeping optional properties optional. See Troubleshooting.

Codex catalog failures use the negotiated error shape

Fixed — A model-discovery failure against the Codex catalog now returns the error shape the inbound endpoint negotiated rather than always the Anthropic one, so OpenAI-protocol clients parse it through their own error path. See Model Discovery.

Admin login and provisioning fixes

Fixed — The login page CSP no longer sends script-src and connect-src; the SPA shell is served on /admin/ as well as /admin; concurrent completions for one pending login are serialized; a refused start now says that it closed the authorization step; and the add-account form no longer misreports a login.

0.44.0 — 2026-09-09

Inbound Responses requests translate to Anthropic and Chat Completions upstreams

Added — A request arriving on the inbound Codex endpoint can now be routed to an Anthropic-kind or Chat Completions upstream, with the translation handled in both directions. See Inbound Codex Endpoint.

In-stream codex.rate_limits is recorded on the WebSocket transport

Fixed — The WebSocket transport now records the in-stream codex.rate_limits event, so quota windows stay current on reused connections instead of only on fresh HTTP turns. This feeds GET /usage.

Tool-schema regex patterns the OpenAI validator rejects are dropped

Fixed — OpenAI backends compile every pattern in a tool schema with Python re and reject JavaScript-only regexes (\p{Cc}, (?<name>…), \u{…}). shunt now strips those patterns from forwarded schemas; outside strict mode pattern is advisory, so only the hint is lost. See Troubleshooting.

0.43.0 — 2026-09-08

GET /usage reports a per-provider breakdown

Added — Alongside the pool-wide aggregate, GET /usage now carries the same sanitized figures per pooled provider under providers, so a client routing to one provider reads that provider’s headroom instead of the blended mean. Providers whose auth mode is not pooled are omitted. See HTTP Endpoints.

GET /usage reports mean pool headroom, not the least-utilized account

Changed — Each window now reports mean(1 - utilization) across non-disabled accounts reporting it — the fraction of the pool’s combined capacity still unused — rather than the single least-utilized account. A client reading the old field as one account’s headroom will now see a pool-wide figure.

0.42.0 — 2026-09-07

Model-routed third-party upstreams on the inbound Responses endpoint

Added — The inbound Responses endpoint now honors per-model routing to third-party upstreams, so a Codex CLI client can reach a vendor other than OpenAI by model id. See Inbound Codex Endpoint.

0.41.3 — 2026-09-07

A Grok product without usagePercent no longer blanks the quota row

Fixed — A product reported with no usagePercent previously blanked the whole quota row instead of being skipped. See xAI / Grok.

0.41.2 — 2026-09-07

The device page’s SSO form can redirect to the identity provider

Fixed — The device page’s CSP form-action refused the redirect to the configured identity provider, so SSO could not complete from that page. See Gateway Login.

0.41.1 — 2026-09-07

The device page’s own form POST is accepted despite a null Origin

Fixed — Referrer-Policy: no-referrer makes a same-page form POST arrive with Origin: null, which the CSRF guard refused. The guard now decides on Sec-Fetch-Site: same-origin first.

An undelivered agy handoff no longer fails a completed turn

Fixed — A turn that had already completed is no longer failed by a handoff that could not be delivered to the local agy subprocess. See Antigravity.

0.41.0 — 2026-09-05

Zhipu and MiniMax China presets

Added — zhipu and minimax-cn ship as built-in Anthropic-compatible presets, so the mainland China endpoints need only a credential rather than a hand-written provider table. See Zhipu and MiniMax China.

The Antigravity effort matrix is re-discovered for an unknown model

Fixed — A turn naming a model absent from the cached effort matrix now triggers re-discovery instead of failing. See Antigravity.

Cursor composer fast mode and built-in tool calls

Fixed — Composer fast mode is sent as model metadata rather than encoded into the model id, and a turn containing a built-in tool call is surfaced instead of dropped. See Cursor.

0.40.2 — 2026-09-05

antigravity-cli rejects caller-supplied tools instead of ignoring them

Changed · Breaking, effective 0.40.2 — Affects callers that send a non-empty tools array (unless tool_choice is none), or a tool_choice of any or tool, to the antigravity-cli provider. It runs the local agy binary, which resolves its own tool calls and never returns a tool_use block, so such a request used to return a text-only 200 that silently ignored them; it is now refused with a 400 invalid_request_error. Send the task as a plain prompt, or route the model at the native antigravity or gemini provider, which do forward tools. A tool_choice of auto with no tools is unaffected. See Antigravity.

Codex client identity bumped to 0.153.3 for gpt-6-astra

Fixed — The advertised Codex client identity was raised to 0.153.3, which the backend requires to serve gpt-6-astra. See ChatGPT / Codex.

In-stream rate_limit_exceeded is classified as 429

Fixed — An in-stream rate_limit_exceeded event is now classified as a 429 and a misalignment steer is forwarded to the client rather than discarded.

Gemini tuple-style array schemas

Fixed — The items schema Gemini requires is now derived from a tuple-style array definition instead of being sent in a form the backend rejects.

0.40.1 — 2026-09-03

Antigravity resolves model ids from the live catalog

Fixed — Model ids are resolved against the account’s live catalog, and a base_url pinned to the production host is redirected, which together clear the spurious 429 “quota” refusals that made the provider unusable. Antigravity’s catalog is per-account and changes without notice, so ids are no longer hardcoded. See Antigravity.

0.40.0 — 2026-09-02

Codex account quota from the wham usage endpoint

Added — shunt polls the wham usage endpoint for Codex account quota, so pool state is populated without waiting for traffic to return x-codex-* headers. See Codex Multi-Account.

Antigravity reaches the daily backend with the agent envelope

Fixed — Requests now carry the full agent envelope and effort-suffixed model ids against the daily backend, the combination the service actually accepts. See Antigravity.

Adjacent Gemini user turns are merged

Fixed — Adjacent user turns are merged so tool pairing survives a mid-conversation system message.

0.39.2 — 2026-09-01

A never-selected account keeps its needs-relogin verdict

Fixed — An account no provider table has ever selected now reports needs_relogin alongside has_state: false, because the admin refresh probe records its verdict by store name. See HTTP Endpoints.

0.39.1 — 2026-08-31

Claude account status is reported by credential kind

Fixed — Account status is derived from the credential kind rather than raw expiry, so a dead credential is reported as needing re-login instead of merely expired. See Anthropic Multi-Account.

0.39.0 — 2026-08-29

Stale near-quota accounts are re-probed opportunistically

Added — An account paused near its quota is re-probed when the opportunity arises, so it returns to rotation as soon as its window resets rather than waiting out a fixed cooldown. See Anthropic Multi-Account.

Pool plans are keyed by account identity

Fixed — Plans are keyed by account identity and the backing file read is single-flighted, so concurrent readers no longer attribute one account’s plan to another.

Deferred tools are stripped on non-Anthropic Messages models

Fixed — Deferred-tool blocks are removed before forwarding to a non-Anthropic Messages upstream, which does not understand them. See Model Aliases.

Reset-less quota marks have a bounded lifetime

Fixed — A quota mark that arrives without a reset timestamp now expires on its own instead of pausing the account indefinitely.

0.38.0 — 2026-08-25

kind = "antigravity" is the native HTTP upstream

Changed · Breaking, effective 0.38.0 — Affects any config with an antigravity provider. The name now means the native HTTP upstream; the local agy subprocess transport moved to kind = "antigravity_cli" (built-in provider antigravity-cli). A config still carrying the old meaning is refused by name rather than retargeted, and a routed antigravity provider with no credential refuses to start. Rename the table to antigravity_cli to keep the subprocess transport, or add a credential to adopt the HTTP one — see Antigravity.

kind = "antigravity_cli" is deprecated

Deprecated — The local agy subprocess transport is deprecated in favor of the native HTTP upstream (kind = "antigravity"). It still works; migrate when convenient. See Antigravity.

A shared credential slot holding a shunt credential is removed entirely

Changed · Breaking, effective 0.38.0 — Affects only callers that send authorization or x-api-key more than once in a single request. When shunt’s own credential shares a slot with a genuine upstream credential, the whole slot is now removed, so the upstream credential is dropped with it. Send the upstream credential in a slot of its own. See Sharing a Gateway.

Read/write admin keys, and the spend surface moved to [server.spend]

Added — [server.admin] gained read_keys and write_keys: a read key passes every admin GET and is refused with 403 on every mutation. The spend-limit surface moved to its own [server.spend] table. See [server.admin].

shunt gateway login, token helper, and Claude Code launcher

Added — shunt gateway login, shunt gateway token, shunt gateway claude and shunt gateway logout let a client authenticate against a shared gateway over a device flow and launch Claude Code against it. See Gateway Login and the CLI.

Kimi Code OAuth as a first-class subscription upstream

Added — A Kimi Code subscription can be used directly over OAuth, rather than only a Moonshot API key. See Kimi.

[server.gateway.session] JWT configuration

Added — Gateway session JWT parameters are configurable under [server.gateway.session].

${VAR} and ${file:} references in config, with redacted secrets

Added — Config values resolve ${VAR} environment and ${file:…} path references, and secret fields are redacted from debug output so a dumped config cannot leak credentials. See Configuration Reference.

Spend-limit admin API

Added — The first stage of the spend-limit admin API landed under [server.spend].

Account plans exposed in pool state

Added — Pool account objects may carry an optional plan string, refined toward a more precise value by a profile lookup when one is available. See HTTP Endpoints.

Codex client surface synced to openai/codex 0.148.0

Changed — The Codex client identity and request surface were synced to upstream 0.148.0. See ChatGPT / Codex.

Gateway JWTs and client tokens never reach an upstream

Security — A gateway JWT is now stripped by shape rather than only when it authenticates, and is never forwarded in either credential slot; a static [server.auth] token is stripped by value; and an inbound x-api-key is stripped on the Codex passthrough. Every credential-slot forward site routes through one shared strip, so the accept and strip rules cannot drift apart. See Sharing a Gateway.

shunt check runs the routed-Antigravity credential guard

Fixed — shunt check now applies the same credential guard that startup does, so a routed antigravity provider missing its credential is reported before the server is started. See the CLI.

0.37.0 — 2026-08-13

Opt-in upstream Statuspage polling

Added — [server.status] polls configured provider Statuspage sources and exposes the most recent indicator, description and incidents for observation. It is never consulted by routing or failover. See [server.status].

grok-4.6 and a refreshed Grok model surface

Added — grok-4.6 was added and the Grok model surface refreshed. See xAI / Grok.

0.36.0 — 2026-08-11

agy runs in agentic mode with streaming and sandboxing

Added — The Antigravity CLI transport runs in agentic mode with streamed output, sandboxing, and a discovered effort matrix. See Antigravity.

0.35.0 — 2026-08-10

The inbound body cap defaults to 32 MiB

Changed · Breaking, effective 0.35.0 — Affects anyone sending request bodies between 32 and 64 MiB, typically large file or image requests. The cap now defaults to 32 MiB instead of the previous hardcoded 64 MiB, and requests in that range return 413 request_too_large. Raise [server.limits] max_request_bytes to restore the old ceiling — see [server.limits].

HTTP tuning configuration surface

Added — [server.limits], [server.timeouts] and related tables expose body, header, URL and timeout tuning that was previously hardcoded. See Configuration Reference.

Navigation

Type to search…

↑↓ navigate↵ selectEsc close