| <!-- SPDX-License-Identifier: Apache-2.0 |
| https://www.apache.org/legal/release-policy.html --> |
| |
| # agents — the agent-target registry (where framework-skill symlinks land) |
| |
| 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"*. |
| |
| ## The registry |
| |
| | 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 | |
| | `kiro` | `.kiro/skills/` | native (relay) | Kiro CLI | |
| |
| 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. |
| |
| ## The canonical directory — `.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](adopt.md#local-self-adoption-methodlocal). |
| |
| This is the load-bearing move for neutrality on two fronts: |
| |
| 1. **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: |
| |
| ```text |
| .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 |
| ``` |
| |
| 2. **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: |
| |
| ```text |
| .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`.) |
| |
| ## Active-target selection — which dirs `adopt` wires |
| |
| On every `adopt` / `upgrade` / `worktree-init`, the **active |
| target set** is computed as the union of: |
| |
| 1. **The always-on neutral targets** — `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. |
| 2. **Any other registry target already present in the repo** — |
| if `.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). |
| 3. **Explicit opt-in** via the `agents:<list>` flag (see |
| [`SKILL.md` Inputs](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. |
| |
| ## How the framework's rules generalise across targets |
| |
| Every adoption rule is "canonical link, then relays", not |
| "per-target independent link": |
| |
| - **`magpie-` prefix** ([`SKILL.md` Golden rule 6](SKILL.md#golden-rules)) |
| — 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](adopt.md#step-7--gitignore-entries-fresh-only). |
| - **Symlink wiring** — the canonical `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](adopt.md#step-8--wire-up-the-framework-skill-symlinks). |
| - **Committed bootstrap** ([`SKILL.md` Golden rule 6](SKILL.md#golden-rules)) |
| — 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. |
| - **Local self-adoption** (framework checkout) — canonical |
| committed symlinks into `../../skills/<skill>/` in |
| `.agents/skills/`, plus committed relays into |
| `../../.agents/skills/magpie-<skill>` in every other active |
| target. See |
| [`adopt.md` → Local self-adoption](adopt.md#local-self-adoption-methodlocal). |
| - **`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. |
| |
| ## SKILL.md format portability |
| |
| 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. |
| |
| ## The Claude-Code-only layer (not wired for other targets) |
| |
| 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. |
| - The `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. `adopt` |
| > itself only places files — it does not grant that approval. |