--- topic: configure source_keys: - context7-microsoft-apm --- ## Scaffolding a new package ```bash apm plugin init --yes --target claude,copilot ``` Run from inside the target package directory, with no positional name argument (see Gotchas). Creates `apm.yml` + `plugin.json` in the current directory — it does NOT scaffold a `.apm/` skeleton. Primitive subdirectories (`.apm/skills/`, `.apm/agents/`, `.apm/hooks/`) must be created manually as content is migrated into them. Run this once per package (e.g. once per `plugins//` directory in a monorepo-hybrid layout), not once for the whole repo. ## `apm.yml` — required fields Only `name` and `version` (SemVer) are required: ```yaml name: my-pkg version: 1.0.0 ``` ## `apm.yml` — top-level keys - `name`, `version` — required (see above) - `description`, `author`, `license`, `homepage`, `repository`, `keywords` — standard package metadata - `type` — `instructions | skill | hybrid | prompts`; selects how the package is processed at install/compile time. It is a routing selector, not a constraint on what `.apm/` may contain (see Gotchas) - `targets` — which harnesses this package compiles to (plural list form preferred; legacy singular `target: copilot,claude` CSV form still accepted) - `includes` — `auto` publishes the authoritative local layout as-is; it is not scoped down to what's relevant, so anything narrower needs an explicit repo-path list. Note: `auto` also does not sweep generic root-level passthrough files (README.md, docs/, sources.md, config files) into the `apm pack` distribution bundle — see `references/compile.md` - `dependencies`/`devDependencies` — `apm`/`mcp`/`lsp` entries; `devDependencies` share the same shape but are excluded from the shipped artifact - `scripts` — named commands runnable via `apm run ` - `compilation` — target/strategy/exclude/placement controls for `apm compile`/`apm pack` - `policy` — e.g. `fetch_failure_default` - `registries` — named registry endpoints for shorthand dependency resolution - `marketplace` — owner + packages list; see `references/marketplace.md` for the full marketplace workflow See `docs/research/docs/microsoft-apm/configuration.md` for the complete annotated schema. ## Bumping a package's own version (repo policy) apm ships no version-bump command, so `version:` in a package's own `apm.yml` is a hand edit. Policy: **bump a package's own `apm.yml` `version:` whenever anything that reaches its compiled output changes.** Two triggers, not one: - **Its `.apm/` content** — a new or removed skill/agent/hook, or a substantive edit to an existing one. - **Its own `apm.yml` manifest metadata** — `description`, `keywords`, `author`, `license`, `homepage`, `repository`. These are compiled verbatim into `.claude-plugin/plugin.json` and `.github/plugin/plugin.json`, so editing them republishes the package's public description under an unchanged version number, which is the same defect as shipping changed content silently. Purely local edits that reach no compiled output — a `README.md`, a `docs/` page — do not require a bump on their own. The version belongs to the package, not to the repo: editing `plugins/foo/.apm/` never bumps `plugins/bar/apm.yml`. Under a `per_package` strategy the same number is also carried in the catalog's `marketplace.packages[]` entry, so both copies move together in the same commit. The catalog's own version follows a separate rule — see `references/marketplace.md`. `apm pack --check-versions` fails the push when a package's version disagrees with the configured strategy, so a bump applied in only one of the two places is caught, but a bump skipped in both is not: nothing infers intent from a content diff. ## Dependency reference forms `dependencies.apm` entries accept: a pinned tag (`owner/repo#tag`), a plain repo (uses default branch), a single primitive path within a repo, a raw git URL, a `git:`/`path:`/`ref:` object for finer control, or a local relative path (`./packages/my-shared-skills`). ## MCP server secrets `${VAR}` indirection is required for MCP server secrets (headers, env vars) in `apm.yml`, never literal values — see SKILL.md Gotchas. ## Registries (config-level, not `apm.yml`) Any git repo is a valid package source by default — no registry required. To declare named registries for shorthand dependency resolution: ```bash apm experimental enable registries # required first — see Gotchas apm config set registry.corp-main.url https://artifactory.corp.example.com/apm apm config set registry.corp-main.token eyJ... apm config set registry.corp-main.default true ``` `apm config get`/`apm config unset` manage individual keys the same way. ## Gotchas - `apm.yml`'s `type:` field validates nothing about `.apm/`. It selects processing: `instructions` compiles to AGENTS.md only, `skill` installs a native skill only, `prompts` emits commands only, `hybrid` does both (see `apm_cli/models/validation.py`, `PackageContentType`). apm checks only that the value parses to one of those four strings; no check anywhere compares it against the primitives actually on disk, and no mismatch diagnostic exists. A package declaring `type: instructions` while shipping `.apm/skills/` therefore raises no error — the mismatch resolves silently, either by omitting that primitive from the install/compile output or, in apm 0.28.0 where `get_effective_type()` routes off the on-disk layout and never reads the declared field, by ignoring the declared value outright. Both directions are silent: `apm install` and `apm compile` can exit 0 having shipped none of the primitives you expected. Set `type:` to cover every primitive the package ships, and confirm the deployed output rather than the exit code. - `apm experimental enable registries` must run before any `registry.*` config takes effect. Declaring a `registries:` block or running `apm config set registry.*` without it silently does nothing — no error, no warning. - `apm plugin init ` run with a positional name argument, from inside a directory already named ``, creates a wrongly-nested `//` subdirectory — it treats the positional arg as "create a new project directory named X," not "confirm the current directory is X." Fix: omit the positional argument entirely when already cd'd into the target package directory — run `apm plugin init --yes --target claude,copilot` instead.