.agents/skills/magpie-setup/agents.md
Framework skills are vendor-neutral content: every supported
agent reads the same SKILL.md (the open Agent Skills format —
plain Markdown + a small YAML frontmatter). The skill body is
byte-identical no matter which agent loads it; there is no
per-agent compile, adapter, or content transform. The only thing
that genuinely differs between agents is where on disk each one
looks for skills. This file is the registry of those locations —
the single source of truth adopt, upgrade, verify,
unadopt, and worktree-init consult to decide which directories
to wire, refresh, health-check, and tear down.
It is the magpie analogue of a package manager's per-agent path table: keep all vendor-specific knowledge here as "where files go", never as "what files contain".
| Target id | Project skills dir | Kind | Reads it |
|---|---|---|---|
universal | .agents/skills/ | universal (canonical) | Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode, Cline, Zed, Warp, Amp, and the rest of the cluster that converged on the shared path |
claude-code | .claude/skills/ | native (relay) | Claude Code |
github | .github/skills/ | native (relay) | GitHub's skill loader |
windsurf | .windsurf/skills/ | native (relay) | Windsurf |
goose | .goose/skills/ | native (relay) | Goose |
The table is extensible: a new agent that wants framework
skills is one new row (id, project dir, kind), nothing else —
the same way a path-registry-driven installer adds an agent. Do
not invent per-agent content; if an agent needs a different
directory, add a row, never a forked skill.
.agents/skills/.agents/skills/ is the one canonical home for every framework
skill. Its magpie-<skill> entries are the links that resolve to
the actual skill source — the gitignored snapshot
(.apache-magpie/skills/<skill>/) for a normal adopter, or the
in-repo ../../skills/<skill>/ source for the framework's own
local self-adoption.
This is the load-bearing move for neutrality on two fronts:
One placement covers the whole shared-path cluster. A large
set of agents (Codex, Cursor, Gemini CLI, GitHub Copilot,
OpenCode, Cline, Zed, Warp, …) all read .agents/skills/ as
their project-scope skills path, so a single
.agents/skills/magpie-<skill> link is seen by all of them:
.agents/skills/magpie-pr-management-triage → the canonical link
├─ Codex picks it up
├─ Cursor picks it up
├─ Gemini CLI picks it up
└─ Copilot … picks it up
Every other target is a thin relay into it. Agents with a
bespoke folder (claude-code → .claude/skills/, github →
.github/skills/, windsurf, goose, …) do not link into
the snapshot independently. Each one gets a per-skill relay
symlink that points back at the canonical entry:
.claude/skills/magpie-<skill> → ../../.agents/skills/magpie-<skill>
.github/skills/magpie-<skill> → ../../.agents/skills/magpie-<skill>
The snapshot path appears exactly once — in
.agents/skills/. Re-pointing the framework at a new snapshot,
or repairing a broken link, is a single-source operation; the
relays follow automatically. Adopters keep their own native
(non-magpie-) skills in .claude/skills/ / .github/skills/
untouched — only the magpie-* entries are relayed.
(Global / per-user skill paths diverge across agents — e.g.
~/.cursor/skills/, ~/.codex/skills/, ~/.gemini/skills/. The
framework's adoption is project-scope — it writes inside the
adopter repo — so it only ever cares about the project columns
above. Global installs are the operator's concern, out of scope
for setup.)
adopt wiresOn every adopt / upgrade / worktree-init, the active
target set is computed as the union of:
universal
(.agents/skills/, canonical) plus the claude-code +
github relay pair. These three are wired unconditionally; the
relays are cheap relative symlinks, harmless to an agent that
never reads them, and dropping them is not a supported
configuration..windsurf/skills/ or .goose/skills/ (etc.) already
exists as a real directory, it is added to the active set so
that agent sees the framework skills too (as a relay).agents:<list> flag (see
SKILL.md Inputs) — a comma-separated list
of registry ids. When passed it replaces the auto-detected
set (1)+(2) for that run; universal is always retained even
if omitted, because it is the canonical home every relay points
at — dropping it would leave the relays dangling.The flow never removes or rewrites an adopter's own
non-magpie- skill content in any target dir. It only adds /
repairs magpie-* symlinks. Whatever layout an adopter's
.claude/ / .github/ directories were in before, the framework
always wires the magpie-* set the same way: canonical in
.agents/skills/, relayed everywhere else.
Every adoption rule is "canonical link, then relays", not "per-target independent link":
magpie- prefix (SKILL.md Golden rule 6)
— unchanged. Every framework skill is magpie-<skill> in
every active target dir, so it never collides with an
adopter's own skills regardless of agent..gitignore — one uniform block per active target dir,
with no per-layout variation: /<dir>/magpie-* ignored plus
!/<dir>/magpie-setup un-ignored. The negation keeps the one
committed bootstrap (magpie-setup) tracked; the glob ignores
the rest (the canonical links target the gitignored snapshot, so
the relays that follow them dangle on a fresh clone). See
adopt.md Step 7.magpie-<n> →
snapshot/source link is created once in .agents/skills/; every
other active target (claude-code, github, windsurf,
goose, …) gets a per-skill relay magpie-<n> →
../../.agents/skills/magpie-<n>. See
adopt.md Step 8.SKILL.md Golden rule 6)
— the one committed framework artefact, magpie-setup, lives at
the canonical .agents/skills/magpie-setup/ (a committed
copy for adopters; a committed symlink under self-adoption).
.claude/.github carry a committed relay symlink to it.../../skills/<skill>/ in
.agents/skills/, plus committed relays into
../../.agents/skills/magpie-<skill> in every other active
target. See
adopt.md → Local self-adoption.unadopt / worktree-init — every active target dir is
torn down / propagated uniformly. Removing only .claude +
.github would orphan the canonical .agents/skills/magpie-*
links; removing only .agents would leave every relay dangling.The same SKILL.md is valid in every target with no
per-agent edit:
| Frontmatter field | Cross-agent behaviour |
|---|---|
name, description | Universal — discovery works everywhere. |
when_to_use | Claude-family routing hint; other agents may ignore it → discovery still works off description, only routing precision degrades. |
argument-hint, capability | magpie / Claude extensions; non-supporting agents silently ignore them. |
license | Inert metadata. |
Unknown frontmatter is ignored by each agent (graceful
degradation), so there is no compile step and no per-agent
file. The gitignored snapshot stays the single source of truth;
.agents/skills/ links into it, and every other target dir
resolves into it through the .agents/skills/ relay.
Some of what adopt installs is genuinely Claude-Code-specific
and is wired only when the claude-code target is active:
.claude/settings.json — the sandbox (network.allowedDomains
allowlist, filesystem.denyRead), the MCP-tool permission
allowlist, and the hooks. Schema:
claude-code-settings.json..claude/settings.local.json — per-machine sandbox-allowlist
entries.setup-isolated-setup-* skill family — sandbox / pinned-
tools / hooks installer.Other agents adopt the skills (the neutral content) without this layer.
Security caveat — this layer is a control, not cosmetics. For a security framework the sandbox is a confidentiality control (it blocks exfiltration of non-public vulnerability data and reading
~/). Running a security-class skill on an agent that lacks an equivalent control is a policy decision, not graceful degradation. Adopting the skills onto a non-Claude agent is supported; executing confidential workflows there requires the project to either declare that agent unsupported for those workflows or provide an equivalent control.adoptitself only places files — it does not grant that approval.