Claude Skill

claude-skill-plugin-packaging

Package Claude Code skills as a plugin plus marketplace and install them into other repos — globally, pinned per project via committed settings, or as a skills-dir plugin. Use when sharing skills across repos, wiring an existing skill plugin into a project, choosing flat project

LLM Mart · 0 points · 0 views 0 listing impressions 0 install-command copies
Virus-scanned Reviewed automatically before listing.

Full trust report

Download wei18-apple-dev-skills-collaboration-skills_skills_claude-skill-plugin-packaging-7ea7e61.zip · 6 KB
Part of wei18/apple-dev-skills — 37 skills

Install

skills CLI npx skills add https://github.com/wei18/apple-dev-skills/tree/main/collaboration-skills/skills/claude-skill-plugin-packaging
Claude Code claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install wei18-apple-dev-skills@llmmart
Git git clone https://github.com/wei18/apple-dev-skills.git

The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole wei18/apple-dev-skills collection as a plugin from our marketplace. Git is the plain clone.

Skill manifest

Claude Code Skill Plugin Packaging

Native mechanism

Plugins and plugin marketplaces are Claude Code's own distribution mechanism — a marketplace repo with .claude-plugin/marketplace.json gives "centralized discovery, version tracking, automatic updates". What the official docs don't spell out in one place is the depth-1 discovery trap and the install-model tradeoffs below — that's what this skill adds.

  • Official sources: when verifying or updating a factual or version-sensitive claim, read references/official-docs.md.

When to invoke

  • You have skills in one repo and want them reusable across other repos/projects.
  • Wiring an existing skill plugin (e.g. apple-dev-skills) into a new project.
  • Deciding flat project skills vs a plugin.
  • A submodule/nested folder of skills "isn't being discovered" and you don't know why.
  • Aggregating other people's skill repos without copy-pasting.
  • User asks "how do I share/install skills", "why is my .claude/skills/<lib>/... not found".

The one rule that explains everything: plain-skill discovery is depth-1 — unless the nested tree is itself a plugin

Claude Code discovers plain project skills only at depth 1: .claude/skills/<skill>/SKILL.md. It does not recurse into subdirectories.

Consequences (each has burned someone):

  • A git submodule of skills at .claude/skills/<lib>/ puts SKILL.md at .claude/skills/<lib>/skills/<skill>/SKILL.md (depth ≥ 2) → NOT discovered as a plain skill.
  • A bare folder of skills nested one level down → NOT discovered as a plain skill.
  • An in-repo submodule of a plugin you also installed via a marketplace is vestigial for that installed copy — the marketplace-installed copy is what loads, the submodule does nothing for discovery.

But a nested skill tree is still found if its root is itself a plugin (carries .claude-plugin/plugin.json) — it self-loads on the next session as <lib>@skills-dir, with no marketplace and no install step (project scope: after the workspace-trust dialog; must launch from the session's primary working directory, no walk-up to a parent project). This is claude plugin init's documented default, not an experimental feature — see Model D below. It only fails to help when the repo you're vendoring is a marketplace (root has marketplace.json but no plugin.json) rather than a single plugin — which is this catalog's own shape, so a bare submodule of this repo still needs Model B1 or B2.

Packaging: make your skills a plugin + marketplace

A repo becomes a Claude Code plugin with a manifest, and a marketplace (catalog) with a second manifest. One repo can be both (single-repo model):

your-skills-repo/
├── .claude-plugin/
│   ├── plugin.json        # makes it a plugin; "name" becomes the namespace
│   └── marketplace.json   # makes it a marketplace; lists plugins
└── skills/
    └── <skill>/SKILL.md   # one dir per skill

plugin.json (the name is the plugin namespace prefix — skills surface as plugin-name:<skill>; this is independent of the marketplace name):

{ "name": "your-skills", "version": "0.1.0", "description": "…", "license": "MIT" }

The marketplace name is the catalog identifier used in /plugin install plugin-name@marketplace-name. These are two distinct names that happen to be the same string in the single-repo model — that identity is a coincidence, not a requirement. A real-world example where they differ: "code-formatter@company-tools" (plugin name = code-formatter, marketplace name = company-tools).

marketplace.json — lists this plugin (and can list MANY plugins from other sources):

{
  "name": "your-skills",
  "owner": { "name": "you" },
  "plugins": [
    { "name": "your-skills", "source": "./", "description": "…", "version": "0.1.0" }
  ]
}

"source": "./" = the plugin is at the marketplace repo root.

Installing (consuming) into a project — pick a model

Model Pinned? Per-repo commit? Install step? Use when
A. Global marketplace No (latest) No /plugin install once, globally Personal use across many repos
B1. Marketplace github+ref Yes (git ref) Yes (settings.json) None for this plugin; external-source plugins still need claude plugin install per collaborator (≥v2.1.195) Team default — no submodule needed
B2. Vendored submodule + directory source Yes (commit SHA) Yes None SHA-level pin, or fully offline vendoring
D. Submodule of a single-plugin repo Yes (commit SHA) No (self-loads) None, after trust dialog The repo you vendor already ships plugin.json at its root
C. npm (flat, non-plugin) Depends on registry No npx skills add One skill set, no aggregation needed

A. Global marketplace (simplest, latest)

/plugin marketplace add owner/your-skills-repo
/plugin install your-skills@your-skills

Loads globally (every project), namespaced. Not pinned per repo.

B1. Marketplace ref pin, no submodule (recommended default for a team)

Commit to the project's .claude/settings.json:

{
  "extraKnownMarketplaces": {
    "your-skills": {
      "source": { "source": "github", "repo": "owner/your-skills-repo", "ref": "v0.1.0" }
    }
  },
  "enabledPlugins": { "your-skills@your-skills": true }
}

No submodule, no vendoring — Claude Code resolves the pinned ref on trust. Caveat (since v2.1.195): auto-install-on-trust applies to plugins declared via a relative/ directory source; a plugin whose source is external (github, npm, url, git-subdir) — like the aggregated github / git-subdir entries in §Aggregating — is enabled in settings but each collaborator still has to run the claude plugin install command Claude Code prints on first load. The marketplace source (extraKnownMarketplaces / marketplace add) — where this marketplace.json itself is fetched from — takes ref but not sha; for an exact-commit pin use B2.

B2. Vendored submodule + project-scope committed settings (SHA-level pin, offline-capable)

Use this when a repo must depend on an exact commit SHA, or must work without network access to the plugin's origin — B1 only pins a ref, not a sha.

  1. Vendor + pin:
    git submodule add https://github.com/owner/your-skills-repo.git .claude/skills/your-skills
    cd .claude/skills/your-skills && git checkout v0.1.0 && cd -
    
  2. Commit this to the project's .claude/settings.json (the shared, committed file — not .claude/settings.local.json, which is personal/gitignored):
    {
      "extraKnownMarketplaces": {
        "your-skills": {
          "source": { "source": "directory", "path": "./.claude/skills/your-skills" }
        }
      },
      "enabledPlugins": { "<plugin-name>@<marketplace-name>": true }
    }
    
    Replace <plugin-name> with the name from the plugin's plugin.json and <marketplace-name> with the name from the marketplace's marketplace.json. In the single-repo model these happen to be the same string (e.g. "your-skills@your-skills": true), but they are conceptually distinct — the plugin namespace and the catalog identifier.
    • The marketplace source for a local dir is an object {"source":"directory","path":"./relative"} — a relative path. Relative plugin sources resolve for marketplaces added from a git source or a local directory; they fail only when the marketplace was added by a direct URL to marketplace.json. A directory source path resolves against the containing repo's main checkout — including from inside a worktree of it — regardless of whether the target itself is a git repo. The docs label directory sources "for development only"; prefer B1 for a team default and reserve B2 for the SHA-pin/offline case.
  3. On git clone --recurse-submodules + workspace-trust, Claude Code auto-registers the marketplace and enables the plugin. Skills load as your-skills:<skill>. No /plugin install step for this relative/directory-sourced plugin — but see B1's v2.1.195 caveat if this marketplace also aggregates externally-sourced plugins.

Why both pieces: the submodule pins the exact version (a commit SHA); the committed settings.json is what actually makes Claude Code load it. Either alone is insufficient (submodule-only = not discovered; settings-only = nothing to point at).

D. Submodule of a single-plugin repo (self-loading, no settings.json needed)

If the repo you're vendoring has .claude-plugin/plugin.json at its root (not just a marketplace.json), a plain submodule under .claude/skills/ or ~/.claude/skills/ is enough:

git submodule add https://github.com/owner/single-plugin-repo.git .claude/skills/their-plugin
cd .claude/skills/their-plugin && git checkout v0.1.0 && cd -

On the next session (after the project-scope trust dialog), it self-loads as their-plugin@skills-dir — no marketplace, no install step, no settings.json edit. Caveats: the same primary-working-directory / trust-dialog rule stated above applies (exact version gate: references/official-docs.md); and because a project-scope skills-dir plugin's content comes from the repository, its code-running components are gated further — MCP servers it declares go through the same per-server approval as a project .mcp.json, LSP servers start only after you trust the workspace, and background monitors do not load (personal-scope ~/.claude/skills/ plugins have none of these restrictions). This repo's own root has only marketplace.json, not plugin.json, so a bare submodule of this repo does not self-load this way — use B1 or B2.

C. npm (flat, non-plugin install)

npx skills add installs skills flatly — see README §C and scripts/install-flat.sh. It reads marketplace.json / plugin.json, but only follows locally-declared skill paths — it does not fetch the aggregated externals' remote github / git-subdir sources (below), so those are skipped. Use it for a single skill set with no aggregation needs, not for this catalog's full plugin set.

Aggregating other skill repos (don't reinvent)

A marketplace is a catalog of plugins from many sources — that is the native aggregation mechanism, no submodule required. Add more entries to plugins[], each with its own source:

"plugins": [
  { "name": "your-skills",        "source": "./" },
  { "name": "someones-testing",   "source": { "source": "github", "repo": "them/testing-skills" } },
  { "name": "vendored-thing",     "source": { "source": "git-subdir", "url": "https://…", "path": "tools/plugin" } }
]

Accepted plugin source types (relative path, github, url, git-subdir, npm, archive, command) and the exact fields and Claude Code version each requires drift with new releases — read references/official-docs.md rather than trusting a hardcoded list. Use a submodule only when you need to vendor + pin another repo's content into yours (Model B2 or D above).

Gotchas (verified)

  • Bare submodule of a multi-plugin repo (root has only marketplace.json) ≠ discovered. Pair it with the extraKnownMarketplaces + enabledPlugins settings (Model B2) — or, if the submodule's own root has plugin.json instead, it self-loads on its own (Model D).
  • Marketplace state is per-user (~/.claude/plugins/known_marketplaces.json), but the committed project .claude/settings.json declaration is what makes it reproducible for everyone on trust. Marketplace names are checked against a reserved list (claude-code-marketplace, anthropic-marketplace, agent-skills, …) — adding a new marketplace under a reserved name is rejected outright, and Claude Code re-checks the name on every load, so an existing marketplace whose name later becomes reserved stops loading too, erroring with "is registered from an untrusted source" (errors reference). Fix: remove it and re-add from the official source, or rename it and have users re-add from yours.
  • Token cost: every enabled skill's description is always-on context — for the exact mechanism see the listing-budget reference doc under skill-authoring-patterns. /doctor and /skill-doctor show the actual per-session cost. skillOverrides: "name-only" only demotes personal/project skills — it does not apply to plugin skills ("Plugin skills are not affected by skillOverrides. Manage those through /plugin instead."); for a plugin the only levers are disabling it via /plugin, or raising the consumer's skillListingBudgetFraction.
  • Relative marketplace paths: see B2 step 2 above for the exact resolution rule and its one exception (direct-URL marketplaces) — Create and distribute a plugin marketplace.
  • A skill/plugin name containing "claude" loads fine in Claude Code — this skill's own name is proof, and claude-hud/claude-mem ship the same way — but is rejected by the platform Agent Skills spec's reserved-word rule. This only matters if the skill is ever uploaded to claude.ai, the Skills API, or packaged with package_skill.py; the Claude Code plugin path this skill describes is unaffected.

Verification

  • git commit -a skips new files — plugin.json/marketplace.json are new, so -a silently omits them. Use explicit git add and verify with git show --stat --summary (plain --stat doesn't print the create mode lines new files need).
  • /reload-plugins then check the skills list shows your-skills:<skill> entries.
  • claude plugin details your-skills@your-skills lists the bundled skills, agents, and token cost — not scope. Scope (user / project) comes from claude plugin list; a project-scope plugin only resolves from inside that project, so running either command from elsewhere returns Plugin "…" not found.
  • For model B2: git ls-files .claude/settings.json (it's committed) and the submodule gitlink point at the intended version.

Related skills

  • github-contribution-workflow — routes plugin distribution/installation questions here; that skill owns PR/issue mechanics, this one owns packaging and discovery.
  • skill-authoring-patterns — routes distribution/packaging questions here once a skill is authored; that skill owns authoring conventions, this one owns how the finished skill gets shared.
Files (apple-dev-skills)
  • references
    • official-docs.md 2.3 KB
      Official pages backing this skill's claims; read when verifying or updating a factual or version-sensitive claim.
      
      | Page | URL | Backs |
      |---|---|---|
      | Create plugins | https://code.claude.com/docs/en/plugins | Native mechanism section; Packaging (`plugin.json` name = namespace) |
      | Create and distribute a plugin marketplace | https://code.claude.com/docs/en/plugin-marketplaces#plugin-sources | Aggregating: accepted plugin source schema and version gates (`pluginRoot` >=2.1.239, `archive` >=2.1.224, `command` >=2.1.229); marketplace source takes `ref` but not `sha` |
      | Create and distribute a plugin marketplace | https://code.claude.com/docs/en/plugin-marketplaces#relative-paths | Gotcha: relative paths fail only for direct-URL marketplaces; "external" means any plugin source other than a relative path |
      | Discover and install prebuilt plugins through marketplaces | https://code.claude.com/docs/en/discover-plugins#configure-team-marketplaces | "As of Claude Code v2.1.195, adding the marketplace doesn't install plugins that come from an external source..." |
      | All settings | https://code.claude.com/docs/en/settings-reference#extraknownmarketplaces | `extraKnownMarketplaces` JSON shape; "`directory` ... for development only" |
      | Plugins reference | https://code.claude.com/docs/en/plugins-reference#skills-directory-plugins | Depth-1 exception; Model D (`<name>@skills-dir`, trust, primary working directory, MCP/LSP/monitor limits); verification via `claude plugin details` / `claude plugin list` |
      | Error reference | https://code.claude.com/docs/en/errors#marketplace-is-registered-from-an-untrusted-source | Gotcha on reserved marketplace names: an already-registered marketplace reports an error, it doesn't stop silently |
      | Extend Claude with skills | https://code.claude.com/docs/en/skills#skill-descriptions-are-cut-short | Gotcha "Token cost": listing budget; "Plugin skills are not affected by `skillOverrides`" |
      | vercel-labs/skills README (upstream of `npx skills`) | https://github.com/vercel-labs/skills#plugin-manifest-discovery | `npx skills` does read `marketplace.json` / `plugin.json` but only follows declared local skill paths, so externals are skipped |
      | Agent Skills | https://platform.claude.com/docs/en/agents-and-tools/agent-skills/overview | Gotcha "name containing claude": reserved words "anthropic", "claude" on the platform upload path |
      
  • SKILL.md 15.1 KB
    ---
    name: claude-skill-plugin-packaging
    description: Package Claude Code skills as a plugin plus marketplace and install them into other repos — globally, pinned per project via committed settings, or as a skills-dir plugin. Use when sharing skills across repos, wiring an existing skill plugin into a project, choosing flat project skills versus a plugin, aggregating other people's skill repos by reference, or when a submodule or nested folder of skills is not being discovered. Does not cover PR/issue mechanics (github-contribution-workflow) or how to write the skill itself (skill-authoring-patterns).
    ---
    
    # Claude Code Skill Plugin Packaging
    
    ## Native mechanism
    
    [Plugins](https://code.claude.com/docs/en/plugins) and [plugin marketplaces](https://code.claude.com/docs/en/plugin-marketplaces) are Claude Code's own distribution mechanism — a marketplace repo with `.claude-plugin/marketplace.json` gives "centralized discovery, version tracking, automatic updates". What the official docs don't spell out in one place is the depth-1 discovery trap and the install-model tradeoffs below — that's what this skill adds.
    
    - Official sources: when verifying or updating a factual or version-sensitive claim, read `references/official-docs.md`.
    
    ## When to invoke
    
    - You have skills in one repo and want them reusable across other repos/projects.
    - Wiring an existing skill plugin (e.g. `apple-dev-skills`) into a new project.
    - Deciding **flat project skills** vs a **plugin**.
    - A submodule/nested folder of skills "isn't being discovered" and you don't know why.
    - Aggregating *other people's* skill repos without copy-pasting.
    - User asks "how do I share/install skills", "why is my `.claude/skills/<lib>/...` not found".
    
    ## The one rule that explains everything: plain-skill discovery is depth-1 — unless the nested tree is itself a plugin
    
    Claude Code discovers **plain project skills only at depth 1**:
    `.claude/skills/<skill>/SKILL.md`. It does **not** recurse into subdirectories.
    
    Consequences (each has burned someone):
    - A **git submodule** of skills at `.claude/skills/<lib>/` puts SKILL.md at
      `.claude/skills/<lib>/skills/<skill>/SKILL.md` (depth ≥ 2) → **NOT discovered as a
      plain skill**.
    - A bare folder of skills nested one level down → **NOT discovered as a plain skill**.
    - An in-repo submodule of a plugin you *also* installed via a marketplace is
      **vestigial for that installed copy** — the marketplace-installed copy is what loads,
      the submodule does nothing for discovery.
    
    **But** a nested skill *tree* is still found if its root is itself a plugin (carries
    `.claude-plugin/plugin.json`) — it self-loads on the next session as `<lib>@skills-dir`,
    with no marketplace and no install step (project scope: after the workspace-trust
    dialog; must launch from the session's primary working directory, no walk-up to a
    parent project). This is `claude plugin init`'s documented default, not an
    experimental feature — see Model D below. It only fails to help when the repo you're
    vendoring is a *marketplace* (root has `marketplace.json` but no `plugin.json`) rather
    than a single plugin — which is this catalog's own shape, so a bare submodule of
    *this* repo still needs Model B1 or B2.
    
    ## Packaging: make your skills a plugin + marketplace
    
    A repo becomes a Claude Code **plugin** with a manifest, and a **marketplace**
    (catalog) with a second manifest. One repo can be both (single-repo model):
    
    ```
    your-skills-repo/
    ├── .claude-plugin/
    │   ├── plugin.json        # makes it a plugin; "name" becomes the namespace
    │   └── marketplace.json   # makes it a marketplace; lists plugins
    └── skills/
        └── <skill>/SKILL.md   # one dir per skill
    ```
    
    `plugin.json` (the `name` is the **plugin** namespace prefix — skills surface as `plugin-name:<skill>`; this is independent of the marketplace name):
    ```json
    { "name": "your-skills", "version": "0.1.0", "description": "…", "license": "MIT" }
    ```
    
    The **marketplace** `name` is the catalog identifier used in `/plugin install plugin-name@marketplace-name`. These are two distinct names that happen to be the same string in the single-repo model — that identity is a coincidence, not a requirement. A real-world example where they differ: `"code-formatter@company-tools"` (plugin name = `code-formatter`, marketplace name = `company-tools`).
    
    `marketplace.json` — lists this plugin (and can list MANY plugins from other sources):
    ```json
    {
      "name": "your-skills",
      "owner": { "name": "you" },
      "plugins": [
        { "name": "your-skills", "source": "./", "description": "…", "version": "0.1.0" }
      ]
    }
    ```
    `"source": "./"` = the plugin is at the marketplace repo root.
    
    ## Installing (consuming) into a project — pick a model
    
    | Model | Pinned? | Per-repo commit? | Install step? | Use when |
    |---|---|---|---|---|
    | A. Global marketplace | No (latest) | No | `/plugin install` once, globally | Personal use across many repos |
    | B1. Marketplace `github`+`ref` | Yes (git ref) | Yes (`settings.json`) | None for this plugin; **external-source plugins still need `claude plugin install` per collaborator (≥v2.1.195)** | Team default — no submodule needed |
    | B2. Vendored submodule + `directory` source | Yes (commit SHA) | Yes | None | SHA-level pin, or fully offline vendoring |
    | D. Submodule of a single-plugin repo | Yes (commit SHA) | No (self-loads) | None, after trust dialog | The repo you vendor already ships `plugin.json` at its root |
    | C. npm (flat, non-plugin) | Depends on registry | No | `npx skills add` | One skill set, no aggregation needed |
    
    ### A. Global marketplace (simplest, latest)
    ```
    /plugin marketplace add owner/your-skills-repo
    /plugin install your-skills@your-skills
    ```
    Loads globally (every project), namespaced. Not pinned per repo.
    
    ### B1. Marketplace `ref` pin, no submodule (recommended default for a team)
    
    Commit to the project's `.claude/settings.json`:
    ```json
    {
      "extraKnownMarketplaces": {
        "your-skills": {
          "source": { "source": "github", "repo": "owner/your-skills-repo", "ref": "v0.1.0" }
        }
      },
      "enabledPlugins": { "your-skills@your-skills": true }
    }
    ```
    No submodule, no vendoring — Claude Code resolves the pinned `ref` on trust. **Caveat
    (since v2.1.195)**: auto-install-on-trust applies to plugins declared via a relative/
    `directory` source; a plugin whose source is *external* (`github`, `npm`, `url`,
    `git-subdir`) — like the aggregated github / git-subdir entries in §Aggregating —
    is *enabled* in settings but each collaborator still has
    to run the `claude plugin install` command Claude Code prints on first load. The
    **marketplace source** (`extraKnownMarketplaces` / `marketplace add`) — where this
    `marketplace.json` itself is fetched from — takes `ref` but not `sha`; for an
    exact-commit pin use B2.
    
    ### B2. Vendored submodule + project-scope committed settings (SHA-level pin, offline-capable)
    
    Use this when a repo must depend on an exact **commit SHA**, or must work without
    network access to the plugin's origin — B1 only pins a `ref`, not a `sha`.
    
    1. Vendor + pin:
       ```
       git submodule add https://github.com/owner/your-skills-repo.git .claude/skills/your-skills
       cd .claude/skills/your-skills && git checkout v0.1.0 && cd -
       ```
    2. Commit this to the project's `.claude/settings.json` (the **shared, committed**
       file — not `.claude/settings.local.json`, which is personal/gitignored):
       ```json
       {
         "extraKnownMarketplaces": {
           "your-skills": {
             "source": { "source": "directory", "path": "./.claude/skills/your-skills" }
           }
         },
         "enabledPlugins": { "<plugin-name>@<marketplace-name>": true }
       }
       ```
       Replace `<plugin-name>` with the `name` from the plugin's `plugin.json` and `<marketplace-name>` with the `name` from the marketplace's `marketplace.json`. In the single-repo model these happen to be the same string (e.g. `"your-skills@your-skills": true`), but they are conceptually distinct — the plugin namespace and the catalog identifier.
       - The marketplace `source` for a local dir is an **object** `{"source":"directory","path":"./relative"}` — a **relative** path. Relative plugin sources resolve for marketplaces added from a git source *or* a local directory; they fail only when the marketplace was added by a direct URL to `marketplace.json`. A `directory` source path resolves against the *containing* repo's main checkout — including from inside a worktree of it — regardless of whether the target itself is a git repo. The docs label `directory` sources "for development only"; prefer B1 for a team default and reserve B2 for the SHA-pin/offline case.
    3. On `git clone --recurse-submodules` + workspace-trust, Claude Code
       auto-registers the marketplace and enables the plugin. Skills load as
       `your-skills:<skill>`. **No `/plugin install` step** for this relative/`directory`-sourced
       plugin — but see B1's v2.1.195 caveat if this marketplace also aggregates externally-sourced
       plugins.
    
    Why both pieces: the **submodule** pins the exact version (a commit SHA); the
    **committed settings.json** is what actually makes Claude Code load it. Either alone
    is insufficient (submodule-only = not discovered; settings-only = nothing to point at).
    
    ### D. Submodule of a single-plugin repo (self-loading, no settings.json needed)
    
    If the repo you're vendoring has `.claude-plugin/plugin.json` at its **root** (not just
    a `marketplace.json`), a plain submodule under `.claude/skills/` or `~/.claude/skills/`
    is enough:
    ```
    git submodule add https://github.com/owner/single-plugin-repo.git .claude/skills/their-plugin
    cd .claude/skills/their-plugin && git checkout v0.1.0 && cd -
    ```
    On the next session (after the project-scope trust dialog), it self-loads as
    `their-plugin@skills-dir` — no marketplace, no install step, no settings.json edit.
    Caveats: the same primary-working-directory / trust-dialog rule stated above applies
    (exact version gate: `references/official-docs.md`); and because a project-scope
    skills-dir plugin's content comes from the repository, its code-running components are
    gated further — MCP servers it declares go through the same per-server approval as a
    project `.mcp.json`, LSP servers start only after you trust the workspace, and
    background monitors do not load (personal-scope `~/.claude/skills/` plugins have none of
    these restrictions). **This repo's own root has only `marketplace.json`,
    not `plugin.json`, so a bare submodule of *this* repo does not self-load this way — use
    B1 or B2.**
    
    ### C. npm (flat, non-plugin install)
    
    `npx skills add` installs skills flatly — see README §C and `scripts/install-flat.sh`.
    It reads `marketplace.json` / `plugin.json`, but only follows locally-declared skill
    paths — it does not fetch the aggregated externals' remote `github` / `git-subdir`
    sources (below), so those are skipped. Use it for a single skill set with no
    aggregation needs, not for this catalog's full plugin set.
    
    ## Aggregating other skill repos (don't reinvent)
    
    A marketplace is a catalog of plugins from **many sources** — that is the native
    aggregation mechanism, no submodule required. Add more entries to `plugins[]`,
    each with its own source:
    
    ```json
    "plugins": [
      { "name": "your-skills",        "source": "./" },
      { "name": "someones-testing",   "source": { "source": "github", "repo": "them/testing-skills" } },
      { "name": "vendored-thing",     "source": { "source": "git-subdir", "url": "https://…", "path": "tools/plugin" } }
    ]
    ```
    Accepted plugin source types (relative path, `github`, `url`, `git-subdir`, `npm`, `archive`,
    `command`) and the exact fields and Claude Code version each requires drift with new
    releases — read `references/official-docs.md` rather than trusting a hardcoded list. Use a
    submodule only when you need to **vendor + pin** another repo's content into yours (Model B2
    or D above).
    
    ## Gotchas (verified)
    
    - **Bare submodule of a multi-plugin repo (root has only `marketplace.json`) ≠ discovered.**
      Pair it with the `extraKnownMarketplaces` + `enabledPlugins` settings (Model B2) — or,
      if the submodule's own root has `plugin.json` instead, it self-loads on its own (Model D).
    - **Marketplace state is per-user** (`~/.claude/plugins/known_marketplaces.json`), but the **committed project `.claude/settings.json` declaration** is what makes it reproducible for everyone on trust. Marketplace names are checked against a reserved list (`claude-code-marketplace`, `anthropic-marketplace`, `agent-skills`, …) — adding a new marketplace under a reserved name is rejected outright, and Claude Code re-checks the name on every load, so an *existing* marketplace whose name later becomes reserved stops loading too, erroring with "is registered from an untrusted source" ([errors reference](https://code.claude.com/docs/en/errors#marketplace-is-registered-from-an-untrusted-source)). Fix: remove it and re-add from the official source, or rename it and have users re-add from yours.
    - **Token cost**: every enabled skill's description is always-on context — for the exact
      mechanism see the listing-budget reference doc under `skill-authoring-patterns`. `/doctor`
      and `/skill-doctor` show the actual per-session cost. `skillOverrides: "name-only"` only
      demotes personal/project skills — it does **not** apply to plugin skills ("Plugin skills
      are not affected by `skillOverrides`. Manage those through `/plugin` instead."); for a
      plugin the only levers are disabling it via `/plugin`, or raising the consumer's
      `skillListingBudgetFraction`.
    - **Relative marketplace paths**: see B2 step 2 above for the exact resolution rule and its
      one exception (direct-URL marketplaces) — [Create and distribute a plugin
      marketplace](https://code.claude.com/docs/en/plugin-marketplaces#relative-paths).
    - **A skill/plugin `name` containing "claude"** loads fine in Claude Code — this skill's own
      name is proof, and `claude-hud`/`claude-mem` ship the same way — but is rejected by the
      platform Agent Skills spec's reserved-word rule. This only matters if the skill is ever
      uploaded to claude.ai, the Skills API, or packaged with `package_skill.py`; the Claude Code
      plugin path this skill describes is unaffected.
    
    ## Verification
    
    - `git commit -a` skips new files — `plugin.json`/`marketplace.json` are new, so `-a` silently omits them. Use explicit `git add` and verify with `git show --stat --summary` (plain `--stat` doesn't print the `create mode` lines new files need).
    - `/reload-plugins` then check the skills list shows `your-skills:<skill>` entries.
    - `claude plugin details your-skills@your-skills` lists the bundled skills, agents, and
      token cost — not scope. **Scope** (`user` / `project`) comes from `claude plugin list`;
      a project-scope plugin only resolves from inside that project, so running either command
      from elsewhere returns `Plugin "…" not found`.
    - For model B2: `git ls-files .claude/settings.json` (it's committed) and the submodule
      gitlink point at the intended version.
    
    ## Related skills
    
    - `github-contribution-workflow` — routes plugin distribution/installation questions here; that skill owns PR/issue mechanics, this one owns packaging and discovery.
    - `skill-authoring-patterns` — routes distribution/packaging questions here once a skill is authored; that skill owns authoring conventions, this one owns how the finished skill gets shared.
    

Comments (0)

Sign in to join the conversation.

No comments yet.

Reviews (0)

No reviews yet.

Related