---
category: 19-agentic-mcp-skills-architectures
angle: 19e
title: "Cross-IDE Plugin Packaging: One Repo, Six Surfaces"
subtitle: "SSOT + sync pattern, installer scripts, and marketplace listings for Claude Code, Cursor, Windsurf, Gemini CLI, Codex, and Copilot"
author: research-subagent-19e
date: 2026-04-19
status: complete
primary_reference: /Users/mohamedabdallah/Work/Projects/Humazier
word_count_target: 3000-4500
tags: [packaging, ssot, mirroring, marketplace, installers, ci, claude-code, cursor, windsurf, gemini-cli, codex, copilot]
---

# 19e — Cross-IDE Plugin Packaging

## Executive Summary

The prompt-to-asset product has to live inside six distinct coding-agent surfaces — Claude Code, Cursor, Windsurf, Gemini CLI, OpenAI Codex, and GitHub Copilot — and each surface reads a different file layout, a different frontmatter dialect, and (increasingly) its own marketplace manifest. The naive approach is to hand-author six copies of every skill and every rule; this fails within a release cycle because the copies drift. The right approach, demonstrated concretely by the *humanizer* plugin (see reference tree below), is to treat a small set of canonical files as the Single Source of Truth (SSOT), then generate every platform-specific artifact from them via a deterministic sync script that runs both locally and in CI.

This document specifies that pattern for the prompt-to-asset. Three findings drive the design:

1. **The SSOT is three files, not thirty.** *humanizer* ships five skills and six IDE integrations from exactly three canonical sources: `skills/<name>/SKILL.md` (long-form behavior), `rules/<name>-activate.md` (short always-on activation text), and the Python/JS scripts the skill invokes. Every other location — `.cursor/rules/*.mdc`, `.windsurf/rules/*.md`, `.clinerules/*.md`, `.github/copilot-instructions.md`, `plugins/<name>/skills/`, `humanizer/SKILL.md` at repo root — is regenerated by `scripts/sync-mirrors.sh` and byte-verified by `tests/verify_repo.py`. The script is ~60 lines of bash; the CI workflow that runs it on every push to `main` is ~40 lines of YAML.

2. **Marketplace manifests are cheap; the real ship artifact is the bundle directory.** Claude Code resolves plugins out of `.claude-plugin/plugin.json` with a companion `.claude-plugin/marketplace.json`; Codex auto-discovers `plugins/<name>/.codex-plugin/plugin.json`; Gemini CLI reads `gemini-extension.json` in the repo root and installs via `gemini extension install ./`; Cursor/Windsurf/Cline discover `.cursor/`, `.windsurf/`, `.clinerules/` as conventions, not as marketplace submissions. One repo can satisfy all six because the manifests are tiny JSON files that point at the same `skills/` and `hooks/` directories.

3. **The installer is the product for Claude Code; for everyone else, checkout-is-install.** Claude Code needs user-level settings merged (`SessionStart` / `UserPromptSubmit` hooks in `~/.claude/settings.json`), which demands a real installer: *humanizer*'s `hooks/install.sh` (bash) and `hooks/install.ps1` (PowerShell) are idempotent, back up `settings.json`, and shell out to Node for safe JSON merging. Cursor/Windsurf/Cline/Copilot pick up the in-repo rule files automatically once the repo is open. Gemini CLI and Codex pick up the in-repo manifests automatically once their respective discovery commands run. The installer surface area is therefore: one bash script, one PowerShell script, one sync script, one CI workflow.

The rest of this document walks the reference tree, the sync architecture, the installer design, and the release process, with direct pointers to the humanizer files that implement each piece.

## Reference File Tree

The humanizer repo is the concrete ship example. Every path below is real and currently on disk at `/Users/mohamedabdallah/Work/Projects/Humazier`:

```
humanizer/
├── skills/                          # SSOT for behavior-heavy skills
│   ├── humanizer/SKILL.md           #   main skill (loaded by every IDE)
│   ├── humanizer-commit/SKILL.md    #   commit-message sub-skill
│   ├── humanizer-review/SKILL.md    #   PR-review sub-skill
│   ├── humanizer-help/SKILL.md      #   reference card
│   └── humanize/SKILL.md            #   mirrored from humanizer-humanize/
├── rules/
│   └── humanizer-activate.md        # SSOT for the short always-on activation text
├── humanizer-humanize/              # SSOT for the Python file-rewriter
│   ├── SKILL.md
│   └── scripts/...
├── hooks/                           # SSOT for Claude Code hook scripts + installers
│   ├── humanizer-activate.js
│   ├── humanizer-mode-tracker.js
│   ├── humanizer-statusline.sh
│   ├── humanizer-statusline.ps1
│   ├── install.sh                   #   idempotent bash installer
│   ├── install.ps1                  #   idempotent PowerShell installer
│   ├── uninstall.sh / uninstall.ps1
│   └── package.json
├── commands/                        # Claude Code slash-command manifests (TOML)
│   ├── humanizer.toml
│   ├── humanizer-commit.toml
│   ├── humanizer-review.toml
│   ├── humanizer-help.toml
│   └── humanize.toml
├── .claude-plugin/
│   ├── plugin.json                  # Claude Code plugin manifest (hooks wiring)
│   └── marketplace.json             # Claude Code marketplace listing
├── .agents/plugins/marketplace.json # "Agents" marketplace listing
├── plugins/humanizer/               # Codex plugin bundle (self-contained)
│   ├── .codex-plugin/plugin.json    #   auto-discovered by Codex
│   ├── skills/                      #   mirrored copies of all SKILL.md
│   └── assets/                      #   icons + logos for marketplace UI
├── .cursor/                         # Cursor mirror (rules + skills)
│   ├── rules/humanizer.mdc          #   generated with alwaysApply:true frontmatter
│   └── skills/humanizer/SKILL.md
├── .windsurf/                       # Windsurf mirror
│   ├── rules/humanizer.md           #   generated with always_on:true frontmatter
│   └── skills/humanizer/SKILL.md
├── .clinerules/
│   └── humanizer.md                 # Cline mirror (title-prefixed)
├── .github/
│   ├── copilot-instructions.md      # Copilot mirror (instructions-prefixed)
│   └── workflows/
│       ├── ci.yml                   # pytest + repo integrity + benchmark
│       └── sync.yml                 # SSOT → mirrors auto-propagation
├── gemini-extension.json            # Gemini CLI manifest (lives at repo root)
├── GEMINI.md                        # Gemini context file
├── scripts/
│   └── sync-mirrors.sh              # the whole sync pattern, in ~60 lines
├── tests/
│   ├── test_hooks.py                # hook installer tests
│   ├── verify_repo.py               # every mirror is byte-identical to SSOT
│   └── humanizer-humanize/...
└── benchmarks/run.py                # offline benchmark, CI-gated with --strict
```

For prompt-to-asset, the same tree maps one-to-one with the main skill renamed to `prompt-to-asset` and the sub-skills renamed to match the asset categories (`prompt-to-asset-logo`, `prompt-to-asset-icon`, `prompt-to-asset-favicon`, etc.). The surrounding wiring — `.claude-plugin/`, `hooks/`, `commands/`, `scripts/sync-mirrors.sh`, `.github/workflows/sync.yml` — is essentially unchanged.

## SSOT + Sync Architecture

### Why a single source of truth at all

Every cross-IDE plugin that does not enforce SSOT drifts within a release. Cursor gets a fix that Windsurf doesn't. The Codex bundle ships a SKILL.md that is one commit behind `skills/humanizer/SKILL.md`. A reviewer updates `.github/copilot-instructions.md` directly and nobody notices that `rules/humanizer-activate.md` now disagrees with it. The drift is silent until a user reports that "it works in Cursor but not in Windsurf," at which point you are doing forensics across six copies.

The fix is structural: make it impossible to write to a mirror and have that write survive. Every mirror is regenerated from an SSOT file on every push; any hand-edit to a mirror is overwritten on the next sync. `tests/verify_repo.py` fails CI if any mirror is not byte-identical to what `sync-mirrors.sh` would produce.

### The three SSOT categories

1. **Skills** — long-form behavior instructions. Canonical path: `skills/<name>/SKILL.md`. One file per skill. Frontmatter carries `name`, `description`, and any triggers. This file is loaded directly by Claude Code, Cursor, Windsurf, Cline, and Codex (via their respective skill mechanisms), and is referenced by Gemini CLI via `contextFiles` in `gemini-extension.json`.

2. **Rules** — short always-on activation text. Canonical path: `rules/<name>-activate.md`. No frontmatter — frontmatter is *added per platform* by the sync script because Cursor wants `alwaysApply: true`, Windsurf wants `always_on: true`, Cline wants no frontmatter but a title prefix, and Copilot wants an instructions preamble. Keeping the body un-frontmattered in SSOT lets the sync script compose the right platform envelope around identical content.

3. **Scripts** — any executable the skill invokes. For the prompt-to-asset these will be Python image-generation helpers (rembg wrapper, transparent-logo generator, sharp-cli shim) and Node hook scripts. Canonical path: `<skill-dir>/scripts/` (co-located with the SKILL.md it serves) or `hooks/` for Claude-Code-specific hooks.

Everything else — `plugins/<name>/skills/`, `.cursor/skills/`, `.windsurf/skills/`, `humanizer/` at repo root — is a mirror, never the canonical location.

### The sync script

The entire sync pattern fits in `scripts/sync-mirrors.sh`, ~60 lines of `set -euo pipefail` bash. The humanizer version does four things:

1. **Copy the main SKILL.md to every consumer of it** — `humanizer/SKILL.md` (repo root), `plugins/humanizer/skills/humanizer/SKILL.md` (Codex bundle), `.cursor/skills/humanizer/SKILL.md`, `.windsurf/skills/humanizer/SKILL.md`. Plain `cp`.

2. **Copy sub-skills to the plugin bundle** — so the Codex plugin is self-contained and can be distributed as a single directory without reaching back up the tree.

3. **Copy the Python file-rewriter skill + its scripts** to `plugins/humanizer/skills/humanize/` and `skills/humanize/`. Uses `cp -R humanizer-humanize/scripts/. <dest>/scripts/` so trailing dots copy contents without the parent directory.

4. **Compose per-platform frontmatter around the activation rule body**:

```bash
BODY_FILE=rules/humanizer-activate.md
{
  printf '%s\n' '---'
  printf 'description: ...\n'
  printf 'alwaysApply: true\n'
  printf '%s\n\n' '---'
  cat "$BODY_FILE"
} > .cursor/rules/humanizer.mdc

{
  printf '%s\n' '---'
  printf 'always_on: true\n'
  printf '%s\n\n' '---'
  cat "$BODY_FILE"
} > .windsurf/rules/humanizer.md

{
  printf '# Humanizer Rule (Cline)\n\n'
  cat "$BODY_FILE"
} > .clinerules/humanizer.md

{
  printf '# Copilot Instructions — humanizer\n\n'
  cat "$BODY_FILE"
} > .github/copilot-instructions.md
```

That block is the entire cross-IDE compatibility story. Identical body text, four different envelopes, one authoritative source. For prompt-to-asset, the same pattern applies — the only change is that the body content will be asset-generation guidance ("When generating a transparent logo, ensure the model actually emits RGBA; checker-pattern output is a known failure mode of…") rather than anti-slop rules.

### The CI workflow

`sync.yml` runs `sync-mirrors.sh` on every push to `main` that touches an SSOT file, then auto-commits the mirrored changes back to main as the `github-actions[bot]` user. Key properties:

- **Triggered only by SSOT paths** (`skills/**/SKILL.md`, `rules/*.md`, `humanizer-humanize/**`, `scripts/sync-mirrors.sh`). Mirror paths do *not* trigger — if they did, the bot's sync commit would trigger itself and loop.
- **`permissions: contents: write`** is the minimum needed to push the sync commit back.
- **Idempotent guard**: `if [ -n "$(git status --porcelain)" ]` — no-op when there's nothing to sync.
- **Deterministic** — developers can `bash scripts/sync-mirrors.sh` locally and produce byte-identical output, so PRs that touch mirrors can be auto-fixed without waiting for CI.

### The byte-identity test

`tests/verify_repo.py` closes the loop. It re-runs the sync logic in memory and diffs every mirror against what the sync would produce. If anyone (human or malicious PR) edits a mirror directly without going through the SSOT, CI fails with a clear diff. This is the guarantee that makes the whole pattern safe: you can stop worrying about mirror drift because the test has replaced worrying.

## Installer Design

### Why only Claude Code needs a real installer

Five of the six target surfaces pick up the plugin *automatically* once the repo is cloned or the appropriate discovery command runs:

- **Cursor / Windsurf / Cline** — scan the open workspace for `.cursor/rules/*`, `.windsurf/rules/*`, `.clinerules/*`. Zero install.
- **GitHub Copilot** — reads `.github/copilot-instructions.md` for the active repo. Zero install.
- **Gemini CLI** — `gemini extension install ./` reads `gemini-extension.json`, which points at `GEMINI.md` plus `skills/<name>/SKILL.md` via `contextFiles`. One command, no config merge needed.
- **Codex** — auto-discovers `plugins/<name>/.codex-plugin/plugin.json` when the repo is opened.

Only **Claude Code** needs user-scope wiring for global (cross-project) hooks: `SessionStart` and `UserPromptSubmit` hooks have to be registered in `~/.claude/settings.json` so they fire every session globally, not just when a specific repo is open. That registration is the entire reason `hooks/install.sh` and `hooks/install.ps1` exist.

> **Updated 2026-04-21:** Gemini CLI v0.26.0+ now supports extension-bundled hooks via `hooks/hooks.json` inside the extension directory. These are discovered automatically when the extension is installed — no user-level settings merge required. However, Gemini CLI shows a security consent warning at install time when an extension contains hooks. Wire the `prompt-to-asset-activate` hook into `hooks/hooks.json` so Gemini CLI gets SessionStart enforcement alongside Claude Code and Codex.

(A companion *project-level* install path is also viable via the Claude Code marketplace — see Release Process — which is zero-config but requires the user to invoke `claude plugin install`. The bash/PowerShell installer is the escape hatch for users who aren't using the marketplace yet.)

### Idempotent bash installer

`hooks/install.sh` obeys five invariants that are worth stating explicitly because they are the hard part of writing a good installer:

1. **Detect "already installed" and exit 0** unless `--force`. The humanizer script checks three conditions: all hook files present, hooks wired in `settings.json` (parsed via Node, not regex), statusline configured. If all three hold, it prints "Nothing to do." and exits cleanly. Users can safely re-run the installer to upgrade.

2. **Back up `settings.json` before modification**. A plain `cp "$SETTINGS" "$SETTINGS.bak"` the instant before any write. If the merge step fails partway, the user has a known-good file one rename away.

3. **Merge JSON via Node, never via `sed`**. The installer shells out to `node -e '...'` with a small inline script that reads settings.json, inserts the hook entries if they aren't present, and writes the result back with `JSON.stringify(..., 2)`. This is the single most important safety property: a regex-based JSON merger will at some point corrupt a user's settings with a nested bracket they didn't anticipate. `JSON.parse` fails loudly; regex corruption fails silently.

4. **Never clobber existing hooks or statusline**. The merge logic checks whether `settings.hooks.SessionStart` already contains an entry whose command includes `humanizer` — if yes, skip; if no, append. The statusline logic is stricter: if any statusline already exists and it isn't ours, print a NOTE and do nothing, deferring to the user to integrate manually.

5. **Work identically from a git checkout or a curl pipe**. The script checks `BASH_SOURCE[0]` to determine if it's running from a cloned repo (in which case it copies files locally) or from a curl-to-bash invocation (in which case it fetches each hook file from the GitHub raw URL). One installer, two distribution channels.

Detecting OS/shell gotchas — MSYS/Cygwin/MinGW banners, missing `node`, symlink warnings — rounds out the script. The humanizer version is 186 lines and readable end-to-end.

### The PowerShell twin

`hooks/install.ps1` mirrors `install.sh` structurally for Windows PowerShell 5.1+, with two concessions:

- **`-Force` instead of `--force`** — PowerShell convention.
- **Statusline command uses `powershell -ExecutionPolicy Bypass -File`** — because `humanizer-statusline.ps1` can't be marked executable the way `humanizer-statusline.sh` can via `chmod +x`.

The `settings.json` merge still shells out to Node (PowerShell-native JSON handling exists via `ConvertFrom-Json` but doesn't preserve key order and is finicky around empty objects). Sharing the Node script between the two installers keeps the merge semantics byte-identical across platforms.

### Why Node for the JSON merge

Because `settings.json` is user-owned territory. Every other file in the install target is something the installer created and owns. `settings.json` may contain dozens of unrelated hooks, custom statuslines, workspace trust settings, keybindings. The merge has to be surgical: touch only the keys we add, preserve everything else byte-for-byte, round-trip cleanly on re-install. A real JSON parser is the only sane way to do that, and Node is the one dependency we can reasonably require because Claude Code itself ships with a Node runtime dependency on most platforms.

### Uninstall

`hooks/uninstall.sh` and `hooks/uninstall.ps1` reverse each step: remove the hook files, re-parse `settings.json`, filter out only the entries whose commands include `humanizer`, drop the managed statusline if it matches our path, and write back. Leave `.bak` in place for one release cycle so an accidental uninstall is recoverable. The uninstall script is about half the size of the install script because it doesn't need the distribution logic.

## Release Process

### Semantic versioning

Bump in three places on every release: `.claude-plugin/plugin.json#version`, `plugins/<name>/.codex-plugin/plugin.json#version`, `gemini-extension.json#version`. A single `scripts/bump-version.sh VERSION` shell script writes all three. The `.claude-plugin/marketplace.json` and `.agents/plugins/marketplace.json` also carry versions — keep them aligned.

Version policy for a prompt-to-asset-shaped plugin:

- **Patch (`0.1.x`)** — SKILL.md wording tweaks, prompt-template edits, fixture additions. Always safe. Users on any mirror pick it up on next session.
- **Minor (`0.x.0`)** — new sub-skill (new asset category), new slash command, new hook event. Backwards-compatible.
- **Major (`x.0.0`)** — installer behavior change, settings.json schema change, breaking rename of a skill. Requires users to re-run `install.sh --force` and refresh the Gemini extension.

### Release artifacts

Four distribution channels, in order of maturity:

1. **GitHub Releases** (day 1). Tag `vX.Y.Z`, attach a release note, let GitHub auto-generate the source tarball. This is the universal artifact — every other channel sources from it.

2. **Claude Code marketplace** (day 1). Submit `.claude-plugin/marketplace.json` to Anthropic's plugin registry, or run your own marketplace by pointing users at your repo's raw marketplace URL. `claude plugin install <marketplace-url>` pulls the plugin without the user needing to clone or run `install.sh`.

3. **npm scoped package** (optional). Publish the hook scripts and installer as `@your-scope/<name>` so `npx @your-scope/<name>-install` becomes the install command. Useful if you want a versioned installer URL, less useful if most users are using the marketplace.

4. **Homebrew tap** (optional, for CLI-heavy users). Create `your-org/homebrew-<name>` with a single `<name>.rb` formula that pins the release tag and runs `bash hooks/install.sh` post-install. `brew install your-org/<name>/<name>`.

For the prompt-to-asset specifically, channels 1 and 2 are sufficient on day one. Channel 3 is worth it if the Python helper scripts (rembg wrapper, image post-processing) get called as standalone CLI tools — at that point an `npm`- or `pip`-installable wrapper makes sense. Channel 4 is a nice-to-have.

### CI gates on release

The `ci.yml` workflow must pass before any tag is cut:

- **Tests** (`python -m pytest tests/ -v`) — installer behavior, frontmatter generation, mirror integrity.
- **Repo integrity** (`python3 tests/verify_repo.py`) — every mirror byte-identical to SSOT; all manifests parse as valid JSON; all shell / PowerShell / JS scripts lint clean.
- **Offline benchmark** (`python3 benchmarks/run.py --strict`) — for the prompt-to-asset, this becomes an asset-quality benchmark: a corpus of prompts, each with an expected asset type and pass/fail criteria (e.g. "logo prompt produces a result that rembg can extract cleanly"). `--strict` fails CI on any regression.

Tag only after green. Cutting a release from a failing build is the single most common way good SSOT pipelines still ship broken plugins.

### Marketplace listings

Three marketplace files coexist in the repo, each targeting a different ecosystem:

- **`.claude-plugin/marketplace.json`** — Anthropic's schema. Points `source: "./"` at the repo root so the plugin uses the current tree. Carries display name, description, version, author, tags.
- **`.agents/plugins/marketplace.json`** — the "agents" marketplace convention (used by several third-party IDE-agent tools). Points `source: "./plugins/<name>"` at the Codex-style bundle so the plugin is self-contained.
- **`gemini-extension.json`** — Gemini CLI's own manifest, discovered at the repo root via `gemini extension install ./`. Lists `contextFiles: ["GEMINI.md", "skills/<name>/SKILL.md", "rules/<name>-activate.md"]` so Gemini loads all three into context on startup.

No marketplace submission is required for Cursor, Windsurf, Cline, or Copilot — they treat in-repo convention files as authoritative and don't have a central registry to submit to (as of the April 2026 reference state). This may change; the pattern absorbs the change gracefully because adding a seventh marketplace file is a one-line addition to `sync-mirrors.sh`.

## Checklist for prompt-to-asset

Port the humanizer pattern by renaming and subsetting. Concrete tasks:

1. Create `skills/prompt-to-asset/SKILL.md` as the SSOT for the main skill.
2. Create one `skills/prompt-to-asset-<category>/SKILL.md` per asset category (logo, icon, favicon, illustration, og-image, splash).
3. Create `rules/prompt-to-asset-activate.md` with the always-on activation text (two to four sentences telling the agent to route asset requests through the skill).
4. Create `hooks/install.sh` and `hooks/install.ps1`. Start from the humanizer scripts verbatim; rename every occurrence of `humanizer` to `prompt-to-asset`. The JSON merge logic needs no change.
4a. Create `hooks/hooks.json` for Gemini CLI extension hooks (v0.26.0+). Define `SessionStart` and `BeforeTool` hooks pointing at the same activate script. This file is auto-discovered when the extension is installed — no separate install step required, but users see a consent warning.
5. Create `.claude-plugin/plugin.json` and `.claude-plugin/marketplace.json`.
6. Create `plugins/prompt-to-asset/.codex-plugin/plugin.json`.
7. Create `gemini-extension.json` + `GEMINI.md` at repo root.
8. Write `scripts/sync-mirrors.sh` modeled on the humanizer version.
9. Wire `.github/workflows/sync.yml` and `.github/workflows/ci.yml`.
10. Write `tests/verify_repo.py` for byte-identity checks.
11. Add an asset-specific `benchmarks/run.py --strict` gate. This is the piece that doesn't exist in humanizer — the prompt-to-asset needs a benchmark harness that actually *generates* assets and scores them against pass/fail criteria (transparency check, no-text-corruption check, size-spec compliance).

Once these are in place, adding a seventh IDE target (say, JetBrains AI Assistant or a future Zed plugin) is exactly one block in `sync-mirrors.sh` plus one entry in a new `.jetbrains/` or `.zed/` directory.

## References

**Primary ship example (reference repo on disk):**

- `/Users/mohamedabdallah/Work/Projects/Humazier/README.md` — architecture + install surface
- `/Users/mohamedabdallah/Work/Projects/Humazier/scripts/sync-mirrors.sh` — the full sync pattern
- `/Users/mohamedabdallah/Work/Projects/Humazier/.github/workflows/sync.yml` — CI auto-propagation
- `/Users/mohamedabdallah/Work/Projects/Humazier/.github/workflows/ci.yml` — gates (tests + integrity + benchmark)
- `/Users/mohamedabdallah/Work/Projects/Humazier/hooks/install.sh` — idempotent bash installer
- `/Users/mohamedabdallah/Work/Projects/Humazier/hooks/install.ps1` — idempotent PowerShell installer
- `/Users/mohamedabdallah/Work/Projects/Humazier/.claude-plugin/plugin.json` — Claude Code plugin manifest
- `/Users/mohamedabdallah/Work/Projects/Humazier/.claude-plugin/marketplace.json` — Claude Code marketplace listing
- `/Users/mohamedabdallah/Work/Projects/Humazier/plugins/humanizer/.codex-plugin/plugin.json` — Codex plugin manifest
- `/Users/mohamedabdallah/Work/Projects/Humazier/gemini-extension.json` — Gemini CLI manifest
- `/Users/mohamedabdallah/Work/Projects/Humazier/.agents/plugins/marketplace.json` — Agents-marketplace listing

**Platform documentation:**

- Claude Code plugins & marketplace: https://docs.claude.com/en/docs/claude-code/plugins
- Claude Code hooks reference: https://docs.claude.com/en/docs/claude-code/hooks
- Claude Code settings.json schema: https://docs.claude.com/en/docs/claude-code/settings
- Cursor rules (`.cursor/rules/*.mdc`): https://docs.cursor.com/context/rules
- Cursor extension / skill publishing: https://docs.cursor.com/extensions
- Windsurf rules (`.windsurf/rules/*.md`): https://docs.windsurf.com/windsurf/cascade/memories#rules
- Cline rules (`.clinerules/*.md`): https://docs.cline.bot/features/cline-rules
- Gemini CLI extensions (`gemini extension install`): https://github.com/google-gemini/gemini-cli/blob/main/docs/extensions.md
- GitHub Copilot custom instructions (`.github/copilot-instructions.md`): https://docs.github.com/en/copilot/customizing-copilot/adding-custom-instructions-for-github-copilot
- OpenAI Codex plugins (`.codex-plugin/plugin.json` auto-discovery): https://developers.openai.com/codex/cli (plugin section)

**Related patterns in the wild:**

- `anthropics/claude-code-plugins` — Anthropic-curated plugin marketplace (GitHub).
- `sanity-io/sanity-plugin-kit` — pattern for generators that emit multi-framework plugin variants from one source (React, Vue, etc.). Not coding-agent-specific but the SSOT + codegen pattern is the same.
- `conventional-changelog/commitlint` — example of a single repo shipping simultaneously to npm, Homebrew, and GitHub Releases with per-channel manifests generated from one `package.json`.

**Within this research corpus:**

- See `19a`, `19b`, `19c`, `19d` (sibling angles in this category) for complementary views on MCP tool design, Claude Skills internals, Codex custom tools, and Gemini function calling. This document assumes those surfaces exist and focuses only on how to package and ship the skills that use them.
