The page already sends one request for a group (agents-some), but its one
change ran a sync that, for every skill given as a copy (every WSL agent,
Windows without the right to link, agents set to copies), hashed the copy
and the library's skill twice, in every agent, on every change, and the
page's read hashed the copies once more. Over a WSL distro's share that is
every file of every skill read through 9P each click.
A copy's mark now keeps the hash of what was copied (markCopy). A copy
whose mark says the library skill's current hash, with nothing in it newer
than the mark, is current without its files being read (copyIsFresh);
takeEdits' walk of a copy is not done a second time in the same sync, and
each library skill is hashed once per change (libHash). Copies with an old
mark, or edited since, are hashed as before. Claude Desktop's copies and
project copies use the same check.
Measured in a sandbox (55 skills x 31 files, copies for 10 agents, a
5-skill group switched on for an 11th): the change went from 1.54s to
0.31s and the page's read from 0.66s to 0.25s on a local SSD; the copies
not touched are no longer read at all, which is the cost over WSL.
TestSyncDoesNotReadUnchangedCopies fails without the change ("codex's
copy of pdf was read and made again"): an unreadable file in an unchanged
copy is left alone now. TestCopyFreshByMark checks a changed library skill
is still copied again, an old mark without a hash still works, and an edit
in a copy is still taken. go test -race ./internal/library ./internal/gui
pass, the new tests pass -race -count=10; vet, gofmt, darwin/linux/windows
builds pass. Not run on Windows or WSL.
6.7 KiB
6.7 KiB
Library: instructions, MCP servers, skills and RTK
The library keeps what every agent should know in one place: the
instructions each agent reads before a conversation, the MCP servers it can
call, and the skills it can load. magpie writes these into each agent's own
files in that agent's format, and takes back only what it wrote. Everything
else in those files stays as it was. Package internal/library also gives
agents RTK, a CLI that cuts shell output down before the model reads it.
Responsibilities and sources of truth
| Part | Responsibility | Source |
|---|---|---|
| library.json | Library holds the instruction sets, the MCP servers, the skills, the projects, skill groups and copy settings. Applied records what magpie last wrote into each agent, so it only ever takes away its own. The instruction texts and skill folders live under Dir (library/ in magpie's config folder). |
library.go |
| One change | change locks the library, loads it, applies one edit, saves, syncs every agent and saves again. Every exported mutation (SaveServer, InstallSkills, SetSkillHow and the rest) goes through it. One change runs at a time, whether from the page or the CLI. |
library.go |
| Targets | Targets lists the detected agents (agent.Detected), plus apps like Claude Desktop, with where each keeps its instructions file (and an Override it reads instead), its MCP file and its skills folder. |
targets.go |
| Sync | sync writes each target's instructions and MCP servers. It then takes edits made in agents' skill copies into the library (takeEdits) and links or copies the skills. ~/.agents/skills goes first, so an agent that reads it gets no second link. Then it syncs projects' skills. |
sync.go |
| Instructions | magpie's part of an agent's instructions file sits between two marker lines. The rest of the file is the user's. Several named sets can be switched between (#106). | instructions.go |
| MCP servers | A Server is a command or a URL (http, sse). mcpFile encodes it in each agent's own format (one mcpFormat per agent family) and merges it with the user's own fields for that entry. Also files get the same servers; Extra files are only read when importing. CheckServers connects as an agent would and keeps the result in memory only. A server that needs OAuth is signed in once in magpie, and agents reach it through the gateway's /mcp/<name> (#615). |
mcp.go, mcp_check.go, mcp_signin.go |
| Skills | A skill is a folder with a SKILL.md. It comes from GitHub, from a folder on this machine (linked, so editing the folder edits the skill) or from the market. Each agent gets a link or a marked copy (#896, SkillHow). An agent in a WSL distro always gets a copy. A copy's mark keeps the hash of what was copied, so a sync knows a copy unchanged since then is current without reading its files (copyIsFresh, #1031); other copies are hashed. |
skills.go, skill_how.go, skill_edits.go, skill_from.go |
| Backups | Before a change first writes an agent file, backups copies it to BackupDir, one folder per change. The last keepBackups (30) changes are kept. |
backup.go |
| RTK | SetRTK runs rtk's own installer (rtk init -g …) for an agent being switched on. For one being switched off, it removes exactly what the installer wrote, using magpie's own code, which works even with rtk gone. ReadRTK reads each agent's files to say which have the hook. rtkSpec.blocked stops the installer where it would break an agent. A detected agent RTK has no hook for at all is still listed, from rtkNoHook, with the reason and a switch that can't be turned on (dsh: its hooks can allow or deny a command but not rewrite it, and rtk init has no --agent dsh). |
rtk.go |
Runtime path
- Edit. The Library page or
magpie librarycalls an exported function such asSaveServer,ServerAgents,InstallSkills,SkillAgentsorSetSkillHow. The skills and servers pages each have Select, Turn all on, Turn all off and Remove all. Select's bar callsSomeSkillsAgentsorSomeServersAgents(/api/library/{skills,servers}/agents-some), Turn all on or off callsEverySkillAgentsorEveryServerAgentsfor the agents shown, and Remove all callsRemoveSkillsorRemoveServers. Each of these is one change that takes every item out as a single removal would (#1027). - Change.
changeeditslibrary.jsonunder the lock and callssync. - Write. For each target,
syncInstructionsandsyncMCPwrite magpie's part in the agent's format and record it inApplied. Skills are linked or copied into the agent's skills folder. A copy edited since it was made is taken into the library first. - Result. The
Resultlists the agents changed, aProblemfor each thing that couldn't be given, and the backup folder.
Constraints and failure behavior
- magpie takes away only what
Appliedor its mark says it wrote. A folder of the user's with a skill's name is never touched. The user's own fields in an MCP entry are kept. - An edit never silently loses. When an agent's copy of a skill and the library both changed, the newest edit wins, and the losing one is kept with the backups.
- A failure for one agent is a
Problemin the result. It doesn't stop the others. - A server an agent can't reach is not written there, and
mcpFile.supportssays why. For example, Claude Desktop takes no remote server, and Codex, Goose, dsh, Grok and Command Code take no SSE. - Removing RTK never uses
rtk init --uninstall. That command deletes Gemini'sGEMINI.mdwhole and removes Claude Code, OpenCode and Cursor together. - CC Switch's own skills folder is only ever read.
Verification
go test -tags nogui ./internal/library -run 'TestTargets|TestServer|TestImportServer|TestCheck|TestInstructions|TestInstructionSets|TestSkill|TestEverySkillAgents|TestEveryServerAgents|TestSomeServersAgents|TestRemoveServers|TestRTK'
go test -tags nogui ./internal/library
node --test internal/gui/tests/library-items.test.cjs internal/gui/tests/library-rtk-gain.test.cjs internal/gui/tests/library-rtk-nohook.test.cjs internal/gui/tests/library-servers-bulk.test.cjs
The package's TestMain runs in a home of its own (testenv), never the
user's real agent files.