Repo shapes for marketplace producers
A marketplace producer repo is just an apm.yml (or several) plus a
marketplace: block. There is no --shape flag and no scaffold
mode: every layout below emerges from the same two commands,
apm plugin init and apm marketplace init, composed differently.
Two primitive postures cover most repos — you ship your own plugin, or you curate others’ plugins into a marketplace. The third row in the table is what happens when one repo does both at once. Pick the shape that matches how the source code is already organised; you can migrate later by moving directories and re-running the same commands.
| Shape | Source files | When |
|---|---|---|
| Single-plugin | One apm.yml at the repo root | One plugin per repo. Smallest surface, fewest gotchas. |
| Aggregator | One apm.yml at the root, N remote packages: | You curate other repos into a marketplace. |
| Monorepo-hybrid (advanced) | Root apm.yml plus per-plugin apm.yml subdirs | Many plugins live alongside the marketplace in one repo. Composition of the two postures above. |
When the layout is ready, ship it with the recipe in Releasing from any CI.
Single-plugin
Section titled “Single-plugin”One repo, one plugin, one marketplace entry pointing at the local source. The marketplace artifact and the plugin live side by side.
Scaffold:
apm plugin init my-plugin --yesapm marketplace init --owner acme-org --name my-marketplaceapm marketplace package add ./ --name my-plugin --version 0.1.0Resulting apm.yml:
name: my-pluginversion: 0.1.0description: Single plugin shipped through its own marketplace
marketplace: owner: name: acme-org url: https://github.com/acme-org outputs: claude: {} packages: - name: my-plugin source: ./ version: 0.1.0apm pack writes the plugin bundle to ./build/my-plugin/ and the
marketplace artifact to .claude-plugin/marketplace.json. Commit
both. Consumers run apm marketplace add acme-org/<repo>.
Aggregator
Section titled “Aggregator”One repo whose only job is to curate plugins that live in other repos. No plugin source lives here.
Scaffold:
apm marketplace init --owner acme-org --name acme-curatedapm marketplace package add acme-org/skill-pkg-a --version "^1.0.0"apm marketplace package add acme-org/skill-pkg-b --ref v0.4.2Resulting apm.yml:
name: acme-curatedversion: 1.0.0description: Curated APM marketplace for acme-org
marketplace: owner: name: acme-org url: https://github.com/acme-org outputs: claude: {} packages: - name: skill-pkg-a source: acme-org/skill-pkg-a version: "^1.0.0" - name: skill-pkg-b source: acme-org/skill-pkg-b ref: v0.4.2apm pack resolves every remote entry against git ls-remote and
writes marketplace.json only. No bundle is produced because there
is no dependencies: block.
Monorepo-hybrid
Section titled “Monorepo-hybrid”Advanced. Most first-time authors should start with single-plugin or aggregator. Reach for hybrid when you’re shipping your own plugin and curating others.
DevExpGbb/zava-agent-configis the live reference: 7 plugins underplugins/, one rootapm.yml, releases via microsoft/apm-action@v1mode: release.
One repo, many plugins under packages/, one marketplace at the root
that lists them as local-path entries. Each plugin gets its own
apm.yml so it can be compiled and tested in isolation.
Layout:
my-monorepo/ apm.yml # marketplace + local-path packages packages/ plugin-a/ apm.yml # plugin-a's manifest .apm/ agents/ expert.agent.md instructions/ style.instructions.md skills/ my-skill/ SKILL.md plugin-b/ apm.yml .apm/ prompts/ review.prompt.md hooks/ pre-tool.jsonImportant — use
.apm/<type>/for every primitive in each plugin.apm packaccepts primitives from both.apm/<type>/and root convention directories (e.g.instructions/at the plugin root), butapm installonly discovers instructions, commands, and prompts under.apm/<type>/. Authoringpackages/plugin-a/instructions/style.instructions.mdinstead ofpackages/plugin-a/.apm/instructions/style.instructions.mdwill produce a bundle that packs correctly but installs silently incomplete. See Pack a bundle — source layout and install-time discovery for the full per-primitive scan-path reference.
Scaffold:
apm plugin init plugin-a --yes # cd packages/plugin-a firstapm plugin init plugin-b --yes # cd packages/plugin-b firstcd ../..apm marketplace init --owner acme-org --name acme-monorepoapm marketplace package add ./packages/plugin-a --name plugin-aapm marketplace package add ./packages/plugin-b --name plugin-bResulting root apm.yml:
name: acme-monorepoversion: 1.0.0description: Acme plugins shipped together
marketplace: owner: name: acme-org url: https://github.com/acme-org outputs: claude: {} versioning: strategy: lockstep # see versioning-strategies packages: - name: plugin-a source: ./packages/plugin-a version: 1.0.0 - name: plugin-b source: ./packages/plugin-b version: 1.0.0Local-path entries skip remote resolution. Each plugin’s own
apm.yml controls its build; the root apm.yml controls the
marketplace index. Pick a versioning strategy that matches how you
tag releases — see Versioning strategies.
Shipping bin/ executables (Claude Code only)
Section titled “Shipping bin/ executables (Claude Code only)”A plugin may ship a top-level bin/ directory of executable scripts.
When a consumer runs a global install (apm install -g), APM
deploys the plugin as a Claude Code skills-directory plugin (a folder
containing .claude-plugin/plugin.json) under the Claude skills
directory, which puts bin/ on Claude Code’s Bash tool PATH. The
agent can then invoke your scripts as bare commands.
my-plugin/ apm.yml .apm/ bin/ my-tool # executable script (chmod handled by APM)This is a Claude-Code-specific contract — no other harness has an
equivalent — so bin/ deploys only when the consumer has an active
Claude Code skills target. Authoring rules:
- Deploy is user-scope only. A project-scope install (without
-g) skipsbin/and prints a hint to re-run with-g. - APM sets user-only execute on deployed files (owner +x; group and other execute bits are cleared). Do not rely on a specific umask.
- Deployed executables sit on Claude Code’s
PATHand are invoked without per-call confirmation. Treat them as trusted code: keep them minimal, audited, and free of network side effects you would not want an agent to trigger unprompted. - Enterprises can deny deployment per-package or globally via the
bin_deploypolicy rule — see the policy schema.
What to read next
Section titled “What to read next”- Versioning strategies — lockstep vs
per-package and how
apm pack --check-versionsenforces them. - Releasing from any CI — the canonical release pipeline that ships any of the shapes above.
- Publish to a marketplace — the
apm marketplace initwalkthrough and the registry schema.