Skip to content

Restructure repo to host multiple plugins (Claude Code, Codex, npx skills) over one shared skills/ pool #4

Description

@MateuszNaKodach

Context

Today the repo is a single Claude Code marketplace with one plugin:

.claude-plugin/
├── marketplace.json        # marketplace "axoniq-agent-skills" → 1 plugin "axon4to5" (source "./")
└── plugin.json             # the axon4to5 plugin manifest
skills/
└── axon4to5-openrewrite/   # the only skill so far

We expect many plugins in this repo, each bundling a subset of the skills in skills/, while keeping skills/ at the root as the single canonical source so it stays directly consumable by:

  • Claude Code (marketplace install)
  • npx skills / agentskills.io (reads skills/<name>/SKILL.md at repo root)
  • a future Codex plugin/manifest (also reads the same pool)

Problem / core constraint

The obvious approach — multiple marketplace.json entries all with source: "./" plus a skills selector — does not subset. Per the Plugins reference:

  • Component paths must be relative to the plugin root, start with ./, and cannot traverse outside it (../shared "will not work after installation because those external files are not copied to the cache"). → #path-traversal-limitations
  • The skills manifest field adds to the default skills/ scan — it does not replace it. → #component-path-fields

So any plugin whose root is the repo root auto-discovers the entire root skills/ dir. The current setup only appears to select because there is exactly one skill.

Goals

  • Support N plugins in this repo, each exposing a curated subset of skills
  • Keep skills/ at the repo root as the single source of truth (no duplication of skill content)
  • Remain installable as a Claude Code marketplace
  • Stay directly consumable by npx skills / agentskills.io and a future Codex manifest
  • Local-dev + CI friendly; cross-platform aware

Options

Option A — Symlink monorepo (officially documented for this case)

Per-plugin subdirectories; each plugin's skills/ holds symlinks into the canonical root skills/. On marketplace install, Claude dereferences sibling-marketplace symlinks (copies the real content into its cache). → Share files within a marketplace with symlinks

.claude-plugin/marketplace.json          # metadata.pluginRoot="./plugins"; one entry per plugin
skills/                                   # canonical pool (untouched)
  axon4to5-openrewrite/SKILL.md
  ...
plugins/
  axon4to5/
    .claude-plugin/plugin.json
    skills/
      axon4to5-openrewrite -> ../../../skills/axon4to5-openrewrite   # symlink
  axon-devagent/
    .claude-plugin/plugin.json
    skills/
      axon-devagent-assistant -> ../../../skills/axon-devagent-assistant
  • Pro: True per-plugin subsetting; zero content duplication; npx skills/Codex read root skills/ untouched; no strict:false, no duplicated component lists.
  • Con: Windows — Git checks symlinks out as text stubs unless core.symlinks=true + Developer Mode — affects Windows contributors and Windows end users whose Claude fetches the marketplace.
  • Con: claude --plugin-dir <subdir> does not dereference cross-dir symlinks; local testing must use /plugin marketplace add <local path> then install.

Option B — Committed generator / copy-sync (Windows-proof)

Same plugins/<name>/ layout, but instead of committing symlinks, commit a small scripts/link-skills.sh driven by a declared skill list per plugin. Use symlinks for local dev and copy real files at release (or always copy).

  • Pro: Bulletproof across OSes and both consumers; no symlink fragility.
  • Con: Adds a build/sync step; "copy" mode duplicates skill content in the published tree.

Option C — Separate sources via git-subdir / per-repo plugins

Keep one marketplace.json but fetch each plugin from its own path/repo using source: { "source": "git-subdir", ... }. → Plugin sources

  • Pro: Best if plugins eventually live in separate repos; sparse-clones large monorepos.
  • Con: Doesn't share one in-repo skills/ pool as cleanly; more moving parts.

Option D — Single mega-plugin, no subsetting

One plugin bundles all skills; rely on Claude auto-activating the right skill by description.

  • Pro: Simplest; no plumbing.
  • Con: No separate install units / branding / discovery per domain; conflates unrelated skills.

Recommendation

Option A (with B as the fallback if Windows contributors/users are in scope). It's the documented mechanism, keeps skills/ canonical for all three runtimes, and needs no content duplication.

Follow-up work if A/B is chosen

  • Migrate axon4to5 into plugins/axon4to5/
  • Rewrite marketplace.json (metadata.pluginRoot: "./plugins", one entry per plugin, drop strict:false)
  • Update README.md local-test instructions (marketplace add instead of --plugin-dir)
  • Document the Windows symlink requirement (and/or add the generator script for Option B)

References

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions