* agent: Ante takes magpie as a provider in ~/.ante/catalog.json Ante (antigma.ai, AntigmaLabs/ante) is asked for in #1179. Its catalog is ~/.ante/catalog.json ($ANTE_HOME moves the folder), merged on top of the providers it ships: a providers map keyed by the id --provider takes, each with base_url, wire_style (AnthropicMessage, OpenAiCompatible, OpenAiResponse or Gemini), an optional auth, and preferred_models, the ids its model picker shows (docs.antigma.ai, reference/catalog-reference). magpie adds the entry "magpie" at the gateway's /v1 on OpenAiCompatible, which is the wire style Ante speaks Chat Completions with and what the gateway takes every model on, and lists magpie's models in its preferred_models. The user's own providers and the models section are left as they are, and magpie's entry goes again when magpie steps out; a file magpie made goes with it. No auth block is written. The gateway listens on loopback and lets any token in from this machine (gateway.Token's own comment, lan.go's identifyCaller: "Loopback takes any token"), and Ante counts a provider with no auth as authenticated. A bearer env_key would mean putting the gateway's key into Ante's environment, which the user would have to do themselves -- the same decision Empryo's entry makes, which sends no key of the user's either. A gateway shared on the local network is another matter, and the same one every agent magpie wires has. Two things are deliberately left off a model's entry. A routing group is not told what it reasons at: which member answers, and what that member takes, is the group's own to decide per turn, and magpieModels sets no APIs for a group for the same reason. And support_vision is never written: Ante takes a model as seeing images unless told otherwise, and what magpie knows is only as good as a provider's own list -- a relay's models are often not described at all, so writing false would have Ante drop the reader's images before the gateway, which describes them to a model that can't see them itself (provider.Described). No other agent magpie wires declares it either. Ante ships macOS and Linux builds alone and suggests WSL on Windows, so the Windows machine's Ante is usually the one in a distro: wslKinds gains it beside Empryo, which also means the gateway address Ante is pointed at is the one that distro reaches magpie on (place.base), and a distro not known to be in mirrored networking gets the notice it already gets for the others. TestAnte covers a user's own providers and models section kept as they are, magpie's entry added and taken away, Sync repointing it, and a file magpie made going again. TestAnteKeepsTheUsersFile covers a catalog magpie can't parse costing magpie's provider and not the user's. TestAnteGroupSaysNoCapab ilities covers a group declaring neither effort nor support_vision. TestAnteEfforts covers the ladder: Ante's has no "none" or "minimal", its two lowest, so both are its "min", and the rungs come out in Ante's order whatever order magpie lists them in. Tried with a real Ante 0.2.9 in WSL Ubuntu: magpie wrote the catalog, and `ante catalog` then read 16 providers with magpie's among them, 39 models, and Ante filled in support_vision: true for each itself. Ante then ran a real turn through the gateway — `ante --provider magpie --model group/auto-deepseek-v4-1-flash -p …` answered, and magpie's own usage log has the request (ep /v1/chat/completions, req the group's id, served by one of its members, out 10) — and so did a second model on another provider. The gateway was reached over the Windows host's address from the distro (172.17.128.1), this machine's own being on 127.0.0.1 alone, which is what notMirrored tells the user about. go vet, gofmt -l and go build (linux nogui, windows) pass. go test -tags nogui ./internal/agent: 12 failures here, the same 12 on unmodified main (the Windows ones AGENTS.md lists). ./internal/gui and ./internal/provider: TestGatewayFixQuitsOnlyAMagpie, TestPurposeAssetMatchesUsage, TestUpdateThatWontStart and TestLoginUsageClaudeAskedMeanwhile, all four on unmodified main here too. docs/reference.md's adapter table gains Ante. * agent: Ante keeps the user's own keys, reads ANTE_HOME, sends no effort it wasn't told to, and starts Ante on magpie (#1210) Seven points from the review, each with a test that fails without it. 1. ANTE_HOME was in the file's own comment and in docs/reference.md but never read: the path was fixed to $HOME/.ante, so a user who set it had magpie write a catalog Ante does not look at. anteDir reads it through place.getenv, the way MiniMax Code reads MINIMAX_DATA_DIR, so a distro's own ANTE_HOME - which magpie can't read - still means ~/.ante there. "ANTE_HOME" joins agentenv.Vars so a sandbox clears it. 2. providers.magpie was written whole, so every key of the user's that magpie doesn't write - the auth block a gateway shared on the LAN or reached from WSL needs to send a key, http_headers, extra_body, stream_idle_timeout_secs, thinking_display - went at the next sync, and an unchanged catalog was rewritten every round. It goes through theirsKept and syncJSON now, as #1103 did for the others: the user's keys in magpie's entry stay, preferred_models is magpie's list alone, and a file that says the same as it does is left as it is. 3. The two files were written in separate steps, so a change that failed halfway left Ante's catalog without magpie's entry and its settings still naming magpie. Each field's Set and its Sync are wrapped in atomic(), as empryo, minimax and kimi do. 4. The comment said Ante's "min" was the rung it sends no effort at, and folded both magpie's "none" and its "minimal" into it. Ante's reference says what min is: "OpenAI-compatible providers send the selected level as the same-named reasoning_effort (min is sent as minimal)" - so min is a sent level, and magpie's "none" has no rung of Ante's to fold into. Ante's "min" is magpie's "minimal"; a model magpie knows only "none" of comes out as the empty list, which is Ante's own way of saying it takes no effort setting at all. 5. The default was the highest rung the model takes, so every model magpie listed ran at Ante's slowest and dearest level. No effort is written: "Omit for models with no reasoning knob (Ante then sends no effort parameter and hides the effort slider)". 6. Having magpie in the catalog never meant Ante used it. What a session starts on is the provider and the model of ~/.ante/settings.json; with neither set Ante "uses the first authenticated provider in catalog order", and Ante's own presets come before magpie's entry - so while the user has any of those signed in, that is the one picked and magpie is not. (Measured: nothing named in settings, two keyless providers ordered aaa_other then magpie, and the request went to aaa_other's port; settings provider=magpie and it went to magpie's.) magpie sets that pair now and saves what it found there, so Disconnect hands it back; a provider the user picks in Ante's own /providers while magpie is wired is theirs and stands, and Check says so instead of keeping quiet. Ante's settings name the model apart from the provider, so magpie writes the catalog id it put in preferred_models, un-prefixed, and reads a bare id as magpie's only beside magpie's provider. Tests lean on the package's own testenv, not a real ~/.ante. TestAnteSyncKeepsTheUsersKeys is modelled on ad3b7fe5's TestAirProviderWritesKeepCustomFields and goes both ways - sync and pick - and wants an unchanged file to keep its mtime. Tried with a real Ante 0.2.9 in WSL Ubuntu on this machine (Ante ships macOS and Linux builds alone; there is no Windows Ante here). The strongest of these is the whole of it: magpie's own Go code - ante(home).Connect(), then the model field - wrote a catalog.json and settings.json into a temp folder, that folder was handed to the real Ante as ANTE_HOME, and Ante ran a turn through it with no --provider, no --model and nothing typed by hand. - `ante doctor` read `home ok /tmp/ante-e2e` and `16 providers (1 authed), 108 models` from ANTE_HOME, and magpie's entry came back with the base_url it was given: ANTE_HOME really moves the folder, and a base_url already ending in /v1 is not doubled (the request went to /v1/chat/completions). - What a session starts on is settings.json's provider, measured against two keyless providers each answering on its own port, so the logged port names the one Ante asked. Catalog ordered aaa_other then magpie, nothing named in settings: Ante asked 44331, aaa_other - the first authenticated in catalog order, exactly the review's "很可能选不到 magpie". settings provider=magpie: it asked 44220, magpie. settings provider=aaa_other: 44331 again, so a pick the user makes in Ante's own /providers overrules what magpie wrote, which is why stepping out leaves it rather than handing back the one magpie found. And with magpie the only authenticated provider, auto-detection does reach it - so the catalog entry is not useless, it is simply not enough while the user has any other provider signed in, which is every real install. - What Ante sends for effort, from the same files: no reasoning_effort at all for a model with no effort written (item 5, as its reference says omitting it sends none); `--effort min` on a model sent `reasoning_effort: "minimal"` - Ante's min is magpie's minimal, exactly item 4; and a model Ante was told `"supported_efforts": []` for sent no reasoning_effort even when asked `--effort low`, which is what a none-only model now gets instead of a level that refuses it. - The user's own keys inside magpie's entry are ones Ante reads, not decoration: `ante catalog` hands back the entry's auth, http_headers, extra_body, stream_idle_timeout_secs and thinking_display unchanged, and a bearer env_key there makes `ante doctor` count the provider as the one authed. That is item 2. - The no-auth decision holds on Ante's side, isolated by doctor's counts: Ante's own presets alone read `15 providers (0 authed)`; a magpie with no auth block reads `(1 authed)`; the same magpie given a bearer env_key that isn't set drops back to `(0 authed)`; with the key set, `(1 authed)`. So an entry with no auth is authenticated and one that asks for a key the user doesn't have is not - writing an env_key, which the first version's comment considered, would have made magpie the one provider Ante refuses to auto-detect. - Ante fills `support_vision: true` in for itself, as the PR's own note said, and a routing group declared with no capabilities at all still worked. Not covered by that run: the stand-in server answered inside the distro, so this proves Ante's config handling end to end, not a live magpie gateway relay (the first commit's message records a real turn through one). Every probe used ANTE_HOME into a temp folder; this machine's real ~/.ante gained no catalog.json or settings.json. What each fix failed without it, one test each: taking ANTE_HOME out -> TestAnteHome "$ANTE_HOME ignored"; theirsKept out -> "the user's auth lost or changed"; syncJSON out -> "an unchanged catalog was rewritten"; atomic out -> "settings.json kept half of a change that failed"; the old min mapping -> "anteEfforts([minimal high]) = [high], want [min high]"; a written default -> "deepseek/pro: effort written"; settings never pointed at magpie -> TestAnte; a model never written -> TestAnteModelField; Check left quiet -> "moved off magpie: \"\""; handing magpie back over a pick the user made while wired -> TestAnteKeepsWhatTheUserPickedWhileWired; never restoring the model -> TestAnteConnectDisconnect "not put back"; Connect picking the model field instead of magpie as provider -> "Connect left the user's model beside magpie's provider"; ANTE_HOME kept out of agentenv.Vars -> TestFolderVarsAreListed. Taking preferred_models out of the whole list is the one mutation no test turns red on: mergeTheirs cannot merge a JSON array (sync.go returns want for it), so the file behaves the same either way and the argument is there for intent and for the other keys, not for behaviour. go vet ./... and go build ./... pass, as do GOOS=linux go build -tags nogui ./... and GOOS=windows go build ./..., and gofmt is clean on LF content (this clone has core.autocrlf and no .gitattributes, so gofmt -l reports every file). go test -tags nogui ./internal/agent fails twelve tests, and an untouched worktree of origin/main run the same command on this machine fails the same twelve, test for test; ./internal/agentenv, ./internal/appdir and ./internal/edit pass, and every Ante test passes at -count=5. The whole ./... was run on both: the failing sets are alike, origin/main having one more, TestLoginUsageClaudeAskedMeanwhile, already filed as #1228. None of those twelve is this change's, and none is fixed here. * docs: agent-wiring records that Ante keeps the user's keys in magpie's entry and starts on settings.json's provider (#1210) The two rules the review asked for, written where the repo keeps them - the same linesad3b7fe5(#1239) added for Air and2d9db1b6(#1242) for malformed configs. The Verification block gains the package's own Ante run, as #1239 added Air's. --------- Co-authored-by: wizzy-yang <wizzy-yang@users.noreply.github.com>
b0d456c3) and every later push queued and was replaced behind it
30d952cf (v0.1.976) forgetSideLogin no longer refuses the account a subscription uses first; magpie accounts forget goes through the same ForgetLogin, so a plugin's in-use account is forgotten and the remaining one becomes the one in use. Test-only; go vet and go test -tags nogui . ./internal/provider/... pass.
6f391bc8) taught the [1m] mark to each group lookup by pasting the expression into AutoStandIn, GroupFinder and DisabledGroup in group.go, groups_cli.go and the agent's reseat.go; a sixth lookup would have to find and copy it again. Behaviour is unchanged. go test ./internal/provider/ ./internal/agent/ and the root package pass, as do the gui and gateway Group/1m tests; build and vet pass.
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.
cda11d84); positives from 6b6113aa, d40fee80, bed306ae and #948
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 |
Why magpie
You probably use more than one agent. Each keeps its model in its own file, in its own format, with its own keys and base URLs, and its own opinion about which vendors it supports. The subscription you pay for works in one agent and nowhere else. And when it runs dry at 3 pm, you're back to editing config files.
magpie gathers all of it into one place.
🎛 One screenEvery agent on your machine, in one list. Click a model, pick another. magpie changes exactly one key in the agent's own config. Comments, order and formatting stay untouched. |
🔌 One gateway
|
🔀 Routing that keeps goingGroup models from several providers. When one is rate-limited or out of quota, the next one answers. Your agent never sees the error. |
🔑 Subscriptions, sharedYour Claude, ChatGPT, Copilot, Gemini or Grok sign-in becomes a provider that every other agent can use. No key to copy. |
🧩 PluginsOpenCode auth plugins and pi packages from npm run inside magpie. A plugin can also be gateway middleware that rewrites every request and reply. |
📊 Every token, countedTokens, cache hits, cost at list price, balances and quota windows for every provider, account and session, with limits per key. |
How it fits together
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
Any model, any agent
Click a value and a searchable list opens: every model of every provider you added, as provider/model. Pick one and the agent's config is rewritten safely and atomically. Start a new session and the agent is on the new model.
Profiles save the setup of every agent under one name ("Budget", "Focus") and switch them all back in one move. Each agent can also have its own short list of models, so its picker shows only what you want there.
magpie lives where you are: a menu bar panel on macOS, Windows and Linux, a full window, a TUI (magpie tui), a web UI (magpie web, for WSL or a server over SSH) and a plain CLI.
|
|
A provider is one field away
Pick a preset, paste a key, done. Model lists come straight 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. Nothing is compiled in.
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.
Already set up elsewhere? 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, like each account, can go through a proxy of its own.
Routing that keeps going
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 |
Conversations stay with the account that answered them while the vendor's prompt cache is still worth keeping. Intent routing goes further: a small model of your choice reads each new turn, so tests go to the strong model and quick questions to the fast, cheap one. Groups can contain groups, and the Routing view shows every decision live.
|
|
Sign in once, use it everywhere
An agent you're signed in to is a subscription with models behind it, so magpie offers it as a provider. 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 of day you choose, or the moment the last one resets, so your windows line up with your day instead of with your first prompt.
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
magpie runs plugins on Bun, downloaded the first time a plugin 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, whatever the provider. onRequest can rewrite a request or turn it away, onEvent sees each streamed event, onResponse sees the whole reply. It runs in-process, about a microsecond per event, and 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.
Every token, counted
- Tokens, cache reads and writes, reasoning and calls, with cost at list price, in dollars or yuan. Set your own price for any model.
- Balances and quota windows for every key, plan and subscription account (
magpie quota). A reset reminder warns you 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, part by part.
- By account and by upstream key, so you can check a vendor's bill line by line, and OTLP export to your own observability stack.
Share one magpie
- On your network. Turn on Share on local network and give each client a named gateway key, each with its own daily, weekly or monthly token and cost limit.
- Remote magpie. A laptop can use the providers, accounts and routing groups of the magpie on your desktop, while still wiring its own agents.
- Docker. Run
ghcr.io/yetone/magpieon a server or a NAS and manage it from the web UI. - Sync. Back up to a file, or keep machines in sync over WebDAV (Nutstore, Nextcloud…) or S3.
The little things
|
📚 Library. Write instructions, MCP servers and skills once; magpie writes them into each agent's files in that agent's format, and removes only what it wrote. 🖼 Images and video. Give any agent an image tool through MCP, made with the model you choose, and videos with a Grok subscription. ☕ Keep awake. Your computer doesn't go to sleep in the middle of an agent's task. |
⬆️ Install and update agents. The Agents page shows each CLI's version, updates it the way it was installed, and gives the commands to install the ones you don't have yet. 🐧 WSL. On Windows, agents inside WSL distros are wired too, and their sessions counted. 🎨 At home on your desktop. Light and dark, and on Omarchy magpie takes your theme's look. |
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 CLI · Crush · DeepSeek Harness · Reasonix Studio · Command Code · fx · Devin · Hermes Agent · Mister Morph · Kimi 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
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, 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
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 |
Community
Questions, ideas, or a model that won't show up? Join us on Discord or open an issue.
If magpie saved you from editing one more config file, a ⭐ helps others find it.