yetone d9bf7c1ccf zcode: the API format the user picks for magpie's provider in ZCode's settings stays theirs; a sync no longer puts Anthropic Messages back on every start (杰多夫 on Discord)
What changed: zcodeRules wrote api.type "anthropic-messages" into
provider_config.json, and zcodeProviderJSON wrote kind "anthropic" into
config.json, on every sync (magpie's start, any catalog change). A user who
switched the provider to OpenAI Chat Completions or Responses in ZCode had it
switched back the next time magpie started. zcodeFormat now reads the format
already there and keeps it, in both files: provider_config.json's api.type
(ZCode 3.14 on) or config.json's kind (older ZCode), the one written last
where they differ, mapped as ZCode maps them (anthropic-messages/anthropic,
openai-chat-completions/openai-compatible, openai-responses/openai). A new
provider, or a format ZCode doesn't have, is Anthropic Messages as before.

Why it's safe: magpie's gateway answers all three at the same base address.
Checked with ZCode 0.16.9's own agent CLI (glm/zcode.cjs -p, run from a
copy under a sandbox HOME, never ~/.zcode) against a sandbox gateway with
the DeepSeek provider: anthropic-messages asks /v1/messages,
openai-chat-completions /chat/completions, openai-responses /responses, and
a tool-using turn (Read a.txt) answered 200 on each, to deepseek-flash.

What was run:
- TestZCodeKeepsUserFormat (new): a format picked in provider_config.json,
  for each of the three, survives two syncs and is carried to config.json's
  kind; one picked in config.json is carried to provider_config.json; an
  unknown one isn't kept. On the old zcode.go it fails: "picked
  openai-chat-completions: kind "anthropic", api "anthropic-messages"".
- Sandbox, real binaries: provider_config.json set to openai-responses,
  then `magpie zcode magpie`: the old build wrote anthropic-messages back,
  this one kept openai-responses (config.json kind openai). Then
  openai-chat-completions, resynced, and the real ZCode CLI ran a turn on the
  file magpie wrote, served over /chat/completions.
- gofmt -l; GOOS=linux and GOOS=windows go vet -tags nogui ./internal/agent;
  go test -tags nogui ./internal/agent under a temp HOME: ok.

The "bcww: Field required" 400 on Anthropic Messages is not part of this
commit: ZCode's real requests (captured from its CLI, plain and with web
search) to deepseek/deepseek-flash through magpie returned 200, and DeepSeek
answers schema errors in serde's words, not "Field required".
2026-10-10 09:58:30 +08:00
group: a routing group's members can be patterns, so a group follows a provider's catalog (#766: magpie group add my-free-pool models='openrouter/*:free,opencode-zen/*-free') — a group names its models one by one, so a pool of a vendor's free models went stale as the vendor added and dropped them. A group now keeps patterns apart from the models it names (Group.Match): a glob, * any run of characters (/ too) over the provider/model id in any case, or re:<regexp> over the whole id. groupsIn, which every reader goes through (Groups, FindGroup, /v1/models, MemberGroups, GroupsWith, RenameGroup, rules, Off, Pick, the GUI, TUI and CLI), puts after the named models every enabled provider's model a pattern matches, in catalog order, deduplicated, the named one keeping its place; a pattern never matches a group. What was matched is derived (Group.Matched) and never stored: store() and SaveGroup keep only the named members, so a save never freezes matches. Off and rules may name a matched model. A group with only patterns is allowed; one matching nothing routes nowhere and says so: magpie group <id> lists each pattern with how many models it matches now ("matches nothing now" in amber), the group list and the TUI too, and the GUI card shows a line per pattern with its count. CLI: models= takes patterns among the ids, models+= adds them (naming a matched model moves it to where it is named), models-=<pattern> drops one, models-= of a matched model is refused naming its pattern; the help documents patterns. GUI: the editor has a Patterns box (Add pattern / Remove, validated as the server does), matched models follow those named marked "by pattern" with their off switch and no Remove, and saves send members without the matched ones plus match; zh strings added. Tests: TestGroupPatterns, TestGroupPatternMembersOffAndRules, TestGroupPatternMatchingNothing, TestPatternSyntax (provider), TestPatternGroupRoutes (gateway: a request reaches a matched model, a model a provider adds joins, Off on a matched one, /v1/models lists the group), TestGroupPatternsCLI, and group-patterns.test.cjs (WebKit, en+zh); they fail on the old code (the Go ones don't build, the GUI one finds no pattern lines). GUI: group-patterns, group-found-off, group-member-fast, group-member-off, settings-groups, agent-model-groups, remote-group-served, routing-manual pass on WebKit; group-from-model-add has the same 2 failures (600x420) as origin/main. A request to a group whose patterns match nothing now is a 404 naming the group and its patterns (emptyGroupError), not 'magpie knows no model' and every model; TestEmptyPatternGroupSaysSo. With the owner's real config under a sandbox HOME: group/ds-pool of models='deepseek/*' listed deepseek-flash and deepseek-v4-pro by pattern, stored only the pattern, was in /v1/models and answered from deepseek-flash; none-pool of 'nobody/*' said its pattern matches nothing. go vet, builds (darwin, GOOS=linux, GOOS=windows) and go test -tags nogui -count=1 ./... under a temp HOME pass.
2026-10-04 16:52:15 +08:00
…
…
claude: a Claude model runs to its own window in Claude Code, not 272K, and magpie model compact on|off is the Long conversations switch from the terminal (Max on Discord: a [1m] model's context stopped at 272K, magpie wrote CLAUDE_CODE_AUTO_COMPACT_WINDOW back when it was taken out, and there seemed to be no way to change it) — on magpie, Claude Code was told CLAUDE_CODE_AUTO_COMPACT_WINDOW=272000 whatever its model, so a [1m] Claude model compacted at 272K, though Anthropic runs it to 1M (the cap was meant for other vendors' long windows: Chen's DeepSeek turns of ~550K). Now a main model that is one of Anthropic's Claude models, from whichever provider, has the env left out (magpie's own value taken away), and Claude Code compacts at the model's own window; another vendor's model of a longer window keeps the 272K cap unless Settings → Long conversations is on Full window. A value the user writes there is still kept. The switch was only in the app's Settings; magpie model compact [on|off] (alias full-context) shows and sets it, and the Settings row's description says how Claude models are treated (en, zh, ja, de). TestClaudeCompactWindow (a Claude [1m] model gets no 272000, set and synced; another vendor's after it is capped again) and TestModelCompactCmd fail on the old code. The Long conversations row read right in WebKit, en and zh. go vet, builds (darwin, GOOS=linux nogui, GOOS=windows) and go test -tags nogui -count=1 ./... under a temp HOME pass (TestClaudeFailureKeepsClaudeCodesStatus flaked once under load, passes alone).
2026-10-05 00:09:49 +08:00
cli: magpie quota wait <provider|account> blocks until that subscription (any of its accounts) or that account has allowance again, then exits 0 (#720, thedavidweng: a long Codex task stopped when every account ran out, and nobody came back to it hours later; step 1 of the maintainer's plan, for 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.
2026-10-04 06:12:51 +08:00
update: install.sh and magpie update take --proxy and --mirror, and magpie update mirror keeps one for the app's updates too (akic404 on Discord: 安装和update如果没有梯子也是麻烦事,能否在install.sh和magpie update后加子选项?--proxy等可自定义或默认ghproxy) — install.sh had no options and fetched with curl alone, and magpie update took none; without a way out to GitHub both failed. Now both take --proxy <url> (http, https, socks5, socks5h; install.sh also MAGPIE_PROXY=) for the feed and the download, and --mirror <prefix> (or MAGPIE_MIRROR=), a GitHub download mirror the release file is fetched from as <prefix>https://github.com/…; only github.com / githubusercontent.com URLs are put through it. No mirror is used unless one is given: magpie names none and has none by default. The feed with each file's SHA-256 is always fetched from usemagpie.ai, never through the mirror, so a file the mirror changed is refused and deleted ("… from the mirror X does not match its checksum from https://usemagpie.ai; not installed"); macOS still checks the app's signing team. magpie update mirror <prefix>|off saves Settings' updateMirror (http(s) only), which the app's own background update follows too; magpie update --mirror off skips it once; the Settings page's save keeps it. The app's update already followed Settings → Proxy (#294); magpie update --proxy overrides it for one run. The environment's ALL_PROXY / all_proxy is now honoured when HTTPS_PROXY / HTTP_PROXY are unset (Go's ProxyFromEnvironment ignores it), with NO_PROXY as curl reads it. magpie update takes --flag value or --flag=value, and an unknown word is an error instead of an update. The help, README and the docs' FAQ (en/zh/ja) say how. install.test.mjs's proxy, mirror and tampered-mirror tests, TestAllProxyFromTheEnvironment, TestUpdateThroughAMirror, TestUpdateThroughAProxyGiven and TestUpdateFlags fail on the old code and pass; TestSettingsSaveKeepsWhatItDoesNotSend covers updateMirror. A dry run of install.sh as Linux amd64 into a temp HOME installed the real 0.1.773 with its SHA-256 checked, refused a local mirror serving a wrong file, and with --proxy to a closed port failed reaching the site through it. go vet, builds (darwin, GOOS=linux, GOOS=windows), sh -n, node --test site/install.test.mjs and go test -tags nogui -count=1 ./... under a temp HOME pass but TestClaudeIdentityServedWhileAsked, a timing test that passes alone. Not tried through a real proxy server or a real public mirror; no install.ps1 exists for Windows, and the app has no field for the mirror.
2026-10-04 00:19:47 +08:00
gui, web: gateway mode — magpie web on a server that is only a gateway shows no Agents, Sessions or Library (Player on Discord) — a magpie web run on a server or NAS for other machines' agents showed the Agents, Sessions and Library pages and the settings written into this machine's agents, none of which do anything there. In gateway mode the page has Providers, Gateway, Routing, Usage, Plugins and Settings; an address kept for a page left out opens Providers. Settings leaves out provider in model names, Codex subagents, long conversations, Codex thread titles, the usage/balance alerts and reset reminders, on top of the tray, open at login, Dock, text size and lightweight rows magpie web already hid; Language, theme, currency, proxy, redaction, vision/image models, sync, updates and the rest stay. magpie web is in it by itself when it finds no agents on its machine (the Docker image, a NAS) and with the new magpie web --gateway; Settings › General › Gateway mode (Automatic / On / Off, saying why it is on) wins over both and Off brings every page back at once. The choice is this machine's own (KeepOwn: never synced or restored from another computer), set only by POST /api/settings/gateway-mode, never by the Settings page's save. The app's own windows are never in gateway mode. boot.js tells the page before it paints. en/zh/ja/de; docs/reference.md (Docker › NAS, CLI list). TestGatewayMode (temp HOME: no agents → on, agents → off, --gateway → on, Off wins over --gateway, the Settings save leaves it, On with agents, Automatic, an unknown mode refused, the app window never told, KeepOwn) is new; TestSettingsSaveKeepsWhatItDoesNotSend sets it. gateway-mode.test.cjs (WebKit, en and zh: the tabs, ?view=agents/sessions/library open Providers, the switch and why, the seven rows hidden, Off posts "off" and brings tabs and rows back with Settings kept open and Agents opening, Automatic hides them again, the Settings save never sends it, no scroll, no select, no left border; web with agents and the app window keep every tab, the switch is magpie web's alone) fails without the change. mobile-web's desktop comparison differs from origin/main on Settings only, by the new row. settings-sections, settings-groups, click-scroll, cli-path, plain-names, codex-titles and agent-grip pass in WebKit. go vet, go build (darwin, GOOS=linux nogui, GOOS=windows) and go test -tags nogui ./... under a temp HOME pass.
2026-10-05 18:20:28 +08:00

magpie

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.

Release Stars Discord License
macOS Windows Linux Docker Termux

Download  ·  Docs  ·  Reference  ·  Plugins  ·  Discord  ·  English · 简体中文


magpie's Agents page: Claude Code on Kimi K3, Codex on DeepSeek V4 Pro, Gemini CLI on GLM-5.3, each picked from one list

45+

agents, one list

4

wire APIs, one gateway

5

routing modes

0

config 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.

The menu bar panel The model picker

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.

Add provider: subscriptions to sign in to, vendors, relays and local servers

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 claude binary 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.

The Routing view: four agents through magpie to seven providers, 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

The Usage page: balances, tokens, cache hit rate 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.

Star history

License

MIT

S
Description
Every agent's model. One place. Codex on DeepSeek, Claude Code on Kimi, from the menu bar.
https://usemagpie.ai
Readme MIT
103 MiB
0 Stars 1 Watchers 0 Forks
Languages
Go 63.1%
JavaScript 31.8%
HTML 3.2%
CSS 1.7%