Commit Graph
57 Commits
Author SHA1 Message Date
yetone e3bf9d05d4 library: one agent's skills or MCP servers are turned on or off at once, and a hidden agent's taken out of it (#475: turning Copilot CLI's 32 skills off was a chip on every row, and once it was hidden on the Agents page it had no chips at all, so what it had been given stayed with no way to take it out) — By agent, beside "In the library" on the Skills and MCP tabs, opens a sheet of the agents that take them, each with how many it has, a Turn all on and a Turn all off; each writes that one agent, every other keeping what it has, and reports what couldn't be written as a row's chips do. An agent hidden on the Agents page is listed while it has any, tagged Hidden and given nothing new; its instructions row is shown while it reads the shared instructions, so it can be switched off. Skills use the existing skills/agents-all; servers get servers/agents-all (EveryServerAgents), which turns on only the servers the agent can reach (no SSE for Codex, no remote one for Claude Desktop). TestEveryServerAgents and by-agent.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; every-skill, library-all, library-items, library-toggle-status, remove-all-skills, click-scroll, old-webkit pass. 2026-10-02 06:33:40 +08:00
yetoneandClaude Opus 5.5 03b4cadb1f library: Remove all beside Turn all on/off takes every skill out of the library at once (#449) — a library of many skills could only be emptied a row's Remove at a time. Remove all, in red, asks in the page first, naming the agents that lose the skills, the projects magpie placed them in, the folders that go to magpie's backups and those of the user's own that are only unlinked; Cancel sends nothing. Confirming sends every name in one call, library.RemoveSkills, which takes each as RemoveSkill does, the folders kept aside together under one backup; one that can't be taken out stays, and is said, while the rest go. magpie library skill rm --all does the same, asking y/N on a terminal and, with none, only with --yes. TestRemoveSkills and TestLibrarySkillRmAll fail without the change, as does remove-all-skills.test.cjs (Chromium and WebKit, English and Chinese); click-scroll, old-webkit, every-skill pass. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build, go test -tags nogui ./... pass (bar the known Claude account flake TestClaudeSignedOut).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 00:47:15 +08:00
AronnaxandClaude Opus 5.5 ec4ee5a3a4 fix(proc): end what a CLI probe started, on its timeout and when magpie exits (#414)
* fix(proc): end what a CLI probe started, on its timeout and when magpie exits

The probes that ask an agent's CLI something (claude auth status,
cursor-agent about/models/status, the --version checks) ran through
proc.CommandContext, which on its timeout kills only the command itself.
A CLI that is a script (a version manager's wrapper, a shim) left what it
had started running, adopted by init; and a probe still asking when magpie
exited (a one-shot command, an update, a restart) was left whole, with
nothing to end it. With Omarchy's mise wrappers stuck in their exec loop
(omacom/omarchy#7234) that was five processes holding about half a core
each for up to six hours.

proc.ProbeContext gives such a probe a session of its own on Unix, as
StartTree does, and its context ending kills the whole group. Probes still
running are listed, and proc.EndProbes kills them when magpie exits (after
run in main) or puts a new version in its place (update.Reexec). On
Windows a probe is killed alone, as before, a job being joined only once
the command has started.

TestProbeTimeoutEndsWhatItStarted and TestEndProbes fail without the
change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(proc): end probes on a terminal's signals and on a Mac's quit

Review of the first change: a probe leading its own session no longer
gets the Ctrl+C, hang-up or SIGTERM sent to magpie's terminal or service,
and magpie ending on the signal never reached EndProbes, so the probe was
left to init where before it died with magpie. main now catches SIGINT,
SIGTERM and SIGHUP, ends the probes and exits as the signal would have
(128+n). A signal magpie was started ignoring (nohup, a background job)
stays ignored. The account sign-in and plugin commands, which end
themselves on Ctrl+C, go through interruptContext and are left to do so.

On a Mac the desktop app's quit ([NSApp terminate:], also the restart to
update) exits without returning to main, so OnShutdown ends the probes.

TestProbeTimeoutEndsWhatItStarted ended its probe on a 500ms timeout,
which on a Mac could come before the script had written its child's pid
(6 of 10 runs failed in review). It now ends the context once that pid is
read, the same Cancel path.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix: let the app and the TUI quit on a signal their own way

Review of the signal handling: endProbesOnSignal exited ahead of Wails
and bubbletea, which quit on SIGINT and SIGTERM themselves. `magpie tray`
exited 143 without OnShutdown (no downloaded update installed, and
sessions.Saved skipped in main), and `magpie tui` left the terminal on its
alternate screen with the cursor hidden. The app's and the TUI's entry
points now hand the signals back (ownSignals): the app's OnShutdown ends
the probes, and the TUI comes back to main, which ends them too. A
one-shot command keeps the handler.

TestOwnSignalsHandsThemBack fails without the change (magpie exited 143
before the command could quit its own way); TestSignalExits keeps the
one-shot behavior.

childPid waited 3s for a script just written to start its child, which a
busy Mac can exceed (2 of 3 full runs failed in review). It waits 30s now
and, should the probe end first, says the probe's error rather than "the
script started nothing".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix: keep SIGHUP for the app and the TUI, and die of the signal

ownSignals handed SIGHUP back along with SIGINT and SIGTERM, but neither
Wails nor bubbletea handles it: the terminal closing under the TUI or an
app started from a shell ended magpie on the spot, and its probes, in a
session of their own, out of the hang-up's reach, kept running (before
this PR they were in the terminal's group and ended with it). SIGHUP now
stays with endProbesOnSignal. A tray under a pty whose terminal closes
left 2 processes before, none now.

The handler asked whether a command was ending itself on Ctrl+C only
after EndProbes, which can take up to a second; a sign-in done in the
meantime got magpie ended in the middle of its own cleanup. It is asked
first.

It exited 128+n, which a shell takes for a child that handled the signal:
a loop running magpie went on to the next run on Ctrl+C. It now dies of
the signal (handling reset, the signal sent again); Windows, which can't
send one, still exits with the code.

agentProbe and agentCommand share withProxy; the Windows probeGroup
comment no longer says EndProbes ends what a shim started.

TestOwnSignalsKeepsHangUp and TestInterruptWhileEndingProbes fail without
the change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix: hand signals to the TUI and the app only once they listen

Review: runTUI handed SIGINT and SIGTERM back before tui.Run, whose
newModel asks agents' CLIs (claude auth status, up to 5s) before
bubbletea listens for signals. Ctrl+C, SIGTERM or SIGINT while it loaded
ended magpie by Go's default and left the probe and its child running.
tui.Run now takes ready, called once the model is made, and runTUI passes
ownSignals.

The app had the same window: runGUI handed them back before gui.Run,
which starts the backend (probes included) before Wails' Run starts
listening. ownSignals is now gui.Started, called on ApplicationStarted,
which Wails emits after its signal handler is set up. A tray sent SIGTERM
0.05s after starting, a probe under way, left 2 processes before and
none now; one sent it once started still quits through OnShutdown
(exit 0).

TestTUIKeepsSignalsWhileLoading fails without the change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 00:42:48 +08:00
yetone 09ee1bbf58 library: every skill on or off at once (#443)
With 30+ skills, turning them all on or off was a row's All at a time.
"Turn all on" and "Turn all off" beside "In the library" give every skill
to every agent shown that can take skills, or take every one from them, in
one write (POST library/skills/agents-all, EverySkillAgents); an agent not
shown keeps what it has, as with a row's All. Off asks first in the page;
each is greyed when there's nothing for it to do. TestEverySkillAgents and
every-skill.test.cjs fail without the change.
2026-10-01 23:38:15 +08:00
yetone 232448855b library: a skill in the library by its name shows as added in Discover (#444)
A skill npx skills put in ~/.agents/skills and taken into the library has a
folder source or none, and the market's added mark matched only a GitHub
source, so skills.sh kept offering it; adding it was then turned away by
name. The mark now also matches a library skill by the market's skill id or
name, as adding does. TestMarketSkillHadByName fails without the change.
2026-10-01 23:38:14 +08:00
yetone e2e5f4bb64 agents: dsh's patch list written in flow style is edited like a block one, and a file magpie can't edit is named as itself (#445) — a profile's cordis.patch.yml whose top-level array was written as [ { id: some-plugin, disabled: false } ] (valid YAML, and what dsh's own writers keep the template's [] as once they add a row) failed every model switch with "config.yaml is not a list of entries magpie can edit": the patch-list reader took only '- ' lines, and the error named config.yaml whatever the file; since web's list goes first, one such profile stopped all of them. New edit.BlockList reads a file whose one document is a flow sequence as the same list in block style (nested mappings and lists in block style, scalars quoted and tagged as they were, the lines before it and the comments after it kept); dsh's model/effort wiring and its MCP servers (internal/library) read and write such a file through it, and its errors name the real path. dshProfiles puts web first by partition instead of a sort whose less wasn't a strict weak order. TestDshFlowPatchList (agent, library) fails without the change; TestBlockList covers one-line, folded/nested/!!js, empty, CRLF and what isn't a flow list. Sandbox HOME: magpie dsh deepseek-v4-pro on main fails with the config.yaml error, with the change both profiles get the model and web keeps some-plugin. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build, go test -tags nogui ./... pass. 2026-10-01 23:25:05 +08:00
yetone 0361189f9e test: every package's tests pass on Windows, and none writes outside its sandbox (the user: 把 Windows 上那几个失败的测试修掉) — on a Windows box the suite failed in most packages, and the root package hung for 25 minutes. Tests set HOME, which os.UserHomeDir ignores on Windows (it reads USERPROFILE), so they read and wrote the runner's own home; each now sets USERPROFILE beside HOME, and Devin's, Goose's, Crush's and Claude Desktop's tests set APPDATA/LOCALAPPDATA, where those keep their files there. said() read the command's output only once it returned, and a pipe holds a few KB on Windows, so magpie model --help blocked forever; it reads while the command writes. Unix permission bits (the gateway key store's 0600 too), exec bits and symlinks Windows lacks are checked only off Windows; TOML strings hold Windows paths as literal strings, JSON as marshalled ones; a URL's path is compared as one. The provider and usage packages run in a home of their own (TestMain, as the gateway's already does), since a CLI's identity kept by a refresh still going when its test ended landed in the runner's ~/.config/magpie — and on a Mac in the user's own. Two product fixes came out of it: imagemcp took a file:///C:/… root or image for the path /C:/…, which doesn't exist on Windows, and now makes a Windows path of it (a host for a UNC share); and session discovery could keep a new Cowork session hidden on Linux, where a folder's mtime is a kernel tick and its size doesn't change, so an entry added within the tick of the last listing left both as they were — a listing made within 2s of its folder's last change is read again, as git does for racy files. TestFilePath and TestRacyDirectoryListedAgain fail without the change. On Windows 11 every package passes (32 of 32) and a run of each package in a fresh home leaves nothing in home, APPDATA or LOCALAPPDATA; on Linux (WSL) and macOS go test -tags nogui ./... passes. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build pass. 2026-10-01 23:15:07 +08:00
ArvakandClaude Sonnet 5.5 f1906bca6a gateway: draw and film through a Grok subscription (Grok Imagine) (#360)
* gateway: draw through a Grok subscription (Grok Imagine)

A Grok subscription (SuperGrok, X Premium+) could not draw: Drawers() returned
nothing for it and draw() refused with "Grok (SuperGrok) can't draw: magpie
draws only through an OpenAI-compatible API, and Grok (SuperGrok) has none".
Grok Build's own image_gen / image_edit tools call the backend's Imagine API
at <cli-chat-proxy.grok.com/v1>/images/generations and /images/edits with the
CLI's sign-in, which magpie already uses for chat.

- drawsGrok / grokDrawers: a Grok account draws with grok-imagine-image and
  grok-imagine-image-quality, like a ChatGPT account does with GPT Image
- the Imagine API takes an aspect ratio, not a size or quality: size
  WIDTHxHEIGHT is matched to the nearest ratio it accepts (aspectAmong,
  aspectOf is unchanged); the image is asked for as base64
- an edit is JSON with the images as data URLs
- a plan's images cost nothing extra, so AutoDrawer ranks Grok with ChatGPT
  (ChatGPT still wins a tie on release date)
- provider.grokBase is exported as GrokBase, like CodexBase, for the test

Tested against a real SuperGrok account through the gateway: generation,
16:9, the quality model and an edit. Video is not covered: the Grok CLI's
video tools need zero data retention off or a storage bucket.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* gateway: film through a Grok subscription, and a generate_video tool for agents

A Grok account that draws (c6578bc) can make videos too: Grok Imagine's
video endpoints sit behind the same sign-in.

The gateway speaks OpenAI's Videos API, so its SDK works as it is:
POST /v1/videos, GET /v1/videos/{id}, GET /v1/videos/{id}/content. A
request is taken on at once and polled; the id carries the provider and
the vendor's request id, so nothing is kept in the gateway and a restart
loses no video. Status is mapped (pending at 0% -> queued, pending ->
in_progress, done -> completed, failed/expired -> failed, with why).
seconds (1-15, the vendor's limit, which it says when exceeded), size
(-> aspect ratio and 480p/720p/1080p by the shorter side), input_reference
for image-to-video (URL, data URL, {image_url}, or a multipart file) and
reference_images are taken; a model that isn't a Grok video model is
refused by name. /content answers 409 until the video is ready.

`magpie mcp image` lists a second tool, generate_video: it starts the
video, waits (up to 10 minutes), saves the mp4 into the project
(generated-videos/ unless path says where, never over a file) and says
where, so an agent can animate an image it just drew by passing its path.

Checked against a real SuperGrok account: text-to-video, image-to-video
(input_reference), reference_images, both video models, the OpenAI
Python SDK (videos.create/retrieve/download_content), the MCP tool end to
end with two videos at once, and the error paths. Unit tests use a fake
Grok upstream.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* gateway: videos follow the Settings' off switch, and an id can't change the vendor's path

Review of the video change:

- Image generation "off" turns off the video a request that names no model
  gets (videomaker, beside drawer), so generate_video says it is off too.
- A video id is put in the vendor's URL with the account's token: its parts
  must be [A-Za-z0-9_-]+ (parseVideoID) and the vendor id is path-escaped, so
  video_grok.x%3Fa=1.1 and %2F answer 404 and ask the vendor nothing.
- The id carries a short mark of the account that started it; after a switch
  the video says it was started with another account instead of the vendor's
  not-found.
- generate_video waits up to ten minutes, and Codex gives a tool a minute:
  magpie-image's Codex entry gets tool_timeout_sec (Goose's timeout) of
  eleven minutes, the user's own value kept.
- grok-imagine-video stops at 720p (the vendor turns 1080p away for it; 1.5
  makes 1080p), so a 1080p size is asked at 720p there.
- A model may be named without its provider (grok-imagine-video).
- "seconds": 6.0 is 6; 6.5 is still refused.
- completed_at is left out: the vendor doesn't say when a video finished,
  and a time made up at each poll changed each time.

Checked against a real SuperGrok account: bare model name, seconds 2.0,
1080p on the base model asked at 720p (the mp4 is 1280x720), 1080p accepted
on 1.5, both malformed ids, no completed_at.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* gateway: TestVideoModelByItsBareName asks its two models in a fixed order

It checked the body of the second request the upstream got, but asked the
two models by ranging over a map, so it failed about one run in seven
(Ubuntu CI). Ask them from a slice.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* library: an installed magpie-image gets the longer tool timeout on the next sync

magpie-image already ships, so many users have it in Codex and Goose as it was
written before: no tool_timeout_sec in Codex, and the timeout: 300 every Goose
server was given. syncMCP skipped an entry whose command, args and env were
unchanged, so an upgrade left Codex at its one-minute default, and Goose kept
300 as if the user had chosen it.

- mcpFile.behind says an entry lacks the timeout magpie gives the server now:
  Codex's tool_timeout_sec is missing, or Goose's timeout is still exactly the
  300 magpie wrote. syncMCP rewrites such an entry; merged() doesn't keep that
  300 as the user's. A value the user chose (any other number) is left alone.
- Test: an entry as main wrote it is given 660 in both, one the user set stays,
  and a second sync changes nothing. It fails without the change ("changed []").

Also, from the review:
- seconds is validated once in readFilming: a decimal number that is whole and
  at least 1 (hex, inf, nan, underscores, negatives and 0 are refused), and the
  object echoes 6 for 6.0.
- imagemcp: Run's doc comment is above Run again.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-01 04:59:22 +08:00
yetone 04805abf39 agent: MiniMax Code (#362) — MiniMax's mcode CLI (and its desktop app, same runtime) reads $MINIMAX_DATA_DIR/config.yaml, else ~/.minimax/config.yaml. Choosing a magpie model adds custom_provider.magpie there (the gateway, spoken to as Anthropic messages, with the catalog's models, efforts, limits and image support) and sets defaultModel to custom_provider:magpie/<model>; the user's own default and variant are kept and put back on reset, their comments, providers and keys on magpie's entry stay, and an emptied custom_provider goes. The Library installs skills into its skills folder; it reads no user-wide MCP file, so it gets no MCP target. Checked against @minimax-ai/code 0.5.10 in a sandbox HOME: mcode provider list shows magpie's entry and mcode exec reaches a fake upstream through it with magpie's key, model and effort; after a reset it loads the restored file. TestMiniMaxCode, TestMiniMaxCodeSync, TestMiniMaxCodeLeavesNoEmptyProviders, TestMiniMaxCodeDataDir and TestMiniMaxCodeSkills fail without the change. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build, go test -tags nogui ./... pass (TestUserPath and the Claude account tests pass alone). 2026-10-01 03:24:34 +08:00
yetone c47b22ee27 agents: "Hide all" in an agent's model list keeps its line, and an uninstalled Gemini CLI goes from the Agents page (#356, #230) — the line under an agent ("Showing 0 / N models") came only when a picker still listed one of magpie's models, so hiding them all took away the one way back; it now stays while any is hidden. Gemini CLI was taken as present from what it leaves in ~/.gemini (settings.json, .env, installation_id…), which stays after it is uninstalled, so its row stayed, offering to set up a CLI that can't run; it is now its gemini binary. TestAgentModelLineAllHidden and TestGeminiNotAntigravity fail without the change; agent-models-all-hidden.test.cjs (Chromium, WebKit, en/zh) added. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build, go test -tags nogui ./internal/agent ./internal/gui ./internal/library ./internal/provider pass; agent-models, click-scroll, old-webkit pass. 2026-10-01 01:03:57 +08:00
yetone b03967bb79 library: agents in a running WSL distro take skills, MCP servers and instructions (#331) — the Library knew only this machine's agent ids, so codex@wsl:Ubuntu and the like were never offered, and the id's colon was refused as an agent's name and can't be in a Windows file name. Claude Code, Codex, Pi and OmO in a distro now get them at their default places under the distro's $HOME through \\wsl.localhost, only while it runs (opening a stopped one's files starts it; its state is kept and asking for it says to start it). Skills go in as copies, made beside and renamed into place and made again when the library's changes, since a Linux agent can't follow a link to a Windows folder (project skills share the same copy code); an MCP server that runs a Windows program (C:\…, *.exe/.cmd/.bat/.ps1) is refused for them with a message; Pi there gets no MCP servers, where its version decides the file. The id's colon is a dot in file and folder names, and setup export/import turns it back. TestWSLTargets, TestWSLSkillsCopied, TestWSLServers and TestWSLInstructions (a fake distro) fail without the change. go vet (and GOOS=windows for agent, library), go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build, go test -tags nogui ./... pass. Not run against a real distro. 2026-09-30 22:17:23 +08:00
yetone 8124d3f927 edit: a config kept as a symlink stays one when magpie saves or clears it (#323, jigaowan) — WriteAtomic wrote a temp file beside the path and renamed it over it, so a linked library.json, instructions.md, CLAUDE.md, settings.json or config.toml became a file of its own and the dotfiles target kept its old text; clearing instructions.md removed the link. Now a write goes to the file at the end of the links (the one it names when nothing is there yet, an error for a loop of links), keeping its mode, and clearing a linked file empties its target and keeps the link (Pi's migrated mcp.json stays as {}); a plain file is removed as before. Sign-ins and the Kiro/StepFun files magpie writes privately follow links the same way, and a failed edit rolled back deletes only what it made behind a link to nothing. TestWriteAtomicFollowsSymlink, TestRemoveKeepsSymlink, TestAtomicallyKeepsSymlink, TestLinkedFilesStayLinked and TestPrivateWritesKeepSymlink fail without the change. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build, go test -tags nogui ./... pass. 2026-09-30 20:21:24 +08:00
yetone 68f9daa4fa library: an agent's own copy of a library skill gives way to it, and one that differs is settled from the warning (StringKe, JasonLeeForOnly on Discord: after Bring in all, "Claude Code already has a skill of its own called impeccable", 这里没有强制覆盖的能力) — a skill is brought in from the agent with the very folder and given to the agents that had that folder; another agent's copy (CC Switch copies a skill into each agent) was listed as "differs in" and left out, and giving the skill to it, or a copy put back into an agent after its folder became magpie's link (by CC Switch or whatever installed it), was a hard failure with no way out. A folder there holding the same files as the library's (bytes compared; .DS_Store, .git and magpie's copy mark aside) is now set aside into backups/<when>/<agent>/skills and the library's linked in its place; a skill brought in takes the agents with such a copy too, which are no longer said to differ; a move that copied it all but couldn't remove the folder brings it in all the same, what was left set aside. One that differs keeps the warning, now in the reader's language with "Use the library's" (the agent's set aside, the library's linked) and "Keep <agent>'s" (the agent, and any reading the same folder, taken off the skill) on its row — skills/use-library and skills/keep-own, magpie library skill use-library|keep-own <name> <agent>, which the CLI suggests under the problem. Backups holding a skill set aside are never pruned. TestOwnSkillInTheWay, TestSameTree, TestPruneKeepsSkillsSetAside and own-skill.test.cjs (Chromium, WebKit, en/zh) fail without the change; TestSharedAgentsSkills now expects the byte copy to be the library's. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build, go test -tags nogui ./... pass; own-skill, import-all-skills, library-items, shared-skills, market-have, click-scroll, old-webkit pass. 2026-09-30 19:42:43 +08:00
yetone 221607b5b9 library: the Library's MCP servers go to Hermes and eight other agents (EUPH on Discord: Hermes gets skills but no MCP) — agents with a skills folder had no MCP target, so the MCP editor had nowhere to write for them. Now Hermes ($HERMES_HOME/config.yaml mcp_servers, comments and other keys kept), omp (agent/mcp.json), Kimi Code (mcp.json), Devin (mcp_config.json), Grok Build (config.toml [mcp_servers.*], no SSE), Droid (~/.factory/mcp.json), Qoder and Qoder CN (settings.json), Cline (cline_mcp_settings.json or $CLINE_MCP_SETTINGS_PATH) and Command Code (mcp.json, no SSE) take them, each in the schema its own source reads; a user's own keys on magpie's entries survive an edit and their own servers show to bring in. WorkBuddy, OpenHanako and fx still get none: the first two run a server only once approved or switched on inside them, and fx drops its whole file over one entry it refuses. Each format was read back by the agent's own CLI in a sandbox HOME (hermes, kimi, devin, droid, qodercli, cline, cmd, grok). TestHermesMCP, TestHermesMCPFound and TestAgentMCPFiles fail without the change. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build, go test -tags nogui ./... pass; library-items, shared-skills, click-scroll, old-webkit pass. 2026-09-30 19:15:00 +08:00
yetone 6c5ed2acf5 agents: CC Switch's provider tables in Codex's config go through magpie too, and the Library brings in every skill found at once (JasonLeeForOnly on Discord: after moving from CC Switch, Codex threads still went to the relay, "model not found" for a magpie model) — CC Switch writes a [model_providers.custom] table (cc-switch, cc-switch-N in older versions) and moves every third-party Codex thread onto it, and a reopened thread takes the provider it was saved with, not model_provider; magpie left those tables pointing at the relay. While a magpie model is on, signed in or not, their base_url is magpie's /v1, the relay's kept in the stash and the table's other keys as they were; a table a profile names, and cc-switch-official, are left alone; Codex's own model or a reset puts the URL back, unless the table was changed since; one pointed away again is named on the agent row and taken back on sync. The Skills tab's "In your agents" gets Bring in all (2+ found), one library write, one that fails named and the others brought in. TestCodexTakesCCSwitchTables, TestImportSkills and import-all-skills.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, shared-skills pass. 2026-09-30 18:16:22 +08:00
yetone 98cbea0ffb agents: Pi's models go to PI_CODING_AGENT_DIR (#304), and the Codex app offers magpie's models' efforts (#310) — Pi keeps settings.json and models.json in PI_CODING_AGENT_DIR when set (~ expanded; @earendil-works/pi-coding-agent config.js), and magpie wrote ~/.pi/agent regardless; omp is read by its own rules (PI_CONFIG_DIR, OMP_PROFILE/PI_PROFILE, then PI_CODING_AGENT_DIR), and the library's Pi and omp targets follow. The Codex app's model picker offers only the efforts in [desktop] enabled-reasoning-efforts of config.toml (ChatGPT.app 26.924: default low…xhigh, ultra, persistent), so a magpie model's max or minimal was never offered; routed through magpie, the efforts its models take are added to the user's list (or the default), nothing else changed, only values the app knows (it drops the setting for any other), comments kept, nothing written when nothing is missing. TestPiAgentDir, TestOmpAgentDir and TestCodexDesktopEfforts fail without the change. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build, go test -tags nogui ./... pass. 2026-09-30 18:09:09 +08:00
yetone fb6c1e175b gui: a Discover card says Add again once its server or skill is removed (#300), and hovering today's bar in the daily trend keeps its tooltip (#309) — every library change went through change(), which redrew the library only; the market's "Added" marks were refreshed on window focus alone, so removing a server or skill, adding or renaming one in the editor, or pasting several left them stale. take() is now the one way the page accepts a library: when the servers' or skills' names change it clears the marks of those gone, redraws the market and fetches it again. RemoveServer drops the server's icon from library.json, unless another server runs the same thing. The Sessions tab re-reads every 15s, and with an agent at work today's numbers change, so the chart was rebuilt and today's bar under the pointer replaced, its tooltip with it; a redraw with the same days, metric and locale now updates the bars in place (heights, titles, peak). market-have.test.cjs and sessions-today.test.cjs (Chromium, WebKit, en/zh) and TestRemoveServerDropsItsIcon fail without the change. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build, go test -tags nogui ./... pass; sessions-overview, click-scroll, old-webkit, library-items, shared-skills pass. 2026-09-30 18:09:09 +08:00
yetone a69ae948dc library: Claude Desktop's MCP servers go into Claude-3p/claude_desktop_config.json as well, where its 3p mode reads them (#297: Claude Desktop 使用 magpie 三方网关(3p)后,library 写入的 MCP 在 Desktop 里看不到) — in 3p mode, which magpie's own provider switch turns on, Desktop's whole userData is Claude-3p (~/Library/Application Support/Claude-3p, %LOCALAPPDATA%\Claude-3p on Windows, ~/.config/Claude-3p), its MCP servers included, so the servers the library wrote into Claude/'s file never showed in Settings → Developer. Where the Claude-3p folder is, its file is now written with Claude/'s, in one edit with each file's own keys kept, read for servers to bring in, and cleared on removal even when Claude/'s no longer has the entry — both, not whichever mode is on, so switching the provider leaves nothing stale and Desktop finds them in either mode; no Claude-3p folder is made for a Desktop never in 3p, and one only ever in 3p (no Claude folder) gets its servers there alone. A server given before reaches Claude-3p on the next sync. Tested with new desktop3p_test.go in a sandbox HOME (both files written and cleared, the user's servers and keys kept, sync of an older server, 3p only); each fails without the change. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build, go test -tags nogui ./... pass. Not tried against a real Desktop in 3p. 2026-09-30 15:56:52 +08:00
yetone 4dc3d93343 kimi: the new Kimi Code (2.x) is wired in ~/.kimi-code, where it reads its settings — a model picked in magpie never reached it, nor did magpie's models reach its /model (#290, kyzhouxu: Gemini 3.8 flash picked, Kimi Code still starts on the old one). magpie wrote only ~/.kimi/config.toml, the old kimi-cli's; the new CLI copies that over once when it first starts and never reads it again. KimiDir picks $KIMI_CODE_HOME, ~/.kimi-code if there, $KIMI_SHARE_DIR, ~/.kimi if there, else ~/.kimi-code. The new CLI's model tables also say tool_use (kimi-cli refuses the word, so it isn't written there), and its skills go to ~/.agents/skills, which it reads (not ~/.config/agents/skills). Tested with TestKimiCode (fails on main: path .kimi/config.toml, want .kimi-code/config.toml) and TestKimi; in a sandbox HOME the new CLI's kimi provider list shows magpie and the new default model, kimi doctor finds the config valid, and kimi -p went through a sandbox gateway to a fake upstream asked for gemini-3.8-flash with its 26 tools. go vet, go build -tags nogui (darwin, GOOS=linux, GOOS=windows) and go test -tags nogui ./... pass (flaky tests under load pass alone). 2026-09-30 15:29:14 +08:00
yetone c9d9652380 library: an agent whose folder is a file isn't written, and skills reach 13 more agents with one link in ~/.agents/skills for those that share it (neiko on Discord: with DeepSeek Harness not installed the Library kept failing on "open ~/.dsh/AGENTS.md: not a directory" and ~/.dsh/config.yaml; inaction: the skills list is short of the Agents page, Kimi Code has none). An agent counted as there when its folder path existed or its command was on PATH, never asking whether the path was a folder — a file at ~/.dsh, or another dsh, made DeepSeek Harness look installed. Now an agent whose folder is a file (or under one) isn't detected (agent.Taken; Goose's, Cindy's and Claude Desktop's own checks want a folder too), a Library target leaves out each place a file stands in the way of, one with none left isn't listed, and an agent given no MCP server with none of magpie's isn't read. Skills: Kimi Code, Goose and Cindy get ~/.agents/skills (Kimi's ~/.config/agents/skills when there, as Kimi reads it first; never ~/.kimi/skills, which would hide Claude Code's from it); Command Code, Devin, Hermes, Droid, Cline, Qoder, Qoder CN, Grok, WorkBuddy, Hanako and fx their own skills folder; Kimi, Goose and Grok a project's .agents/skills. The shared folder is filled first, and an agent that reads ~/.agents/skills besides its own (Codex, Gemini CLI, OpenCode, Crush, DeepSeek Harness and those above) gets no second link to a skill already there. Tested with new taken_test.go (neiko's two errors without the change) and agent_skills_test.go (skills folders, written once, a shared skill imported for Kimi), in sandbox HOMEs; library-items and shared-skills 24/24 in Chromium and WebKit; go vet, go build (-tags nogui, GOOS=linux, GOOS=windows), go test -tags nogui ./... pass. Not tried with real Kimi Code, Goose or Cindy. 2026-09-30 14:40:41 +08:00
yetone 98d1674a52 library: Antigravity is a Library target — rules, MCP servers and skills reach agy and the Antigravity app alike (#277) — both read their user-wide customizations from ~/.gemini/config: GEMINI.md there, mcp_config.json (a remote server written as agy's own mcp add writes it, its serverUrl, "type": "sse" only for an SSE one so magpie reads it back as one; a url agy read in place of serverUrl is read too; the user's own servers and anything they added to an entry, disabled included, are kept) and skills; a project's skills go in the shared .agents/skills. The rules card says Antigravity also reads Gemini CLI's ~/.gemini/GEMINI.md, so text given to both is read twice. RTK is left out: rtk 0.50 has no user-wide hook for Antigravity. Tested with antigravity_test.go in a sandbox home (target paths and the antigravity-cli alias; stdio, http and sse servers written and read back, user keys and servers kept); library-items.test.cjs 18/18; go vet, go build (GUI, -tags nogui, GOOS=linux, GOOS=windows), go test -tags nogui ./... pass. 2026-09-30 12:42:56 +08:00
yetone 04f374fa8c agent: OmO (oh-my-openagent, omo-ai), a fork of Pi that keeps its own ~/.omo/agent, gets its own row: a magpie model sets settings.json's defaultProvider/defaultModel and magpie's provider in models.json there as Pi's does, $OMO_CODING_AGENT_DIR / $SENPI_CODING_AGENT_DIR are honoured, the Library writes its AGENTS.md, mcp.json and skills, and omo update updates it (#264 rhyme227). Pi's own ~/.pi is left alone. piIn becomes piLike(at, id, name, dir) so both share one wiring. Tested with omo_test.go in agent and library (fail without the change); go vet, go build -tags nogui (darwin, GOOS=linux, GOOS=windows), go test -tags nogui ./... pass. 2026-09-30 11:38:07 +08:00
yetone be4298b294 library: Pi 0.99's own MCP — with Pi 0.99 or later on PATH and no MCP extension replacing it, MCP servers go in the mcp.json Pi reads itself, in its shape (command/args/env, url/headers, no adapter transport keys; SSE refused, which it has none of) (Discord feedback, 何似在人间: Pi now has native MCP) — Pi 0.99 (extensions/mcp/config.ts) reads mcpServers from <agent dir>/mcp.json, unless pi-mcp-adapter or pi-mcp-extension is installed (now also found in Pi's extensions folder) or settings.json has -builtin:mcp; then the files are as before. Servers magpie or the user had in mcp-adapter.json, which nothing reads now, are moved into mcp.json, the adapter's settings and anything mcp.json has differently left where they are and still found, both files backed up and written together (edit.Atomically). Without an adapter found, mcp.json is no longer moved to mcp-adapter.json, since it may be Pi's own. agent.InstalledVersion asks the CLI on PATH, once per binary. Tested with TestPiMCPNative in a sandbox HOME with a fake pi on PATH: 0.98 writes mcp-adapter.json, 0.99 moves the servers over with the user's fields kept, writes and removes in Pi's shape, SSE refused, the adapter (listed or in extensions) or -builtin:mcp keeps the old file; TestPiNativeVersions, TestInstalledVersion. go vet ./internal/..., go build -tags nogui (and GOOS=linux, GOOS=windows) and go test -tags nogui ./... pass. Not tried with a real Pi 0.99. 2026-09-30 10:14:38 +08:00
yetone d37b821908 toml: Codex's config.toml with a multi-line array (notify = [ … ]) is edited right, and an edit that fails leaves every file as it was (#253 kerwinliu00001: "edited TOML is invalid: line 2, column 1: incomplete number", config.toml left with model_provider gone and [model_providers.magpie] added but no model) — the top-level key edits (GetTOMLTop, SetTOMLTop, DelTOMLTop) went line by line with regexes: a new key went after the last line that looked like key = …, which for notify = [ was inside the array; key = value lines inside a multi-line string were read as keys and a line starting with [ as a table; replacing or deleting a multi-line value touched only its first line. They now locate the top-level keys with the TOML parser, as the table edits already did, each with its value's whole range however many lines it takes (parseTOMLFile, the unnamed root table beside the tables); SetTOMLTop finds all its keys in the file as read and writes once. A file the parser refuses is still read line by line, so a broken config keeps showing its model, and writes to it are refused untouched. And a pick is several writes (Codex: drop model_provider, add magpie's provider table, set openai_base_url and model), each checked, so one failing left the earlier ones on disk: edit.Atomically(fn, paths…) puts each file back to its bytes and mode, or removes one it created, when fn fails, and every field set and Sync of Codex (config.toml and magpie-models.json, so Codex in WSL too), Kimi and Grok goes through it, as do Codex's MCP server writes (putCodex, delCodex). Tested in temp dirs and a temp HOME: the reporter's file read, set and deleted directly and through Codex's model field (signed in, with model_provider and model above the array, with magpie as the provider), the array's text kept and the TOML valid, and back to a Codex model; nested arrays, trailing commas, comments in arrays, [x] and a = b in strings, an inline table in an array; """ and ''' strings holding model = … and [table] lines not read as keys, new keys after their closing quotes, one deleted whole; a forced failure of Codex's last write leaving config.toml byte-identical; TestAtomically. They fail on main (the Codex ones with the reporter's error). go vet ./internal/..., go build -tags nogui (and GOOS=linux, GOOS=windows) and go test -tags nogui ./... pass. Not tried against a real ~/.codex, in WSL or in the GUI; multi-line inline tables (TOML 1.1) are refused by the parser and so left untouched with an error. 2026-09-30 09:31:59 +08:00
yetone ac1f522154 library: skills in the user-wide ~/.agents/skills are found, one row with the agents that link or junction to them, and brought in by a link that leaves the shared folder as it is (#227 Aimer779: the Library's "In your agents" never looked in ~/.agents/skills, the shared folder many agents read and where the user keeps skills, many as symlinks to D:\aimer-skills; a skill junctioned from there into Pi and ZCode showed as Pi's with "differs in ZCode") — foundSkills walked only each target's own skills folder, and realDir used filepath.EvalSymlinks, which since Go 1.23 leaves a Windows junction (a mount point, reported as irregular, not a symlink) as it is, so two junctions to one folder were two skills, and the Link check (ModeSymlink) took a junction for a folder of its own, one ImportSkill would move. Now foundSkills reads ~/.agents/skills first (hidden entries, ones without a SKILL.md, ones the library has or linked, skipped as for the agents' folders), a skill there carrying shared (its entry) and the agents whose entry resolves to the very same folder; a byte copy in an agent's folder is still another ("differs in"), as copies were. realDir follows links a part at a time itself (symlinks, and on Windows junctions through os.Readlink, relative targets, links to links, a loop or a missing part giving the path back), and a new linked() (symlink, or junction on Windows) replaces the ModeSymlink checks in foundSkills and ImportSkill. ImportSkill links the library to a skill in the shared folder (Source folder), real folder or link alike, and never moves it; the agents' links to it are replaced by the library's as before; an agent's own folder still moves in. No target writes to ~/.agents/skills: targets.go gives no agent a user-wide ~/.agents/skills (only projects.go's project .agents/skills), so it stays a place skills are found in. The page: a found skill in the shared folder says "shared in ~/.agents/skills/<name>" (共享于) above any "linked from", its Bring in title says it stays where it is and can be given to any agent; the shared path is revealable. Tested with TestSharedAgentsSkills (sandbox HOME/USERPROFILE: a symlink in the shared folder to a folder elsewhere, real folders there, Pi and Codex links to one of them, absolute and relative, Gemini's link to the shared link, a Codex copy, a folder with no SKILL.md and a hidden one; one row each with the right agents, shared, link and others; importing all three leaves the shared folder and the folder elsewhere as they were, the library's entries links to them, the agents' links now the library's, Codex's copy untouched, nothing found after), TestRealDir (absolute, relative, a linked parent, .., a loop, a missing path, linked, within) and TestJunction (mklink /J, Windows only, skipped here), and a new internal/gui/tests/shared-skills.test.cjs in Chromium and WebKit, en and zh. go build -tags nogui (and GOOS=linux, GOOS=windows), go vet for windows and go test -tags nogui ./... pass (TestClaudeSignedOut flaked once, passes alone); the GUI suite passes but for login-import (passes alone) and panel-profiles in WebKit, which fails on main the same under this load. Not tried on real Windows, with real junctions, or in the real window. 2026-09-30 02:15:47 +08:00
yetone 3ee4ebbf62 images: agents can generate and edit images with a model set in Magpie (让Magpie支持配置图像识别模型以及生图模型, part 2) — the gateway answers /v1/images/generations and /v1/images/edits for any model that draws: an images-API model (gpt-image-1, dall-e, imagen, a relay's) is sent the vendor's own images request (an edit as multipart, image[] per reference); a chat model that answers with images (OpenRouter's Nano Banana and GPT-5 Image, gpt-5-image) is asked with modalities ["image","text"], the size given as an aspect ratio, once per image asked for; Gemini's own image models over generateContent. Either way the answer is the images API's (b64_json with its mime_type, the model's text, usage), recorded in usage like any request. The model is Settings → Images → Image generation: Automatic (a model that draws among the providers set up, from the catalog's image-output models), Off, or any model; a request that names none is drawn by it, and with it Off is refused saying where to set one. Subscriptions draw nothing yet. magpie mcp image is a stdio MCP server with one tool, generate_image (prompt, size, n, path, reference_images): it asks the agent for its roots, saves each image in the project (assets/ by default, a name from the prompt, never over a file, the extension of what came back — a JPEG asked for as hero.png is hero.jpg), and says where; reference images are read from the project and sent as an edit. Its requests carry the agent's own name (claude-code/… magpie-image/1) so usage says which agent drew. Library → MCP servers → Discover has it as Magpie Image, opt-in: no agent is given it until picked, since every image costs what the model charges. Checked in a sandbox HOME against real vendors: OpenRouter's gemini-3.1-flash-lite-image drew a 3:2 magpie over MCP as Claude Code and edited it from the saved file as Codex (usage: claude, codex), AIHubMix's gpt-image-1 answered /v1/images/generations with a 1024² PNG; the Settings row and picker in light and dark, the Library card and its opt-in sheet 2026-09-29 01:52:53 +08:00
yetone 5b43bdd61c library: RTK's version is kept up to date from magpie, and what it saved is drawn day by day (这里要能够管理RTK的版本,比如给它升级,以及能够看到RTK省token的趋势) — the RTK card shows its latest release beside the installed one (read from where github.com/rtk-ai/rtk/releases/latest redirects, as RTK's install.sh does, the API as fallback; kept six hours) and, when newer, an Upgrade button that brings it up the way it was installed: brew upgrade rtk for Homebrew's (in a Cellar; Homebrew updated first), winget upgrade on Windows, cargo install --git again for cargo's, and RTK's own script again, into the same folder (RTK_INSTALL_DIR), for one it put elsewhere; when Homebrew's formula is still behind the release, that is said. Also magpie library rtk upgrade. Under the totals, a chart of what RTK saved each day (week by week past 92 days) over 30 days, 90 days or all it has recorded: each bar the commands' whole output, the part saved above what still went to the model, the range's own total beside it — from rtk gain --daily --format json (RTK 0.28 on), which carries the summary too. Tested with a fake Homebrew rtk behind its release and a fake script install, and against the real rtk 0.28.2 and its history in a sandbox magpie (GitHub says 0.50.0); the upgrade itself not run on this machine 2026-09-29 01:01:25 +08:00
yetone 42aae751f5 agent: Pi's MCP servers go where pi-mcp-adapter reads them now (xiaozhu1337 on #58: pi-mcp-adapter no longer reads …\.pi\agent\mcp.json) — pi-mcp-adapter 3 (3.0.0 2026-09-26, 3.1.0 now) reads <agent dir>/mcp-adapter.json, same format, after ~/.config/mcp/mcp.json and ~/.agents/mcp.json (.mcp.json and .pi/mcp-adapter.json per project), and no longer <agent dir>/mcp.json; at every session start it warns while that file has any server, settings, imports or claudePlugins, whether or not mcp-adapter.json is there too (config.ts getLegacyMcpMigrationNotices, index.ts session_start). magpie only looked for the adapter in <agent dir>/npm/node_modules, so one Pi installed the older way (npm -g: %APPDATA%\npm\node_modules and the like, which Pi 0.87's package manager still resolves), from git, or from a folder counted as none and mcp.json kept being written; and with mcp-adapter.json already there (the adapter's own setup writes it) mcp.json's servers were left behind. Now which extension Pi has comes from settings.json's packages (a pin like npm:pi-mcp-adapter@2.9.1 counts) and the folders Pi installs them in: adapter 3, or listed with no version found, or mcp-adapter.json there → mcp-adapter.json; mcp.json is renamed to it when there is none, else each server and setting it lacks is merged in (backed up first), one the two have differently left in mcp.json for the user, and mcp.json removed once empty. pi-mcp-extension 1.5 reads only ~/.pi/agent/mcp.json (its home's, not PI_CODING_AGENT_DIR's; transport field, zod schema): with it alone that file, with both each file gets the servers (user fields in each entry kept) and mcp.json isn't moved — the adapter's warning can't be avoided then. Adapter before 3 → mcp.json; nothing found → mcp.json if there, else mcp-adapter.json. Servers in either file are found for bringing into the library. Tested in sandbox homes, and against the real 3.1.0 loader: the reporter's shape (adapter under npm's global folder, mcp.json from magpie, mcp-adapter.json from setup) warned before, and after one magpie write it gives no notice and loads all three servers 2026-09-29 00:44:43 +08:00
yetone 63f9fa7465 agent: Claude Desktop runs on magpie in its third-party mode (#156: Claude Desktop 不会解锁 Claude Code 面板 — CC Switch 可以,咱这个支持吗?) — signed in with a Free account, Desktop's Code tab is only "Get Claude Code"; in its 3p deployment mode it needs no Anthropic sign-in and Code and Cowork run on the gateway. A Claude Desktop agent whose provider field switches it: on writes deploymentMode "3p" into Claude/ and Claude-3p/claude_desktop_config.json, a magpie profile in Claude-3p/configLibrary/<id>.json (inferenceProvider gateway, inferenceGatewayBaseUrl the gateway's address, inferenceGatewayApiKey magpie-claude-desktop, inferenceGatewayAuthScheme bearer; disableDeploymentModeChooser and coworkEgressAllowedHosts ["*"] only where unset) and its entry in _meta.json, applied — the keys and files CC Switch writes (claude_desktop_config.rs). No inferenceModels: Desktop lists /v1/models, which the gateway already gives it by ids it keeps. Off puts each deploymentMode back as it was (gone where there was none), the profile applied before applied again, magpie's profile and entry removed, and files and folders magpie made gone if nothing else went in; other keys and profiles are never touched. Folders as CC Switch finds them: ~/Library/Application Support, %LOCALAPPDATA% (a Claude… folder there if not Claude itself), $XDG_CONFIG_HOME. Desktop reads them at start-up, which the picker and notice say. The Library keeps giving Desktop's MCP servers to %APPDATA%'s file on Windows, listed once. Tested in a sandbox home: fresh, with the user's settings and 3p profiles (off restores every byte), on twice, on → off → on, drift, odd files refused, each system's folders; and against Claude Desktop 2.9939.2 on Windows 11 (winget): on, it started in 3P mode (provider gateway, apiHost the gateway) with the Code tab and no sign-in, and asked the gateway's /v1/models; off, it went back to claude.ai 2026-09-28 22:37:26 +08:00
yetone 376a02bb80 library: tests keep Windows' LOCALAPPDATA out of the sandbox — Crush's crush.json is %LOCALAPPDATA%\crush's on Windows, and the sandbox left LOCALAPPDATA as it was, so TestTargets looked for Crush in the real one and found it missing (crush not a target), on main as with #157. Now it is blanked with APPDATA, and Crush is found in the sandbox's ~/.config/crush. Run on Windows 11 in a scratch profile 2026-09-28 22:16:33 +08:00
kevinandClaude Opus 5.5 2ff1842257 library: Crush on Windows gets the library's instructions in ~/.config/crush, where it reads CRUSH.md (#157)
Since Crush 0.14 (charmbracelet/crush#1352) its config folder is
~/.config/crush on Windows as well (or XDG_CONFIG_HOME/crush), and the
global CRUSH.md it reads is there. magpie wrote the instructions beside the
crush.json it edits, which on Windows is %LOCALAPPDATA%\crush's: Crush keeps
its own model picks in that file and still reads skills from that folder,
but no CRUSH.md, so instructions given to Crush never reached it. They now
go to the config folder on every system; MCP servers and skills stay where
they were, and on Linux and macOS the path is the same as before.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 22:16:26 +08:00
yetone fb4b6c76cd library: a skill whose folder is gone can be removed (#151) — its folder was moved aside with the backups on removal, and with no folder the move failed (rename …: The system cannot find the file specified), so a skill marked as no longer in the library stayed listed for good. Now only its entry is taken out when its folder isn't there 2026-09-28 20:01:48 +08:00
yetone c8d7a995d1 rtk: Codex isn't given an rtk older than 0.50 (LeeHom: rtk's installer didn't add its hook to Codex) — rtk has a hook for Codex (rtk hook codex in hooks.json) from 0.50.0 on; an older rtk init -g --codex only puts @RTK.md in AGENTS.md, which rewrites no command, so switching Codex on ran it and then said the hook wasn't there. With an rtk before 0.50 the Library shows Codex with "Update RTK" (需更新 RTK), its switch off, the tooltip and magpie library rtk saying to update it (brew upgrade rtk, or its installer again) first 2026-09-28 19:02:23 +08:00
yetone b990735823 agent: RTK isn't given to OpenCode 2 — rtk init --opencode writes a plugin shaped for OpenCode 1 (a named export, no default {id, effect|setup}), which OpenCode 2 refuses to load with 'Plugin must export a default definition with an id and an effect or setup function' (rtk-ai/rtk#4311, still so in rtk 0.50.0); with opencode --version at 2 or later the Library shows 'Not for OpenCode 2' and won't switch it on, while a plugin already there can still be switched off and taken out (ARNO) 2026-09-28 16:36:01 +08:00
yetone e02d3f28d7 library: a project's agents can have some of the library's skills as the project's own — under Skills, In projects takes a folder (the system's picker in the app, a typed path anywhere) and each of its skills gets agents' chips; magpie links the skill into <project>/.claude/skills for Claude Code and <project>/.agents/skills for Codex, Gemini CLI, OpenCode, Pi, Cursor and Copilot (the agents documented to read it; MiMo Code, Crush, ZCode, DeepSeek Harness and oh-my-pi aren't, so they're left out), or copies it when the project asks for copies, a copy made again whenever the library's skill changes (updates included). What it places is listed between magpie's marks in the project's .gitignore, made if there was none; taking a skill or the project away removes only what magpie placed, its lines and the folders it made once empty, and a folder of the same name that isn't magpie's is left as it is and said so. The home folder, or one whose project skills folder is an agent's own, can't be added 2026-09-28 13:34:17 +08:00
yetone 41cbe54a14 library: which skills from GitHub have changed there can be checked — Check for updates asks GitHub for the last commit to each skill's folder (one request per folder, a repository's skills together; once GitHub limits requests the rest are left unknown, each skill's trouble its own) and a changed one carries an Update available pill whose tooltip has the commit's summary and date, a click opening the changes on GitHub; Update N fetches just those. The library keeps a hash of a skill's files as fetched and, once a check finds GitHub's files to be the same, the commit they're at, so a later check needs only the API; a skill installed before this is compared by its files, the repository fetched once 2026-09-28 13:11:25 +08:00
yetone e173710982 backup: the library goes with a backup and a WebDAV sync — the instructions, MCP servers and skills with their files, a fifth part, ticked by default (magpie backup/restore --no-library). A backup without keys leaves the servers' secret env and headers empty and a restore fills them from the servers kept here; a skill's file over 2 MB, or past 32 MB in all, stays behind; a path that climbs out of its skill is refused. What it replaces is kept with the library's backups. Tested from a sandbox: exported without keys, changed and removed things, imported — the server back with the local key kept, the skill back as files, run.sh still executable 2026-09-27 17:24:53 +08:00
yetone c025a927d7 library: DeepSeek Harness (dsh) gets the library — its MCP servers as marked inserts of the dsh-mcp-client plugin in every profile's cordis.patch.yml (id magpie-mcp-<name>), a row the user inserted read like any other agent's and one holding a !!js value left alone; AGENTS.md and skills in its folder. SSE servers and names dsh can't take are refused with a reason (#107) 2026-09-27 17:22:03 +08:00
yetone 3c5f60b1f3 library: Pi's MCP servers go in mcp-adapter.json when pi-mcp-adapter 3 is installed — it reads that file and no longer mcp.json, which it leaves to the MCP Pi is to have itself (nicobailon/pi-mcp-adapter#680); an mcp.json found then is moved over, as the adapter asks, and once mcp-adapter.json is there it is the file. Before 3, mcp.json as before 2026-09-27 17:10:49 +08:00
yetone 3597cbbcc3 library: instructions come in sets — Default and any others named, each its own text, one of them the one the agents read; a set is added, renamed, switched to and removed (after a confirm, never the one in use or Default) in Library → Instructions, and a setup snapshot keeps which was in use. Providers: each protocol keeps its own URL, so a saved chat URL no longer shows as the Anthropic one; a URL typed and not saved yet moves to the protocol picked after it, spelled as that one wants it (/v1 dropped for Anthropic, added for OpenAI). Settings: an open WebDAV, export or import form is no longer emptied when the window regains focus. Tested in the browser from a sandbox. Issues #104 #105 #106 2026-09-27 17:05:59 +08:00
smallnest 03a01a548d agent: MiMo Code — Xiaomi's fork of OpenCode, sharing its config shape (#98)
* agent: MiMo Code — a terminal coding assistant that is Xiaomi's fork of OpenCode, whose config keeps OpenCode's shape: its own mimocode.json(c) under ~/.config/mimocode, its auth beside it, and a magpie provider block with npm/@ai-sdk/openai-compatible, model and small_model fields. opencode() becomes openCodeLike() for the two to share it, and magpieProviderJSON splits shape from the catalog id (magpieProviderJSONFor), so a visibility narrowed on mimocode (magpie visible mimocode …) narrows its list and leaves OpenCode's alone. The library gives it the same instructions, MCP servers (its mcp key) and skills as OpenCode, except the shared skills go into its own skills/ folder: it reads Claude Code's skills only behind a flag, though it reads its CLAUDE.md like OpenCode, and the page says so. Its requests are told by the mimocode/ User-Agent. Checked against XiaomiMiMo/MiMo-Code

* icon: MiMo Code's own favicon, from packages/ui/src/assets/favicon — its frame with the bottom bar, in the monochrome the app masks to the text colour
2026-09-27 08:42:44 +08:00
yetone 3651b45e00 library: the skills.sh test counts its fetches atomically — the market asks for the skills' pages at once, so the test server's handler runs on several goroutines and go test -race called the plain counter a race 2026-09-27 04:55:15 +08:00
yetone a90e9ae4e5 library: every skill from GitHub is updated with one click — the Library's skills page has Update all beside the skills in the library (and magpie library skill update with no name does it from the command line): each repository is fetched once however many of its skills there are, the agents are written once, and a skill that couldn't be fetched is said while the rest are updated all the same. Asked for on Discord 2026-09-27 04:21:14 +08:00
yetone 8630e4c62a tui: the routing page (3, was groups) does what the app's Routing view does — an open group lists its rules under its models, one list: n adds a rule typed as magpie group rule add takes it (use=<model> tokens=200k images effort=… agents=… intent="…" classifier=<model> at=<n>), ↵ types one again in place, J/K moves it, d twice removes it; c picks the classifier, s how long a conversation stays, x the context agents are told, R renames the group (the page follows it); a found group that was removed is listed last and u brings it back; smart routing is shown as smart, not in order, and o goes round all four. The library page adds too: a adds an MCP server (a URL, or a command) or skills from a GitHub repository or a folder, e changes a server (its env, headers and agents kept), u fetches a skill from GitHub again, s syncs the library into the agents. The rule parsing moves to provider (ParseRule, RuleWords, Rule.Line) and a typed server to library (ServerOf), for the CLI and the TUI alike. Asked on Discord 2026-09-26 23:08:58 +08:00
yetone 0218eeb5ca rtk: an agent left with the hook of an rtk that isn't installed (never was, or removed since) is shown with RTK missing — its shell commands fail — and can still be switched off: magpie takes out just what rtk's installer put in (the hook in settings.json / hooks.json, RTK.md and the @RTK.md line, Gemini's hook script, Copilot's instructions block, the OpenCode / Pi / OMP extension, Hermes' plugin) itself, needing no rtk, the files kept aside first; rtk's own uninstaller is no longer used, which deleted Gemini's GEMINI.md whole and took Claude Code, OpenCode and Cursor away together. Gemini is given rtk hook-only, so the user's GEMINI.md isn't written over. Install RTK on the page (and magpie library rtk install) installs rtk with Homebrew, winget on Windows, or rtk's own script into ~/.local/bin, only when clicked 2026-09-26 21:53:05 +08:00
yetone 631e4c3096 library: RTK (rtk-ai.app) can be switched on per agent — a Library tab lists the agents RTK has a hook for (Claude Code, Codex, Gemini CLI, OpenCode, Cursor, Copilot, Pi, OMP, Hermes), each with a switch that runs RTK's own installer (rtk init -g …) for it, keeping the files it edits aside first; which have it is read from their files, and the tab says RTK's version and the tokens it saved. RTK's installers for OpenCode and Cursor give it to Claude Code too, and its uninstaller for Claude Code or OpenCode takes all three: magpie keeps each switch to its own agent. magpie library rtk [on|off <agent>] does it from the CLI. Asked on X 2026-09-26 19:25:23 +08:00
yetone 7a3c434610 agents: Alma — magpie wires it through Alma's local API (localhost:23001, while Alma runs): choosing one of magpie's models for Alma adds a provider named magpie there (OpenAI type, the gateway's /v1, key magpie), offers magpie's models in it and makes the model Alma's default chat model, the rest of Alma's settings and its other providers left as they are; the list is kept current as magpie's catalog changes, and going back to Alma's own takes magpie's provider out. Asked on Discord 2026-09-26 19:18:51 +08:00
yetone c0e6d985de library: ZCode gets the library — its instructions go to ~/.zcode/AGENTS.md, its skills to ~/.zcode/skills and its MCP servers to ~/.zcode/cli/config.json's mcp.servers, where ZCode's own MCP settings keep them (a server of the user's there, and the file's other keys, stay as they are). magpie library … agents no longer takes an agent it has no place in for that: an unknown one, or one without MCP (omp) or instructions (Cursor), is refused with why, instead of recorded and given nothing (asked on Discord) 2026-09-26 16:18:56 +08:00
yetone 0f9d60db07 library: the MCP servers an agent's app writes into its config itself (Codex's node_repl and cua_repl, run from inside its install) are told apart — not offered to bring in, shown as the agent's own and left as they are; magpie library lists what agents have that the library doesn't 2026-09-26 14:34:53 +08:00
Zhizhen HeandClaude Code f3d567e07e agent: TOML tables magpie edits end where the parser says — a table no longer swallows the [[skills.config]] blocks that follow it. A write that would leave an invalid config is refused with its file, line and column
Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-26 13:46:03 +08:00