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 --marketplacestarts a project that will publish its own marketplace -
apm marketplace initappends amarketplace:block to yourapm.ymland creates.claude-plugin/ - there are authoring helpers around it —
check,outdated,migrate,package -
apm packbuilds.claude-plugin/marketplace.jsonfrom that block — that is the publishing step, and the file is the artifact -
microsoft/apm-actionruns the whole release: gate, matrix-pack, sha256 sidecars,marketplace.jsondrift 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'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.yamlcan pin the resolved tree with integrity hashes,apm-policy.ymlcan constrain sources with tighten-only inheritance from enterprise to org to repo, andapm lock exportcan emit CycloneDX or SPDX. -
Reproducibility as a contract.
git clone && apm installis 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 pushis 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 --tagreads only the commits touching that plugin's directory since its lastcommit-crafter@x.y.ztag, 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.0puts 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.
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.
- agkit — npm · docs · source
- APM — github.com/microsoft/apm · docs
- Previously: Stop zipping your Claude Code skills: build a plugin marketplace in 15 minutes
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)