911Liam's auto mode, on claude-sonnet-5.5 through a relay, got 400 "To
turn thinking off on this model, send "thinking": {"type":
"between_tools"} instead of {"type": "disabled"}". Claude Code turns
thinking off for its classifier and side queries unless it knows the
model refuses that, and a model reached through a gateway can fall
outside what it knows. magpie forwarded the disabled as it came, and
turns thinking off itself too (an effort of none fitted, a budget that
doesn't fit, thinkingOffUnlessAsked for other vendors' models).
thinkingOffAsTaken, in forwardOnce next to adaptiveThinking, so that
relayed requests, count_tokens, magpie's own thinking-off and retries
all go through it, follows Anthropic's rules for each model. It reads
the model's name as the vendor gives it, from the body, or from the path
for Bedrock and Vertex.
- Sonnet 5.5: between_tools with no other field, and xhigh or max asked
as high (between_tools is a 400 above high).
- Opus 5.5, Fable 5.x and Mythos 5.x refuse disabled at every effort.
Thinking is left out, effort is low unless one was asked, and
classifierRoom is added to a reply limit below it, as Claude Code
itself does for these models.
- Opus 5 and Haiku 5.5: disabled is kept, with xhigh or max asked as
high.
- between_tools sent to any other Claude goes as disabled, or with no
thinking where disabled is refused too.
Other vendors' models, Sonnet 5, Opus 4.8 and older, and lines later than
these go byte for byte as they came. A Sonnet 5.5 under a name these
rules can't read is asked again with between_tools, once, on the 400
that asks for it (asksBetweenTools). A refusal of disabled at any effort
(thinkingOffRefused) is asked again with thinking left to the model,
beside alwaysThinks.
TestAdaptiveOnlyModelsNeverGetABudget's "disabled stays" case pinned
disabled for claude-opus-5.5, which the vendor refuses. It now checks an
older Claude keeps disabled and Opus 5.5 is sent none.
Verified:
- Tests:
- TestThinkingOffAsTheModelTakesIt and
TestThinkingOffLeavesOtherModelsAlone (deepseek, glm-5.3, kimi,
Sonnet 5, Opus 5 at high, Haiku 5.5, Opus 4.8 at max, Sonnet 4.6,
Haiku 4.5, Claude 3.7, dated Sonnet 5 and Sonnet 6 unchanged).
- TestClaudeFiveFiveThinkingOffOnTheWire: a fake vendor answers with
the reporter's literal 400, covering the classifier body,
count_tokens and the retry.
- Without the forwardOnce call, the wire test's Sonnet 5.5, Opus 5.5 and
count_tokens cases and the Opus 5.5 adaptive case FAIL. Without the
retry, its unreadable-name case FAILs.
- Live, through this build's `magpie serve` under a sandbox HOME with
the aihubmix relay key, in the classifier's shape (max_tokens 64,
temperature 0, stop </block>, thinking disabled):
- claude-sonnet-5-5 answers 200 at default and xhigh effort (sent
straight to aihubmix with disabled it gives the reporter's 400);
- count_tokens 200;
- claude-opus-5-5 200;
- claude-haiku-5-5 at max 200;
- claude-sonnet-5 200.
- gofmt -l, GOOS=linux and GOOS=windows go vet -tags nogui
./internal/gateway, and go test -tags nogui ./internal/gateway under a
temp HOME with pinned caches.
magpie accounts import; the box says the source tool is signed out (#1453)
magpie accounts import; the box says the source tool is signed out (#1453)
magpie group set <id> levels=low,medium,high,xhigh, levels= clears; TUI l; GUI group editor's Levels: its models' shared / named) is offered instead in /v1/models, Codex's catalog, Pi and the rest; only levels magpie knows are taken, stored lowest first; a group in a group that names its own offers them for its models; unset is as before. A member without the level asked is sent its nearest, as it already was. The GUI's group save also keeps a family set from the CLI. TestGroupLevelsOverride, TestGroupLevelsReachAgents, TestGroupLevelsNamed (passthrough and translated: medium→high, xhigh→max on the low/high/max member, as asked on the one with all), TestGroupSetLevels and routing-levels.test.cjs (Chromium, WebKit, en/zh) fail without the change. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build, go test -tags nogui ./... pass (TestUserPath, a known flake under load, passes alone); click-scroll, old-webkit, routing-effort(-row), routing-levels, settings-groups GUI tests pass.
magpie group pick <id> <model> (or group set <id> pick=<model>, a bare model id when it names one member) picks from the CLI; magpie groups and group show mark the pick, the TUI shows "manual → model". A renamed provider or model renames the pick. TestManualGroup, TestGroupPick and routing-manual.test.cjs (Chromium, WebKit, en/zh) fail without the change. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build, go test -tags nogui ./... pass; click-scroll, old-webkit, routing-levels, routing-steady, panel-routing, settings-groups pass.
magpie tray, autostart's argument, so the new version came up as a tray icon however the update was asked for; the Mac reopens its .app and was fine. The window's Update pill and Settings' "Restart to update" send the tab they're on, the new process starts as magpie gui <tab>; the tray menu's Restart to Update brings the window back if it was open and keeps to the tray if not; autostart stays tray. magpie gui <tab> / magpie app <tab> open the window on that tab, and hand it to a magpie already running. The MAGPIE_REPLACES handover is unchanged: the new process waits for the old one before its single-instance lock. Tested with TestRelaunchArgs and TestRelaunchBinaryArgs (a script in magpie's place is started with gui settings <pid> / tray <pid>); go vet, go build (GUI and -tags nogui, GOOS=linux, GOOS=windows), go test -tags nogui ./... pass. Not tried: a real restart to update on Windows or Linux.
magpie accounts import; the box says the source tool is signed out (#1453)
magpie model output (#1438, yhong91)
magpie model output (#1438, yhong91)
559ce021 (#203) had a custom name keep " · <provider>" after it like any other, so "Opus 5.5" read "Opus 5.5 · Claude Code" in every list Labels feeds (Codex's model_catalog_json and the gateway's Codex /models, Pi's, OpenCode's, ZCode's, OMP's, Muse's), while #92 had been promised the name as written. Both are kept: the setting is now Off / Not on names I set (自定义名称不带供应商) / On. On stays the default and keeps #203's behaviour, so nobody's list changes unasked; own leaves a name the user gave as it is and a vendor's name with its provider's; off is #335's plain names. Stored as plainOwnNames beside plainNames, so a settings.json of before reads as it did (plainNames: true is off). POST /api/settings/plain-names takes mode on|own|off (a body of on alone still works), magpie model suffix on|own|off, a Settings save keeps it, and /v1/models' magpie_label now follows the setting through Labels as the agents' lists do. The row's hint is one line that fits (en, zh), and its zh name says 供应商 as the rest of the app. Prompts and headers are unchanged. TestSuffixMode, TestSuffixModesReachAgentFiles (Codex model_catalog_json and Pi models.json), TestModelsListSuffixModes (/v1/models magpie_label) and model-suffix-own.test.cjs (Chromium and WebKit, en and zh) fail without the change; TestModelName and TestModelNameAndLevelsReachAgentFiles keep #203's assertions. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build, go test -tags nogui ./... pass (TestConfiguredModelsAdvertiseImageInput load-flaky, passes alone); plain-names, click-scroll, old-webkit pass.
magpie omp auto sets omp's thinking to auto, and the panel's effort slider shows a level it doesn't list as it is (#339)
until codex exec …; do magpie quota wait codex || break; done) — it reads the vendors itself as magpie quota does, gateway running or not (provider.Allotted: the subscriptions' and plans' readings, no key balances; AskUsage has each look wait for a new reading, and only a wait for Claude runs Claude Code's /usage, through AskClaudeUsage, which now calls it). An account has allowance when routing's usedUp says so (no window that stops it, every model, at 100%; exported as provider.UsedUp), and BackAt is when the last of those windows starts again. While all are used up it sleeps to the soonest reset plus 30s, at least a minute and at most ten, saying on stderr what it waits for and until when; an allowance it can't read (an error, or only the last reading kept in its place) is asked again after 1, 2, 4, 8 then every 10 minutes. A provider's accounts switched off or signed out in magpie are left out, as the agent is never moved to them; an account is named by its user, or <provider>/<user> when two subscriptions share it. --timeout <duration> exits 1 when it passes first, --quiet says nothing, an unknown name or flag exits 2 (main now honours an exitError's code) and Ctrl+C 130. The loop takes its reading, clock and sleep as functions: quota_wait_test.go runs it on a fake clock (already available → no sleep; used up → 10m, 10m, then to just past the reset; one account named ignores another's room; a reset under a minute away is a minute; --timeout ends at the deadline after its last look; unreadable usage backs off and the wait goes on once read; an untold reset is looked at every 10 minutes; an off account is passed over; Ctrl+C), plus resolving names and the usage errors. Help in magpie quota's and magpie's usage, and the README. go vet, builds (darwin, GOOS=linux, GOOS=windows), the new tests and ./internal/provider pass; not run against real accounts.
magpie
Every agent's model. One place.
Claude Code on Kimi. Codex on DeepSeek. Gemini CLI on GLM. OpenCode on your ChatGPT plan.
Switch any of them from the menu bar. One local gateway serves them all,
and when a quota runs out, it quietly moves on to the next account.
Download · Docs · Reference · Plugins · Discord · English · 简体中文
45+agents, one list |
4wire APIs, one gateway |
5routing modes |
0config files edited by hand |
Is magpie for you?
Each agent keeps its model in its own file, in its own format, with its own keys and base URLs. A subscription you pay for works in one agent and nowhere else. magpie puts all of that behind one app and one local gateway:
- Pick any model for any agent from one list. magpie edits the one key that matters in the agent's own config.
- Use one provider everywhere: an API key, a local model, or the Claude, ChatGPT, Copilot, Gemini or Grok plan you're signed in to.
- Keep going when a quota runs out: a routing group moves to the next account or model, and the agent never sees the error.
It's for you if you use more than one agent, more than one provider, or more than one account. If you use one agent on its vendor's own plan and that's enough, you don't need it.
Runs on macOS, Windows and Linux (menu bar app, window, TUI, web UI and CLI), in Docker, and on Termux.
Quick start
1 · Install. Download the app from usemagpie.ai, or run:
curl -fsSL https://usemagpie.ai/install.sh | sh
Mac builds are signed and notarised, and every build updates itself. Behind a firewall, use --proxy or --mirror. Or go install github.com/yetone/magpie@latest, or the Docker image.
2 · Add a provider. Open magpie and go to Providers → Add provider. Pick a preset and paste a key, or sign in with a subscription.
3 · Pick a model for each agent on the Agents page. Start a new session and it's on the new model.
Or do it all from the terminal:
magpie provider add deepseek sk-… # a preset needs only the key
magpie claude deepseek/deepseek-v4-pro # Claude Code on DeepSeek
magpie codex moonshot/kimi-k2.5 # Codex on Kimi
magpie group add "Opus anywhere" models=claude/claude-opus-5-5,copilot/claude-opus-5.5 routing=smart
magpie claude group/opus-anywhere # fails over between subscriptions
magpie save work && magpie use work # profiles
magpie quota # what's left on every plan
magpie tui # the whole thing, in a terminal
Supported agents
|
Claude Code · Claude Desktop · Codex · Gemini CLI · Antigravity CLI · OpenCode · OpenChamber · MiMo Code · Pi · oh-my-pi · Aside · OmO · Goose · Cursor CLI · Cursor Private Inference · Zed · VS Code Chat · VS Code Insiders · VSCodium Chat · JetBrains Air · Copilot (JetBrains) · Copilot CLI · Crush · DeepSeek Harness · Reasonix Studio · Command Code · fx · Devin · Hermes Agent · Mister Morph · Kimi Code · Qwen Code · Muse Code · Empryo · MiniMax Code · Droid · Cline · Qoder · Qoder CN · Grok Build · ZCode · WorkBuddy · CodeBuddy Code · Pencil · T3 Code · OpenHanako · AtomCode · Alma · Cindy |
magpie shows only the agents installed on your machine; setup notes for some of them are in the reference. Anything else that takes a base URL can use the gateway too:
export OPENAI_BASE_URL=http://127.0.0.1:3425/v1 OPENAI_API_KEY=magpie
export ANTHROPIC_BASE_URL=http://127.0.0.1:3425 ANTHROPIC_API_KEY=magpie
export GOOGLE_GEMINI_BASE_URL=http://127.0.0.1:3425 GEMINI_API_KEY=magpie
How it fits together
The gateway at 127.0.0.1:3425 speaks OpenAI Chat, OpenAI Responses, Anthropic Messages and Gemini, and translates between them, streaming, tool calls and reasoning included.
flowchart LR
subgraph A["Your agents"]
direction TB
a1["Claude Code"]
a2["Codex"]
a3["Gemini CLI"]
a4["OpenCode · Zed · Cursor CLI · 40+ more"]
end
subgraph M["magpie · 127.0.0.1:3425"]
direction TB
g["Gateway<br/>Chat · Responses · Messages · Gemini"]
r["Routing groups<br/>fail-over · smart · pace"]
p["Plugins & middleware"]
g --> r --> p
end
subgraph P["Your providers"]
direction TB
p1["API keys<br/>DeepSeek · Kimi · GLM · OpenRouter …"]
p2["Subscriptions<br/>Claude · ChatGPT · Copilot · Gemini · Grok"]
p3["Local models<br/>Ollama · LM Studio"]
end
A --> M --> P
What it does
Any model, any agent
Click a value and a searchable list opens: every model of every provider you added, as provider/model. The agent's config is rewritten atomically, and its comments, order and formatting stay as they were. Profiles save every agent's setup under one name ("Budget", "Focus") and switch them all back in one move. Each agent can also have its own short list of models; a profile keeps that list too.
|
|
Providers
Pick a preset, paste a key. Model lists come from the vendor, with names and reasoning levels filled in from models.dev, so a model released this morning is in your picker on the next refresh.
Presets include Anthropic · OpenAI · Google Gemini · DeepSeek · Kimi · Zhipu GLM · MiniMax · StepFun · Qwen · Baidu Qianfan · Tencent Cloud · Huawei Cloud MaaS · Volcengine Ark · Mistral · Groq · xAI · OpenRouter · Together · Fireworks · SiliconFlow · NVIDIA NIM · ModelScope · Ollama · LM Studio … and any OpenAI- or Anthropic-compatible URL.
Import brings in the providers from CC Switch, Claude Code, Codex and Alma. Add to magpie links let a provider's website hand its config to magpie in one click. Each key and each account can go through a proxy of its own.
Subscriptions
An agent you're signed in to is a subscription with models behind it, so magpie offers it as a provider to every other agent. Add several accounts per subscription and magpie fails over between them.
- Claude: drives the real local
claudebinary and bridges your agent's tools over MCP - Codex / ChatGPT: your ChatGPT plan's models, in every other agent
- GitHub Copilot, Gemini (Code Assist), Antigravity, Grok (SuperGrok) and more
- Any OpenCode auth plugin or pi package from npm
Daily warm-up starts each Claude and ChatGPT account's 5-hour window at the times you choose, or the moment the last one resets.
Routing groups
A routing group is several models an agent picks as one, such as group/daily-coding. The gateway spreads requests over every member's keys and accounts:
| Mode | What it does |
|---|---|
smart |
Of the subscriptions with quota left, use the one that renews soonest, so less is wasted at the reset |
order |
Use the first model until it can't answer, then the next |
rotate |
Move to the next member on each turn |
usage |
Use the least-used member first |
pace |
Use the account with the most of its week left per hour until it resets |
A conversation stays with the account that answered it while the vendor's prompt cache is worth keeping. Groups can contain groups. Intent routing has a small model of your choice read each new turn, so tests go to the strong model and quick questions to the cheap one. The Routing view shows every decision live.
Plugins
magpie plugin add opencode-gemini-auth # an OpenCode plugin from npm
magpie plugin add pi-antigravity # a pi package, the same way
magpie plugin login google-plugin # its own sign-in flow, in magpie
Plugins run on Bun, downloaded the first time one needs it. A plugin signs in, lists its models and makes each request; agents use those models like any other provider's. Browse magpie-community/plugins, or write your own.
A plugin can also be gateway middleware: JavaScript that sees what every agent sends and gets back. onRequest can rewrite a request or turn it away, onEvent sees each streamed event, onResponse the whole reply. A hook that throws or runs too long leaves the request as it was.
// alias.middleware.js — magpie plugin add ./alias.middleware.js
export function onRequest(body, ctx) {
if (body.model === "fast") return { ...body, model: "deepseek/deepseek-chat" };
}
Ready-made middleware, most of it what New API does for its channels, with the same JSON
| Package | What it does |
|---|---|
param-override |
New API's param_override: set, delete, move or rewrite request fields, under conditions, or turn a request away |
model-map |
New API's model_mapping: send a model under another name; replies keep the name asked for |
system-prompt |
Your system prompt on every request, or some agents' or models' |
word-guard |
New API's sensitive-word filter: turn away or mask words in what users send, and in replies |
think-tags |
Take <think>…</think> out of replies, or put reasoning_content into them |
magpie plugin add @magpie-community/middleware-model-map
magpie plugin options model-map '{"mapping": {"fast": "deepseek/deepseek-chat"}}'
Find them under Plugins › Discover › Gateway middleware. See Gateway middleware.
Usage and cost
| Tokens and cost | Tokens, cache reads and writes, reasoning and calls, with cost at list price in dollars or yuan; set your own price for any model |
| Quota | Balances and quota windows for every key, plan and account (magpie quota), and a reminder before a window renews with much of it unused |
| Sessions | Every agent conversation with its cost and title, reopened in your terminal with one click |
| Context | How full each request's context window is, how much came from the cache, and what fills it |
| Bills | By account and by upstream key, and OTLP export to your own observability stack |
Sharing
| Local network | Turn on Share on local network and give each client a named gateway key with its own daily, weekly or monthly token and cost limit |
| Remote magpie | A laptop uses the providers, accounts and groups of the magpie on your desktop, and still wires its own agents |
| Docker | Run ghcr.io/yetone/magpie on a server or a NAS and manage it from the web UI |
| Sync | Back up to a file, or sync machines over WebDAV (Nutstore, Nextcloud…) or S3 |
Also
- Library: write instructions, MCP servers and skills once; magpie writes them into each agent's files in its format, and removes only what it wrote.
- Images and video: an image tool for any agent over MCP, with the model you choose, and videos with a Grok subscription.
- Agents kept current: the Agents page shows each CLI's version, updates it the way it was installed, and gives the commands for the ones you don't have.
- WSL: on Windows, agents inside WSL distros are wired too, and their sessions counted.
- Keep awake, light and dark, and your theme's look on Omarchy.
Documentation
| Get started | The guided tour |
| Reference | Every agent, provider option, gateway endpoint, CLI command and file |
| Plugins | Use plugins and write your own |
| Intent routing | Route each turn by what it asks for |
| Import links | "Add to magpie" buttons for provider websites |
| Remote magpie | Use one magpie's providers and groups from your other computers |
| Docker | Run magpie on a server or a NAS |
Privacy
Your prompts, replies, keys and accounts go only to the providers you use. Once a day a released magpie tells us it is in use: a random id, its version and system, and which agents, providers and models it is used with, by magpie's own ids (a provider you added yourself is only custom), and for each partner listed first in the add sheet, how many times a day it was shown, opened and added (counts only). No names, URLs, accounts, keys, prompts or usage. Turn part or all of it off in Settings → Privacy, or with DO_NOT_TRACK=1. What is sent, exactly.
Community
Questions, ideas, or a model that won't show up? Tell us on Discord. That is where feedback goes.
This repository doesn't take pull requests. Only maintainers can open them. If you'd like a fix or a feature, describe it on Discord and we'll build it.
If magpie saved you from editing one more config file, a ⭐ helps others find it.