Skip to content

feat(marketplace): distribute Magpie 0.2.0 via agent marketplaces + auto-upgrade hook - #907

Open
potiuk wants to merge 15 commits into
apache:mainfrom
potiuk:feat/marketplace-distribution-0.2.0
Open

feat(marketplace): distribute Magpie 0.2.0 via agent marketplaces + auto-upgrade hook#907
potiuk wants to merge 15 commits into
apache:mainfrom
potiuk:feat/marketplace-distribution-0.2.0

Conversation

@potiuk

@potiuk potiuk commented Jul 19, 2026

Copy link
Copy Markdown
Member

Prepares Apache Magpie 0.2.0 for release through existing agent-skill marketplaces, and wires automatic upgrade detection. Refs #518.

Approach

Package the whole framework as a single magpie plugin whose skills points at the existing ./skills tree — no file moves, no vendored copies, no symlinks (PRINCIPLES §13 intact). The marketplace path is positioned as a discovery/trial channel alongside /magpie-setup full adoption; the canonical release stays the signed ASF source artefact on dist.apache.org.

Manifests added (one plugin, referenced by each ecosystem)

Ecosystem Files Confidence
Claude Code .claude-plugin/marketplace.json, .claude-plugin/plugin.json authoritative (current docs)
Gemini CLI gemini-extension.json (skills auto-discovered) authoritative
Codex CLI .codex-plugin/plugin.json, .agents/plugins/marketplace.json best-effort — verify
GitHub Copilot marketplace.json (repo root) best-effort — verify
microsoft/apm apm.yml (type: skill, multiplexes to Claude/Cursor/Codex/Copilot/Gemini) best-effort, schema v0.1 — verify
Cursor / Kiro / OpenCode consume the above / native SKILL.md git-install docs only
Windsurf / Goose no SKILL.md path (documented)

Plus docs/setup/marketplaces.md (per-agent install + the non-mappings) and version_manifest_files wiring so release-prepare keeps the manifest versions in sync with pyproject.toml.

Auto-upgrade detection

A Claude Code SessionStart hook (hooks/check-upgrade.sh) detects when the marketplace updated the plugin to a new version and prompts /magpie-setup upgrade to reconcile snapshot/overrides/drift. Detect-and-prompt, not auto-run — Claude Code hooks cannot invoke a slash command, and Magpie never mutates an adopter repo without the guided skill's confirmation (also avoids the auto-running-hook risk raised on #518). Claude Code-only; Codex/Gemini have no equivalent lifecycle hook.

Reviewer notes

  • Supersedes docs(readme): mark public skill marketplace as not yet implemented #905's README wording — this makes the "public skill marketplace" real, so the "planned but not yet implemented" note becomes "installable via …". docs(readme): mark public skill marketplace as not yet implemented #905 can be closed as superseded (or merged first and this rebased).
  • Namespacing to verify: skills carry name: magpie-<x> frontmatter, so under a plugin named magpie invocation may double up (/magpie:magpie-release-vote-tally). Test against a live install; if so, we either drop the magpie- frontmatter prefix or rename the plugin.
  • The best-effort manifests should be validated against each vendor's current tool before an actual marketplace publish — none of them affect how the ASF source release is built or signed.

Opened as draft pending that live validation.

potiuk added 3 commits July 19, 2026 05:31
Package the framework as a single 'magpie' plugin (skills: ./skills, all 70)
and add the manifests each agent marketplace needs, referencing the existing
skills tree with no vendored copies:

- Claude Code:  .claude-plugin/marketplace.json + plugin.json
- Codex CLI:    .codex-plugin/plugin.json + .agents/plugins/marketplace.json
- Copilot:      marketplace.json (repo root)
- Gemini CLI:   gemini-extension.json (skills auto-discovered)
- microsoft/apm: apm.yml (type: skill; multiplexes to Claude/Cursor/Codex/Copilot/Gemini)

Adds docs/setup/marketplaces.md (per-agent install, incl. Kiro/OpenCode
git-install and the Windsurf/Goose non-mappings), positions the marketplace
path as a discovery/trial channel alongside /magpie-setup, keeps the ASF
source release canonical, and wires the version-bearing manifests into
version_manifest_files so release-prepare keeps them in sync.

Refs apache#518.
Add a Claude Code SessionStart hook (hooks/check-upgrade.sh, wired via the
plugin's hooks block) that detects when the marketplace has updated the
Magpie plugin to a new version and prompts the user to run
`/magpie-setup upgrade` to reconcile the snapshot, agentic overrides, and
drift.

Detect-and-prompt, not auto-run: Claude Code hooks cannot invoke a slash
command, and Magpie never mutates an adopter repo without the guided skill's
confirmation, so the trigger is automatic while the changes stay confirmed.
Claude Code-only; Codex/Gemini have no equivalent lifecycle hook.
Extend the update-detection prompt beyond Claude Code:

- Make hooks/check-upgrade.sh agent-neutral (resolves CLAUDE_/CODEX_ plugin
  root+data env vars; reads version from whichever plugin manifest is present).
- Codex CLI: wire the same script via the plugin's hooks block (schema
  best-effort, flagged for verification before publish).
- Gemini CLI: ship GEMINI.md extension context (contextFileName) instructing
  the agent to compare the extension version to a recorded marker and prompt
  for /magpie-setup upgrade on change — Gemini has no lifecycle hook.

Documented per-agent in docs/setup/marketplaces.md.
@potiuk
potiuk force-pushed the feat/marketplace-distribution-0.2.0 branch from 4864c08 to 1ecaade Compare July 19, 2026 03:32
@potiuk
potiuk marked this pull request as ready for review July 19, 2026 11:47
…l (adopt alias)

Folds the top-level README simplification from apache#901 (by @meonkeys) into the
0.2.0 marketplace work, and shifts the primary term to 'install' now that
marketplace installation exists:

- Keeps Adam's simplified Install / Usage / Update / Skill-families structure.
- Install section covers both paths: agent marketplace (easiest, nothing
  committed) and the committed snapshot via /magpie-setup.
- 'install' is the primary verb/command; '/magpie-setup adopt' stays an alias;
  'Adopt a Magpie' remains the landing-page slogan; 'adopter'/'adopter repo'
  kept as the ecosystem noun.
- Repoints inbound doc links from the removed README#adopting-the-framework
  anchor to README#install and updates their labels.

Supersedes the standalone apache#901 (its Fix apache#899 goal already merged via apache#905).
Credit to @meonkeys for the simplification.
potiuk added 6 commits July 19, 2026 16:33
Keep 'adopt' for the project relationship and 'install/installation' for the
process, per the terminology model: a project adopts Magpie into its source;
/magpie-setup installs the snapshot.
…marketplace

Expand docs/setup/marketplaces.md from a one-line-per-agent table into
step-by-step instructions for installing Magpie from the apache/magpie
GitHub repo-as-marketplace: add marketplace, install, verify, invoke, update
— for Claude Code, Codex, Copilot, Gemini, Cursor, apm, Kiro, OpenCode.
States plainly that the GitHub repo is the marketplace (no vendor official
directory needed) and how to pin a tag vs track main. Verify-flagged the
still-evolving CLIs (Codex/Copilot/apm/Cursor).
…en cost

Live-tested that Claude Code's plugin 'skills' field rejects paths outside the
plugin dir, so per-family plugins reference the shared skills/ tree via
single-hop symlinks (no copies, single source of truth).

- Add 10 family plugins under plugins/magpie-<family>/ (security, release-
  management, setup, pr-management, issue, repo-health, contributor-growth,
  utilities, mentoring, pairing), each a .claude-plugin/plugin.json + a skills/
  dir of symlinks into ../../../skills/<skill>.
- marketplace.json now lists the all-in-one 'magpie' plugin plus the 10
  families. Family plugin.jsons omit version and inherit it from the
  marketplace entry (centralised versioning).
- Verified via real installs: e.g. magpie-security = 12 skills / ~3.9k
  always-on, magpie-pairing = 2 / ~0.6k, vs the all-in-one 70 / ~21.7k.
- Namespacing confirmed clean: /magpie-<family>:<skill> (dir name, no
  magpie- frontmatter double-prefix).

Docs: docs/setup/marketplaces.md gains the all-in-one-vs-per-family guidance
and per-family token costs.
…caveat

- tools/dev/check-family-plugins.py: validates that plugins/magpie-<family>/
  match the skills' family: frontmatter (each family's skills present as
  single-hop symlinks into skills/, and listed in marketplace.json). Catches a
  new skill, a changed family, or a stale symlink. --fix regenerates them.
- Wire it as a local prek hook (runs when a SKILL.md, a family plugin, or the
  marketplace manifest changes).
- docs/setup/marketplaces.md: document that per-family plugins rely on git
  symlinks — on Windows enable core.symlinks + Developer Mode, or use the
  all-in-one magpie plugin (no symlinks). Verified symlinks survive a GitHub
  clone on macOS.
Spell out that you can install either the all-in-one magpie plugin or any
number of per-family plugins (and mix families), with the pros/cons of each:
simplicity + Windows-safe (no symlinks) vs proportional always-on token cost.
Comment thread tools/dev/check-family-plugins.py Fixed
Comment thread tools/dev/check-family-plugins.py Fixed
Comment thread tools/dev/check-family-plugins.py Fixed
potiuk added 4 commits July 19, 2026 17:12
…o the portable non-marketplace install

Add a WARNING callout: plugin/marketplace mechanisms across the agentic CLIs
(Claude Code, Codex, Copilot, Gemini, apm) are experimental and change between
releases. The non-marketplace /magpie-setup install from the signed SVN release
or the GitHub repo is always available, harness-neutral, and portable — it
works on every agentic CLI via the universal .agents/skills/ layout, not just
the ones with a marketplace.
…hods

Same skill, different invocation name: portable /magpie-setup install bakes a
magpie- prefix into each skill (invoked /magpie-<name>), whereas a marketplace
plugin namespaces with plugin:skill and keeps the bare name (/magpie:<name> for
the all-in-one, /magpie-<family>:<name> for a family plugin). Adds a comparison
table + examples and notes that repo cross-references use the portable form.
Resolves the 3 CodeQL 'file is not always closed' alerts (35/36/37) flagged on
apache#907. Rewrite the family-plugin validator with pathlib — Path.read_text /
write_text open-and-close by construction, so no dangling handles — and the
same read/write/symlink logic reads cleaner. Behaviour unchanged (check/--fix
verified: passes, idempotent, catches drift).
Extend check-family-plugins to confirm every plugin is properly defined:
- all-in-one 'magpie' manifest names itself, declares skills: ./skills, and
  wires the hooks/check-upgrade.sh SessionStart hook (which must exist);
- every marketplace.json entry resolves to a matching, uniquely-named
  plugin.json (catches dangling sources, name mismatches, duplicates);
- each per-family manifest is well-formed (name/skills/description) in addition
  to the existing symlink-vs-frontmatter check.
Also trigger the hook on .claude-plugin/plugin.json and hooks/check-upgrade.sh
changes.
@potiuk

potiuk commented Jul 26, 2026

Copy link
Copy Markdown
Member Author

Looking for reviews :)

@choo121600 choo121600 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks good to me :)
let's go 0.2.0!

@choo121600 choo121600 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit;
claude plugin validate . --strict from the repo root comes back with 20 warnings. Nothing is actually broken.
I installed a family plugin from a local replica of this branch and it enables fine, picks up 0.2.0 from the marketplace entry, and its skills load. So this is hygiene, not a bug.

Image

`claude plugin validate . --strict` reported 20 warnings — each of the ten
per-family plugin manifests was missing `version` and `author`. Nothing was
broken (a family plugin installs and enables fine), but --strict treats the
warnings as errors, so the repo root failed validation.

Rather than hand-edit ten generated files, make the shared metadata inherited:
`tools/dev/check-family-plugins.py` now copies `version`, `author`, `homepage`,
`repository`, and `license` from the all-in-one `.claude-plugin/plugin.json`
into every family manifest, and `check` fails if any of them — or a marketplace
entry version — drifts from the root. This also removes the hardcoded
`"version": "0.2.0"` in `--fix`, which would have silently reset the family
marketplace entries to 0.2.0 after a release bump.

A bump now has one edit point (the root manifest) plus
`python3 tools/dev/check-family-plugins.py --fix` to propagate; the prek hook
catches a missed propagation. Documented in the release config's
`version_manifest_files` notes and docs/setup/marketplaces.md.

`claude plugin validate . --strict` now passes with 0 warnings.
@potiuk

potiuk commented Jul 29, 2026

Copy link
Copy Markdown
Member Author

Thanks — reproduced exactly: 20 warnings, plugins[1]plugins[10], each missing version and author. Fixed in 28062dc; claude plugin validate . --strict now passes with 0 warnings.

Worth noting why it wasn't just a ten-file edit: those manifests are generated by tools/dev/check-family-plugins.py --fix, so hand-adding the fields would have been wiped on the next regeneration. Instead the shared metadata is now inherited from the all-in-one .claude-plugin/plugin.jsonversion, author, homepage, repository, license — and check fails if any family manifest or marketplace entry version drifts from the root. One edit point per bump, enforced by the prek hook.

Your nit also surfaced a real latent bug next to it: --fix hardcoded "version": "0.2.0" for the family marketplace entries, so running it after a release bump would have silently reset all ten back to 0.2.0. It now reads the version from the root manifest, and refuses to run if the root manifest is missing the inherited keys.

Verified:

  • claude plugin validate . --strict: 20 warnings → passed
  • drift detection: bumping the root to 0.3.0 yields 21 errors (11 marketplace entries + 10 family manifests); --fix propagates; check passes again
  • --fix is idempotent (two consecutive runs byte-identical)
  • full prek run --all-files: all 23 hooks pass

Also documented the bump flow in the release config's version_manifest_files notes and docs/setup/marketplaces.md — a glob doesn't work there, since release-prepare reads each entry as a literal path via gh api contents/<file>.

Thanks for the local-replica install test too — good to have confirmation the family plugins enable and pick up 0.2.0 from the marketplace entry.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants