Skip to content

APM integration — a few alignment notes from the APM side #1015

Closed

Description

@danielmeppiel

Hey Squad team — first off, thanks for shipping #876 and following up so cleanly with #963. Squad reaching for APM as the distribution layer is a milestone, and the framing in the PR description (".squad/ remains the source of truth — APM is an export layer") nails the architecture I'd hoped third-party tools would land on.

I'm Daniel, the maintainer of microsoft/apm. Working through the merged code, I noticed the integration drifts from APM's current contract in a handful of spots. Each one has a documented APM-side answer, and most would simplify Squad's code in the process. Writing this up so it's all in one place — happy to send a PR for the mechanical bits if it's useful.

Summary

# Area Squad today APM contract
1 apm.yml schema Top-level skills: / instructions: / prompts: Not valid keys; primitives are discovered from .apm/
2 Install Reimplemented via gh api + a regex YAML parser Shell out to apm install owner/repo[/skill-name]
3 Publish/portability Custom apm.yml regen apm pack --format plugin produces a portable bundle
4 Distribution model "APM registry" / apm publish Git-native; no registry; apm publish doesn't exist
5 Skill source path .copilot/skills/<name>/skill.md .apm/skills/<name>/SKILL.md (then APM deploys to .copilot/, .github/, etc.)

1. apm.yml doesn't have skills: / instructions: / prompts: top-level keys

The manifest only recognizes name, version, description, author, license, target, type, scripts, dependencies, devDependencies, compilation (manifest-schema §2). Primitives aren't declared in the manifest — they're discovered from .apm/<primitive>/ directories (primitive-types). The blocks Squad emits are silently ignored by apm install, and the target: paths inside them aren't honored — APM's integrators decide deployment paths based on the consumer's target: setting.

Suggested: emit only the fields APM reads — typically name, version, and (when relevant) a dependencies.apm: block. Skill content goes in .apm/skills/<name>/SKILL.md and is picked up automatically.


2. squad skill install reimplements apm install

The current path uses gh api to fetch the upstream apm.yml, parses it with a regex YAML reader, then gh api-fetches each skill.md. APM's apm install already does this and a lot more (cli-commands):

apm install owner/repo                  # whole package
apm install owner/repo/skill-name       # virtual subdirectory (selective)
apm install owner/repo/path/skill.md    # single file

You also get lockfile pinning (apm.lock.yaml), transitive resolution, content-hash verification, and security scanning — none of which are reachable via the gh api path. The lockfile also tracks provenance, so .apm-source.json becomes redundant.

Suggested: swap the install internals for execFile('apm', ['install', source]). Drops ~200 LOC including the YAML parser flagged in #963.


3. The actual feature for "make this Squad portable" is apm pack --format plugin

squad skill publish regenerates apm.yml to advertise local skills. The intent — "make this skill bundle portable so others can use it" — is exactly what apm pack --format plugin solves (pack-distribute §plugin format):

"apm pack --format plugin transforms your project into a standalone plugin directory consumable by Copilot CLI, Claude Code, or other plugin hosts. The output contains no APM-specific files."

Mapping:

Source Plugin output
.apm/skills/*/SKILL.md skills/*/SKILL.md
.apm/agents/*.agent.md agents/*.agent.md
.apm/prompts/*.prompt.md commands/*.md
.apm/instructions/*.instructions.md instructions/*.instructions.md

Suggested: squad skill publish shells out to apm pack --format plugin after laying skills out under .apm/skills/<name>/SKILL.md. Users git push the resulting bundle. This also unlocks "hybrid mode" (guides/plugins) — Squad packages can declare dev-only deps that get excluded from the published bundle.


4. There's no APM registry and no apm publish

A few user-facing strings reference both:

  • skill.ts:173 — "push to GitHub to share via APM registry"
  • skill.ts:183 — "Run 'apm publish' to push to the APM registry"
  • skill.ts:298 (help) — "APM registry: https://github.com/microsoft/apm"

APM is git-native by design (what-is-apm):

"Distribute. Any git repository is a valid APM package. Publish by pushing to a git remote — no registry required."

microsoft/apm is the source repo, not a registry endpoint. Marketplaces (guides/marketplaces) exist as optional curated indexes for discovery, but there's no apm publish and no plan to add one — the model is intentionally git push.

Suggested: update the strings to "Run apm pack --format plugin to produce a portable bundle, then git push to share."


5. Skill source location: .apm/skills/, not .copilot/skills/

Worth being precise on the directory model since the doc has been ambiguous on this:

  • .apm/<primitive>/ is where a project's own primitives live (the project itself is a package). APM discovers them automatically.
  • .copilot/, .github/, .claude/, .cursor/ are deploy targets that apm install populates, both from local .apm/ content and from installed dependencies. They're outputs, not sources.

Today resolveSkillsDir writes skills to .copilot/skills/<name>/skill.md as the source location, which inverts that model. (Side note: @Omzig already noted in #924 that Copilot CLI doesn't actually read .copilot/skills/ either, so users probably aren't getting what they expect on the consumer side.)

Suggested: treat .apm/skills/<name>/SKILL.md as the source of truth. APM's integrators handle the per-target deployment.


On the APM side

A few things shipping in parallel that should make this easier going forward:

  • JSON Schema for apm.yml (warns rather than errors on unknown top-level keys, so existing Squad-generated manifests in the wild won't break overnight).
  • A short doc page aimed at framework authors integrating with APM, with Squad as the worked example if you're OK with that.

Offer

Items 1, 2, 4, 5 are mechanical and I'd estimate ~150 LOC net delta (negative once the YAML parser comes out). Happy to PR them in one or split across a few. Item 3 is a UX shift for squad skill publish so I'd defer to you on direction before opening anything.

Let me know what's useful — no obligation either way, and again, really nice to see APM integration in Squad.

— Daniel

Activity

  1. bradygaster commented on Apr 25, 2026

    @bradygaster
    Collaborator

    Closed by #theSquadsquad triage — verified fixed/superseded in v0.9.4.

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