DEV Community

Cover image for APM vs agkit: is your plugin marketplace a build artifact or a source of truth?
Fairen
Fairen

Posted on

APM vs agkit: is your plugin marketplace a build artifact or a source of truth?

Microsoft shipped APM — Agent Package Manager. 3.2k stars, apm.yml, a lockfile, policy files, SBOM export, eight coding agents configured from one manifest. It is a serious piece of work.

I maintain agkit, which scaffolds and manages agent plugin marketplaces. So when APM landed, the honest first reaction was the one you'd expect: is there anything left for mine to do?

Take what follows with the appropriate grain of salt — I am not a neutral party. But I spent a week in APM's docs and issue tracker trying to answer that question properly, and the answer turned out to be more interesting than either "no" or "obviously yes." The two tools overlap almost completely on the surface, and disagree about one thing underneath. That one thing is the whole decision.

The easy answer, and why it's wrong

The comfortable story writes itself: APM installs, agkit publishes. Consumer versus producer. Two halves of the same problem. Everybody shakes hands.

It's wrong, and it's worth killing before it spreads, because APM publishes marketplaces perfectly well:

  • apm init --marketplace starts a project that will publish its own marketplace
  • apm marketplace init appends a marketplace: block to your apm.yml and creates .claude-plugin/
  • there are authoring helpers around it — check, outdated, migrate, package
  • apm pack builds .claude-plugin/marketplace.json from that block — that is the publishing step, and the file is the artifact
  • microsoft/apm-action runs the whole release: gate, matrix-pack, sha256 sidecars, marketplace.json drift detection, gh release create

So both tools take skills sitting on your disk and turn them into something other people install by name, at a version. If you want a reason to pick one over the other, "producer versus consumer" is not it.

What they actually disagree about

APM authors in apm.yml plus .apm/ and compiles marketplace.json with apm pack; agkit's marketplace.json is itself the source of truth, read as-is by Claude Code and Copilot

APM's source of truth is apm.yml plus a .apm/<type>/ tree. marketplace.json is what falls out the other end. apm pack is a compiler, and APM is deliberate about this: the GitHub Action doesn't assume which CLI consumes the output, it just emits whatever your outputs: map declares — claude=marketplace.json, codex=plugins.toml. Vendor-neutral by design. The catalog is a build artifact.

agkit's source of truth is .claude-plugin/marketplace.json itself. There is nothing to compile for Claude Code and Copilot, because they read that file as-is. agkit sync runs the other way entirely: the README plugin table and the AGENTS.md list are derived from the catalog, so they can't drift. The catalog is the source of truth.

Same filename. Opposite direction. Everything else follows from that.

What the compile step buys you

A real abstraction layer earns its keep, and APM's does:

  • One manifest, many ecosystems. Declare once, deploy across Copilot, Claude Code, Cursor, OpenCode, Codex, Gemini, Windsurf, and Kiro. When a vendor changes its format, that's APM's problem, not yours.
  • Somewhere to hang governance. You cannot lock, hash, scan, and police a file that people hand-edit. Once the catalog is generated, apm.lock.yaml can pin the resolved tree with integrity hashes, apm-policy.yml can constrain sources with tighten-only inheritance from enterprise to org to repo, and apm lock export can emit CycloneDX or SPDX.
  • Reproducibility as a contract. git clone && apm install is a promise. A marketplace is only ever an offer.

What it costs you

An abstraction is a thing you have to learn, a build you have to run, and a place bugs can live that couldn't otherwise exist.

APM's own authoring guide is refreshingly blunt about one of these. apm pack is liberal — it collects primitives from both .apm/<type>/ and root convention directories like agents/ or skills/. apm install is stricter, and per-primitive. The consequence is that if you author instructions/ at your plugin root, your bundle packs cleanly and then installs silently incomplete. Their recommendation to marketplace publishers is to use .apm/<type>/ for every primitive, because it's the only layout that's symmetric across both commands.

That's good documentation of a sharp edge. It is also a category of bug that cannot exist when there is no compile step — when the file you edit is the file the agent reads, "packs but doesn't install" isn't a state your project can be in.

What agkit's directness buys you

  • What's in the repo is what ships. No build, no artifact, no drift between them. git push is the release — no registry, no account, no publish token.
  • Zero adoption cost. npx agkit init dev-toolkit, Node 22+, nothing installed. Compare with adopting a manifest format, a lockfile, and a release pipeline before your first plugin exists.
  • The plugin is the unit of release. agkit bump commit-crafter --tag reads only the commits touching that plugin's directory since its last commit-crafter@x.y.z tag, applies conventional-commit rules, writes the manifest version, generates the changelog entry, syncs the derived files, and tags it. Semantic-release, scoped to one plugin, so a busy plugin never drags a quiet one into a release.
  • Reference without vendoring. agkit add octo-org/changelog-skill changelog --ref v1.2.0 puts someone else's plugin in your catalog without cloning it. Your repo gains one JSON entry; the agent resolves the source at install time.

What it costs you

You inherit the platform's model, including its future. If Anthropic and GitHub change the catalog shape, agkit follows them; it has no layer to absorb the change on your behalf. That's the deal you're signing.

And there's a harder limit. agkit has no lockfile, no integrity hashes, no policy file, no SBOM, and no supply-chain scanning. If your security team needs to say "these are the only sources this organisation will allow" and have it enforced on every install, agkit has nothing to offer them. That isn't a roadmap gap I'm being coy about. It's the wrong tool, and APM is the right one.

They compose — and that's the actual answer

Here is the part I didn't expect to find, and the reason this article isn't a fight.

An agkit-published repo is consumed either natively by Claude Code and Copilot, or through APM, which adds a lockfile, SHA pinning, scanning, policy and SBOM on top of the same catalog

APM reads marketplace.json as-is — both .github/plugin/marketplace.json and .claude-plugin/marketplace.json. It normalises both dialects: Copilot CLI uses repository and ref fields, Claude Code uses source as a string or an object, and APM maps either onto its canonical dependency representation. It then resolves each entry to a Git URL — at which point plugins installed from that marketplace get the same version locking, security scanning, and governance as any other APM dependency.

Read that from a publisher's chair. An agkit-published marketplace is already an APM dependency. You don't do anything. You published the format the platform defined, and APM speaks it fluently.

So the split was never producer versus consumer. It's this:

You choose how you author. Your users choose how they consume.

Those are two decisions, made by two different people, at two different times — and neither tool forces the other's hand. A solo maintainer publishes a catalog with agkit and git push. A regulated bank three timezones away installs one plugin out of it through apm install commit-crafter@dev-toolkit, with a lockfile, a pinned SHA, a Unicode scan and a policy gate in the way. Nobody had to agree on a toolchain. They agreed on a file format, which is the only thing worth agreeing on.

So which one?

agkit APM
Catalog is the source of truth a build artifact
You author in the platform's native format apm.yml + .apm/<type>/
Build step none for Claude Code / Copilot apm pack
Release unit the plugin (per-plugin semver + changelog + tag) the package / project
Version bump computed from conventional commits you decide, CI releases
Distribution git push to any forge git, plus release artifacts
Consumption the agent's native /plugin install apm install + lockfile
Governance none lockfile, hashes, policy, SBOM, drift detection
Targets Claude Code, Copilot native · Codex, Cursor via agkit build 8 agents from one manifest
Runtime Node 22+, npx-able Python binary — curl, brew, pip, scoop

Reach for agkit when you're publishing: you have skills you want other people to install by name, you want the catalog to be a file you can read, and you want git push to be the whole release pipeline.

Reach for APM when you're consuming or governing: you need every developer and CI runner to end up with a byte-identical agent setup, you need to answer "what reached disk and from where," or someone in your organisation has an opinion about supply chains that comes with a compliance deadline attached.

Reach for both in the obvious configuration: publish with agkit, let the people who need governance put APM in front of it. The catalog doesn't care.

The honest closing

APM is a bigger project than mine, backed by an organisation, moving faster, and solving a problem I'm not solving. Its authoring surface has been growing steadily — and if it eventually converges on treating the catalog as the source rather than the output, agkit's reason to exist gets thin.

I'd take that outcome. I wrote agkit because assembling marketplace.json by hand at 6pm on a Friday is a chore, not because the ecosystem was short an abstraction. If that chore stops existing, the tool has done its job either way.

Until then: the file is the interface. Pick whichever tool gets you to a good one.


Compared against APM v0.25.0 and agkit 0.9.2, July 2026. Both move fast — check the docs before quoting me. agkit is MIT-licensed and unaffiliated with Anthropic, GitHub, Microsoft, OpenAI or Cursor.

Top comments (0)