Skip to content

Docs: clarify install-time discovery rules for marketplace-published plugins (.apm/<type>/ vs root convention dirs) #1161

@danielmeppiel

Description

@danielmeppiel

TL;DR

Authoring a multi-plugin marketplace publisher repo today requires reading APM's integrator source code to figure out the right source layout. The pack-distribute and marketplace-authoring guides imply a layout that silently breaks at install time for half the primitive types.

Concrete ask (docs-only): add a per-primitive scan-path table sourced from the integrators, recommend .apm/<type>/ as the symmetric canonical layout for marketplace publishers, and add a worked example of a multi-plugin publisher repo (top-level marketplace: + per-plugin apm.yml + per-plugin apm pack).

Problem

The "convention dirs" layout shown for apm pack in the pack-distribute guide (i.e. agents/, skills/, commands/, instructions/, hooks/ at plugin root) is asymmetric between the pack-export code path and the install-integrate code path.

  • apm pack (liberal): accepts both .apm/<type>/ AND root <type>/ for all primitive types.
  • apm install (per-integrator, stricter): only agents and skills accept root <type>/. Instructions, commands, hooks, and mcps are scanned ONLY under .apm/<type>/.

As a marketplace publisher, this means if I author a plugin with instructions/foo.instructions.md at plugin root (per the docs), apm pack happily includes my file in the bundle — but downstream apm install silently drops it. No warning, no error, no doc that flags this.

This bit me hard while building DevExpGbb/zava-agent-config (a multi-plugin marketplace publisher used for an enterprise demo). Debugging took ~half a day; the only way to discover the gap was reading instruction_integrator.py.

What I expected from the docs

That the "convention dirs" pattern shown as the canonical apm pack output (per Bundle structure → Single plugin per repo and the remap table) would also be the layout that consumers see and that integrators scan at install time. The remap table even shows .apm/instructions/*.instructions.mdinstructions/*.instructions.md as the deployed shape — implying parity. Nothing on pack-distribute, marketplace-authoring, or marketplaces mentions that authoring directly into root instructions/ (without .apm/) will be silently dropped at install time.

What actually happens

Two scan modes diverge:

Pack-export (liberal — accepts both layouts):

  • _collect_apm_components() scans .apm/{agents,skills,prompts,instructions,commands}src/apm_cli/bundle/plugin_exporter.py:~83
  • _collect_root_plugin_components() scans root {agents,skills,commands,instructions}src/apm_cli/bundle/plugin_exporter.py:~111

Install-integrate (per-integrator, stricter):

Integrator Source Scans .apm/<type>/ Scans root <type>/
AgentIntegrator.find_agent_files integration/agent_integrator.py:40-64 .apm/agents/, .apm/chatmodes/ <root>/*.agent.md, <root>/*.chatmode.md
SkillIntegrator._integrate_skill_bundle integration/skill_integrator.py:1029+ .apm/skills/ <root>/skills/<name>/ (only when package_type ∈ {MARKETPLACE_PLUGIN, SKILL_BUNDLE})
InstructionIntegrator.find_instruction_files integration/instruction_integrator.py:35-44 hard-coded subdirs=[".apm/instructions"]
CommandIntegrator.find_prompt_files integration/command_integrator.py:185 .apm/prompts/
HookIntegrator integration/hook_integrator.py:282 .apm/hooks/

Net: agents and skills tolerate root convention-dirs at install time; instructions, commands, hooks, mcps do not.

Concrete failure I hit

In zava-agent-config v2.0.0, plugins followed the convention-dirs pattern shown in the pack docs:

  • plugins/<kit>/agents/security.agent.md → ✅ deploys (root *.agent.md glob)
  • plugins/<kit>/skills/<name>/SKILL.md → ✅ deploys (MARKETPLACE_PLUGIN branch in SkillIntegrator)
  • plugins/<kit>/instructions/<x>.instructions.md → ❌ silently does not deploy — only .apm/instructions/ is scanned

apm pack showed the file in the bundle, so authoring-side feedback was green. The gap surfaced only when a downstream consumer ran apm install and noticed agent prompts weren't picking up the rules. No warning, no doc page, no per-primitive layout reference.

How I resolved it (validates the recommended layout)

zava-agent-config v4.0.0 standardizes on plugins/<kit>/.apm/<type>/ for every primitive type. Verified end-to-end:

  1. Install side (apm install): all 7 primitives across 4 plugins deploy correctly — 2 agents, 2 skills, 3 instructions. Storefront PR (merged) shows green CI on apm audit --ci.

  2. Pack side (apm pack per-kit): with a per-plugin apm.yml (containing minimal dependencies: apm: [] to satisfy the "neither dependencies nor marketplace" check), apm pack --offline correctly:

    • synthesizes plugin.json from apm.yml metadata into build/<name>-<version>/plugin.json
    • remaps .apm/agents/*.agent.mdagents/*.agent.md
    • remaps .apm/skills/<name>/skills/<name>/
    • emits a clean Anthropic-shape plugin bundle ready to publish

So the symmetric .apm/<type>/ source layout is the canonical layout that satisfies both code paths simultaneously. The docs just don't say so.

What would help

A docs section (probably an addition to pack-distribute or a new "Plugin layout reference" page) that:

  1. Documents the asymmetry explicitly — pack-export is liberal, install-integrate is stricter and per-primitive.
  2. Provides a per-primitive scan-path table like the one above, sourced from the integrators rather than the pack exporter, so authors know what consumers will actually see at install time.
  3. Recommends .apm/<type>/ as the symmetric canonical layout for ALL primitives in a multi-plugin marketplace publisher repo — i.e. tell authors "use .apm/<type>/ and both code paths agree; use root convention dirs and only agents+skills will work."
  4. Shows a worked example of a marketplace publisher repo with multiple plugins, each as a self-contained APM package: per-plugin apm.yml + .apm/<type>/ source tree + per-plugin apm pack to emit plugin.json, plus a top-level apm pack to emit marketplace.json. The current marketplace-authoring guide covers the marketplace block beautifully but stops short of showing the in-plugin source layout, and the pack-distribute "Multi-plugin repo" section is similarly silent on per-plugin source layout. zava-agent-config at v4.0.0 is a working reference if useful as a starting point.

Scope

This is a docs-only ask — please do not treat it as a request to change integrator behavior. Whether the install-time scanners should also accept root convention dirs (matching the pack exporter) is a separate behavior question I'm happy to file as a follow-up if useful. For now I just want the docs to reflect what the code actually does, so the next author building a marketplace publisher repo doesn't lose half a day to silent-drop debugging.

Metadata

Metadata

Assignees

Labels

area/docs-sitedocs/src/content (Starlight), README, doc generation.area/package-authoringapm pack/unpack, plugin authoring, vendoring guidance, bundle format.priority/highShips in current or next milestonestatus/acceptedDirection approved, safe to start work.status/triagedInitial agentic triage complete; pending maintainer ratification (silence = approval).theme/portabilityOne manifest, every target. Multi-target deploy, marketplace, packaging, install.type/docsDocumentation change (prose, examples, generated reference).

Type

No type
No fields configured for issues without a type.

Projects

Status
Done

Relationships

None yet

Development

No branches or pull requests

Issue actions