Extra HTTP headers, typed by the user, ride on every request magpie makes
to a plain key+URL provider — forwarded calls, connectivity tests, and
model-list fetches — applied after the auth headers. Presets and signed-in
agent accounts ignore them. Editable in the GUI (with a JSON value mode) and
via the CLI as header.X-Foo=bar.
Logging out of Claude Code can leave its credentials behind; claude auth status
now decides. Removing a Claude, Codex or Copilot account hides it from magpie
(the agent stays signed in); Add it back, or magpie provider add <id>, restores it.
Through magpie, each tier follows the main model until it is given one of
its own (ANTHROPIC_DEFAULT_*_MODEL; haiku also sets ANTHROPIC_SMALL_FAST_MODEL).
The GUI shows them under one tiers menu; the CLI takes magpie claude haiku <model>.
usemagpie.ai/docs/import explains import links, with a link builder and
buttons to copy; usemagpie.ai/import#… turns the fragment into a
magpie:// link and offers the download. install.sh registers the scheme
on Linux.
A vendor or relay can hand out a ready-made provider as a link. The app
registers the magpie scheme (Info.plist on macOS, HKCU on Windows, a
.desktop handler on Linux), a second launch hands the link to the running
one, and the window shows what the link would add, with the hosts the
prompts and key would go to, before anything is saved. `magpie import`
does the same in a terminal.
OpenCode's gateway turns away requests that do not name their conversation
in x-opencode-session ('Request is missing x-opencode-session and cannot be
routed efficiently'), and magpie never sent it. Requests to opencode.ai now
carry the agent's own session id (OpenCode's x-session-affinity, Pi's,
Codex's session_id, Claude Code's) or, when the agent sends none, an id
derived from the conversation's first user message, stable across turns;
the provider test sends one too. OpenCode's docs ask exactly this of
third-party clients, along with their own User-Agent, which magpie already
sends.
Pi shows xhigh and max only for models whose thinkingLevelMap names them,
and magpie wrote just "reasoning", so a model whose top level is max (GLM-5.3,
DeepSeek) stopped at high and a max setting was sent as high (#5). Checked on
the wire: --thinking max sent reasoning_effort high before, max after. Picking
the model or thinking level in magpie again rewrites Pi's models.json.
Pi sends the developer role to reasoning models; relayed unchanged, DeepSeek
rejected every request (422 unknown variant `developer`), so Pi got no reply
at any thinking level above off (#1). Every backend, OpenAI included, accepts
system.
The download button follows the visitor's OS, a platform list sits under
the final call to action, /download/{windows,linux}[-arm64] redirect to
the builds, and install.sh installs the Linux desktop app, with a menu
entry, when WebKitGTK 4.1 is present.
The Windows app cross-compiles (WebView2, no cgo) as a GUI program with an
icon, version info and a DPI-aware manifest; run from a terminal with a
command it borrows the console. The Linux app links GTK 3 and WebKitGTK
4.1. Off the Mac the app updates its own binary from its own build:
downloaded in the background, swapped in on restart or quit, and the
relaunched process waits for the old one before taking the gateway. The
window leaves room for traffic lights only on a Mac.
The screenshots still showed the row's + and an older control column. New
shots, dark and light, off a throwaway demo config (the same DeepSeek/Kimi/
GLM/Qwen/MiniMax/OpenRouter/Anthropic/Gemini set). The panel is a hair taller
now, so its height goes 470 -> 476.
The lined-up columns only suit the wide window: in the narrow menu bar
panel a solo control spanning both columns is what keeps a long model id
readable, so scope the fill to body.window and leave the panel as it was.
The controls hugged their text and right-aligned, so a model pill sat in
a different place on every row and the chevrons never lined up. They now
fill a fixed two-column grid — model (or large model) on the left, the
second setting on the right — so every chip and chevron lines up down the
list. A single control keeps the left column, so the model always sits in
the same place.
The Agents field is now a summary of who is on the provider: point a new
agent at it from the Agent tab's picker instead. Removes the row's +, the
editor's list of capable agents, canUse, and the strings they used.
The Agents field listed every agent that could use the provider, most of
them sitting there doing nothing until clicked. A normal edit now shows
just the agents pointed at it, and hides the row when there are none; the
ones that could be added stay behind the row's +, which opens the same
editor in an add mode.
A relay with several endpoints is one preset now: a Region selector
(Auto / Global / China Mainland) swaps the provider's base URLs, and the
endpoints list follows the choice. AiHubMix's key page moves to
console.aihubmix.com/token.
The rest is a pass over the gateway, usage and provider views: a copy
button that answers on itself, a cache hit rate in the usage tiles, the
chart's peak and last date no longer overlap, the tabs sit level with
the logo, the provider key column holds a line, pickers opened from the
editor show above its modal, and buttons drop the native webkit look so
their labels centre.
OpenRouter serves a second, namespaced catalogue from /v1/models as
soon as it sees anthropic-version, so sending that header on the chat
fetch cached ids like anthropic/xiaomi/mimo-v2.6-pro-ultraspeed[1m]
that the chat endpoint then rejected. Send it only when the fetch is
for the Anthropic protocol, where the official API requires it.
The site leads with what magpie is for: Codex on DeepSeek, Claude Code on
Kimi. New screenshots (Codex's picker, the panel, Providers), a diagram of
the gateway, shared subscriptions, a light/dark/system theme switch, a new
OG image, and links to the source.
site/ is the website: a static page plus a worker that turns the newest
release of yetone/magpie-releases into an update feed (/api/latest, with
every file's SHA-256), stable download links and an install script.
The app asks the feed at start-up and every six hours, downloads a newer
version in the background, and installs it on Restart to Update or on
quit. A download must match its checksum and be signed by the same team
as the app it replaces. `magpie update` does the same from a terminal and
replaces a bare binary in place.
A signed-in Claude Code is now offered as a provider (claude/…) like Codex
and Copilot. Anthropic classifies another agent's system prompt as
third-party traffic even over Claude Code's OAuth, so magpie drives the
real local claude binary for every generation: the caller's tools are
bridged in over MCP (magpie claude-mcp-helper), and tool results resume
the same Claude Code turn. Token counting is estimated locally so the
OAuth token takes no side path.
No model list is compiled in any more. The built-in catalog, preset
defaults and Claude Code's alias list are gone; the picker shows the
models.dev catalog (refreshed in the background when stale) layered with
each vendor's own /models answer, and signed-in accounts fetch theirs at
start-up. Whether a model rejects temperature/top_p now comes from
models.dev rather than a name prefix.
The gateway retries a Chat request on the Responses endpoint when the
model is Responses-only, and remembers that. Recent calls keep the first
256 KB of request and response bodies, viewable in the call list. The
Usage tab shows subscription allowances (Claude, Codex, Copilot) as the
vendors report them.
On start-up magpie now renames what dial wrote into the agents' files: a
model spelled dial/… becomes magpie/… (which also writes the magpie
provider entry), and the dial provider entry, Codex's [model_providers.dial]
table and dial-models.json, and Claude Code's bearer token go. Once nothing
says dial it changes nothing.
The product, module path (github.com/yetone/magpie), binaries, env vars
(MAGPIE_ADDR, MAGPIE_DEV_UI, MAGPIE_THEME, MAGPIE_DEBUG), config and cache
folders (~/.config/magpie, ~/.cache/magpie), bundle id (com.yetone.magpie),
gateway provider id and token, and every UI string now say magpie.
On first run magpie copies ~/.config/dial and ~/.cache/dial to the new
folders when they don't exist yet (copy, not move, so a still-running dial
keeps working; the old folders can be deleted by hand later).
The logo is a small round magpie in profile: one path for the header and
the tray, and the app tile adds the white belly and the blue-green tail.
The header mark is drawn in ink rather than the accent colour, which
fought the text in light mode.
The gateway glyph is gone. The mark is now a kingfisher in profile, facing
the wordmark: big head, dagger beak, short tail, one line for the wing, the
eye a hole. The header draws it in ink rather than the accent, which fought
the text in light mode. The icon generator rasterizes the same SVG path
(flattened cubics, even-odd fill), and the app tile is kingfisher blue.
fswatch swallows SIGINT, so the shell went round again instead of
exiting; a trap now stops the child and leaves. The loop also kills
only its own dial-dev rather than every one on the machine.
The editor grid's 1fr column had an auto minimum, so a long endpoint
error pushed the dialog past the window edge.
The editor no longer unfolds under a row: it lifts over the page as a
dialog with a blurred backdrop, closed by Escape, the backdrop or Cancel.
Its head names the provider and links to its site, so it stands alone.
Motion, kept restrained: a single ease (quick start, soft landing), pills
with one thumb that glides to the chosen option (nav, appearance,
language, usage period, the editor's API switch), views that settle in,
buttons that give under the press, and a theme change that crossfades
instead of snapping. Reduced-motion users get none of it.
A gear in the header opens Preferences: appearance (system/light/dark)
and language (system/English/中文), applied at once and kept in
~/.config/dial/settings.json. The About card shows the version, config
folder (copy/open) and gateway URL. Every visible string goes through
t() with a Chinese table in i18n.js.
The panel gets a tonal ladder of its own (bg, card, pill) with hairline
edges and a legible --faint, instead of the pale flat wash.
The gateway gets its own tab: status and URL, a connect card with the base
URL, key and a model id as copy buttons, and a highlighted snippet in
shell, curl, Python or Node for each of the four APIs; then every model id
and the recent calls. Providers rows show signed-in accounts (ChatGPT Pro,
GitHub) with an editor for their model picks, and a note explains why a
signed-in Claude Code is not listed.
A Codex (ChatGPT) or Copilot login is a subscription with models behind
it, so dial offers it as a provider: every other agent can use its models
through the gateway. The agent's own credential file is read each time,
tokens are refreshed the way the agent does it, and only the model picks
are stored. Claude Code is found but deliberately not offered (Anthropic's
terms), and the CLI and API say so.
The gateway signs upstream requests through the provider (Sign/Prepare),
translates non-streaming requests for backends that only stream, and now
recognises an event stream by its body when the vendor sends no
Content-Type, which is what the ChatGPT backend does.