diff --git a/.agents/adr/0002-ship-as-a-claude-code-plugin.md b/.agents/adr/0002-ship-as-a-claude-code-plugin.md new file mode 100644 index 0000000..8902f9d --- /dev/null +++ b/.agents/adr/0002-ship-as-a-claude-code-plugin.md @@ -0,0 +1,28 @@ +# Ship the skill set as a native Claude Code plugin; defer a native Codex plugin + +These skills have always been installable via [skills.sh](https://skills.sh/mattpocock/skills) (`npx skills add mattpocock/skills`), which copies editable skill files into a user's project across Claude Code, Codex, and other Agent-Skills-standard harnesses. A recurring request is a **plug-and-play** distribution: subscribe to the set as a read-only, always-current bundle you don't edit, rather than a fork you own. That is exactly what native plugin systems provide. + +We ship a native **Claude Code plugin** and, for now, **defer** a native **Codex plugin**. The split is forced by how each ecosystem's plugin manifest selects skills, against this repo's bucketed layout. + +## The constraint: bucketed skills vs. single-path selection + +Skills live in bucket folders under `skills/` — `engineering/` and `productivity/` are **promoted** (shipped); `misc/`, `personal/`, `in-progress/`, and `deprecated/` are **not**. A plugin must expose only the promoted set, which spans two of those bucket folders. + +- **Claude Code** — `.claude-plugin/plugin.json` accepts `skills` as an **array of explicit skill-directory paths**. We list the promoted skills one by one, exclude everything else with zero ambiguity, and add `.claude-plugin/marketplace.json` so the repo is its own single-plugin marketplace. Verified end to end: `claude plugin validate . --strict` passes, and `marketplace add` → `install` resolves all promoted skills. + +- **Codex** — `.codex-plugin/plugin.json` accepts `skills` only as a **single path string** (arrays are rejected with `missing or invalid plugin.json`), and Codex discovers `SKILL.md` files recursively under it. There is no way to name two bucket folders, or to curate a subset, from one path. Two escape hatches were tested and rejected: + - Pointing at `./skills/` would also ship `deprecated/`, `in-progress/`, `personal/`, and `misc/` — retired, draft, and personal skills we deliberately don't promote. + - A curated flat directory of **symlinks** into the buckets does not survive install: Codex copies the plugin tree into its cache and **drops symlinks**, so the skills arrive empty. + +The only robust ways to give Codex a single promoted-only path are (a) **restructure** so `skills/` contains only promoted skills (moving the non-promoted buckets out — a large blast radius across `CLAUDE.md`, `scripts/link-skills.sh`, the bucket READMEs, and the local dev workflow that relies on `in-progress/` and `personal/`), or (b) **commit duplicate copies** of promoted skills into a flat directory (a sync burden and a second source of truth). Both are structural decisions, not something to bundle into shipping the Claude plugin. This is very likely the original, half-remembered reason a plugin wasn't shipped earlier: the manifest formats didn't cleanly express a curated subset of a bucketed repo. + +## Decision + +- Ship the **Claude Code plugin** now (`.claude-plugin/plugin.json` + `.claude-plugin/marketplace.json`), curated to the promoted set, as the headline v1.2 deliverable. +- Keep **skills.sh** as the universal installer — it already serves Codex and other harnesses today, so no Codex user is left without an install path. +- **Defer** the native Codex plugin until we decide between restructuring `skills/` to promoted-only vs. committing a generated flat copy. Revisit when Codex either supports a `skills` array / include-list or preserves symlinks on install. + +## Invariants this creates + +- Every promoted skill has an entry in `.claude-plugin/plugin.json`'s `skills` array (this already stood as a `CLAUDE.md` rule; it now also gates the plugin's contents). +- `.claude-plugin/plugin.json`'s `version` tracks `package.json`'s version — bump both together on release. Claude uses the plugin `version` to decide when installed users see an update. diff --git a/.changeset/ship-as-claude-plugin.md b/.changeset/ship-as-claude-plugin.md new file mode 100644 index 0000000..b58c0d1 --- /dev/null +++ b/.changeset/ship-as-claude-plugin.md @@ -0,0 +1,12 @@ +--- +"mattpocock-skills": minor +--- + +Ship the skill set as a native **Claude Code plugin**. The repo is now its own single-plugin marketplace, so you can subscribe to the promoted skills as a managed, read-only bundle instead of copying editable files: + +``` +/plugin marketplace add mattpocock/skills +/plugin install mattpocock-skills@mattpocock +``` + +`.claude-plugin/plugin.json` gains full marketplace metadata (version, description, author, license, keywords) and a sibling `.claude-plugin/marketplace.json` lists the plugin. `skills.sh` remains the universal installer (and the path for Codex and other harnesses today); a native Codex plugin is deferred — see `.agents/adr/0002-ship-as-a-claude-code-plugin.md` for why. diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json new file mode 100644 index 0000000..2944f1d --- /dev/null +++ b/.claude-plugin/marketplace.json @@ -0,0 +1,23 @@ +{ + "name": "mattpocock", + "owner": { + "name": "Matt Pocock", + "url": "https://www.aihero.dev" + }, + "description": "Matt Pocock's skills for real engineering, as an installable Claude Code plugin.", + "plugins": [ + { + "name": "mattpocock-skills", + "source": "./", + "description": "Matt Pocock's agent skills for real engineering — grilling, spec/ticket flows, TDD, code review, domain modelling and more.", + "category": "engineering", + "keywords": [ + "engineering", + "skills", + "tdd", + "code-review", + "grilling" + ] + } + ] +} diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json index db81962..e324378 100644 --- a/.claude-plugin/plugin.json +++ b/.claude-plugin/plugin.json @@ -1,5 +1,23 @@ { "name": "mattpocock-skills", + "version": "1.2.0", + "description": "Matt Pocock's agent skills for real engineering — grilling, spec/ticket flows, TDD, code review, domain modelling and more. Plug-and-play, not vibe coding.", + "author": { + "name": "Matt Pocock", + "url": "https://www.aihero.dev" + }, + "homepage": "https://www.aihero.dev/s/skills-newsletter", + "repository": "https://github.com/mattpocock/skills", + "license": "MIT", + "keywords": [ + "engineering", + "skills", + "tdd", + "code-review", + "grilling", + "domain-modeling", + "productivity" + ], "skills": [ "./skills/engineering/ask-matt", "./skills/engineering/diagnosing-bugs", diff --git a/CLAUDE.md b/CLAUDE.md index 20ca92b..1a3d81a 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -7,7 +7,9 @@ Skills are organized into bucket folders under `skills/`: - `in-progress/` — drafts not yet ready to ship - `deprecated/` — no longer used -Every skill in `engineering/` or `productivity/` (the **promoted** buckets) must have a reference in the top-level `README.md` and an entry in `.claude-plugin/plugin.json`. Skills in `misc/`, `personal/`, `in-progress/`, and `deprecated/` must not appear in either. +Every skill in `engineering/` or `productivity/` (the **promoted** buckets) must have a reference in the top-level `README.md` and an entry in `.claude-plugin/plugin.json`'s `skills` array (the Claude Code plugin ships exactly the promoted set). Skills in `misc/`, `personal/`, `in-progress/`, and `deprecated/` must not appear in either. + +The repo is also its own single-plugin Claude Code marketplace: `.claude-plugin/marketplace.json` lists the one `mattpocock-skills` plugin. When bumping the release version, keep `.claude-plugin/plugin.json`'s `version` in sync with `package.json`'s — Claude uses the plugin `version` to decide when installed users see an update. Run `claude plugin validate . --strict` after touching either manifest. Why a Claude plugin but not (yet) a Codex one lives in [.agents/adr/0002-ship-as-a-claude-code-plugin.md](./.agents/adr/0002-ship-as-a-claude-code-plugin.md). Each skill entry in the top-level `README.md` must link the skill name to its `SKILL.md`. diff --git a/README.md b/README.md index 1b290f8..ebe022f 100644 --- a/README.md +++ b/README.md @@ -39,6 +39,33 @@ npx skills@latest add mattpocock/skills 4. Bam - you're ready to go. +## Install as a Claude Code plugin + +Prefer a plug-and-play install you don't maintain by hand? These skills also ship as a native [Claude Code plugin](https://code.claude.com/docs/en/plugins). Instead of copying editable files into your repo, the plugin installs the whole skill set as a managed bundle that updates when I ship a new version — you subscribe rather than fork. + +Inside Claude Code: + +``` +/plugin marketplace add mattpocock/skills +/plugin install mattpocock-skills@mattpocock +``` + +Or from your shell: + +```bash +claude plugin marketplace add mattpocock/skills +claude plugin install mattpocock-skills@mattpocock +``` + +Then run `/setup-matt-pocock-skills` once per repo, exactly as in the quickstart above. + +Two ways to install, two philosophies: + +- **[skills.sh](https://skills.sh/mattpocock/skills)** copies the skills into your project so you can hack on them and make them your own. +- **The plugin** keeps them as a read-only, always-current bundle you don't edit — best when you just want my set to work and follow along as it evolves. + +> Using Codex or another agent? The [skills.sh installer](https://skills.sh/mattpocock/skills) already installs these skills into Codex and other Agent-Skills-standard harnesses today. A native Codex plugin is on the roadmap — see [`.agents/adr/0002-ship-as-a-claude-code-plugin.md`](./.agents/adr/0002-ship-as-a-claude-code-plugin.md). + ## Why These Skills Exist I built these skills as a way to fix common failure modes I see with Claude Code, Codex, and other coding agents.