Pack a bundle
A bundle is the artifact you hand to a consumer when you do not want to publish
to a registry. It is a directory (or .tar.gz of one) containing a
plugin.json, your primitive folders, and an embedded apm.lock.yaml that
pins every file by SHA-256. Build it with one command from a project that has
.apm/ and apm.yml:
apm packThis is the producer side of Deploy a local bundle.
Consumers who receive the artifact run apm install ./your-bundle and skip
the registry resolver entirely.
What apm pack produces
Section titled “What apm pack produces”By default apm pack writes a plugin-format directory under ./build/:
build/<your-package>/+-- plugin.json+-- agents/+-- skills/+-- commands/+-- hooks/+-- apm.lock.yaml # embedded: pins every file by SHA-256The success line tells you exactly what to share:
$ apm pack[+] Packed 7 file(s) -> build/my-pkg[>] Plugin bundle ready -- contains plugin.json plus plugin-native directories (agents/, skills/, commands/, ...) and an embedded apm.lock.yaml for install-time integrity verification.[i] Share with: apm install build/my-pkgAdd --archive to get a single .tar.gz instead of a directory; use -o to
change the output location (default ./build).
apm pack --archive -o ./dist# -> ./dist/my-pkg-<version>.tar.gzThe plugin.json contract
Section titled “The plugin.json contract”plugin.json is the bundle’s identity card. Only name is required. APM
synthesises one from apm.yml if you do not author it yourself, mapping these
fields:
apm.yml field | plugin.json field |
|---|---|
name | name (required) |
version | version |
description | description |
author | author: {name: ...} |
license | license |
Author your own plugin.json at the project root (or under .github/plugin/,
.claude-plugin/, or .cursor-plugin/) when you need fields APM does not
synthesise — otherwise leave it to apm pack and keep apm.yml as the
source of truth. See Package anatomy for
the full schema.
Integrity: how install verifies the bundle
Section titled “Integrity: how install verifies the bundle”apm pack writes pack.bundle_files into the embedded apm.lock.yaml — a
mapping of every file’s relative path to its SHA-256 digest. On the consumer
side, apm install <bundle> rehashes every file and rejects the bundle if:
- any hash does not match
- any file listed in
pack.bundle_filesis missing - any file is present in the bundle but not listed in the manifest
- any path is a symlink
The manifest is the source of truth. Tampering after pack time is detected
before any file lands in the project. You do not configure this — it runs on
every apm install <bundle>.
Distribution paths
Section titled “Distribution paths”Three common ways to hand off a bundle:
- Directory + git. Commit
build/<pkg>/to a release branch or a separate artifacts repo. Consumersgit cloneand runapm install ./build/<pkg>. - Archive + GitHub release.
apm pack --archivethen upload the.tar.gzas a release asset. Consumers download and runapm install ./<pkg>-<version>.tar.gz. - Marketplace entry. If your project also has a
marketplace:block inapm.yml,apm packbuildsmarketplace.jsonalongside the bundle. See Publish to a marketplace.
For the consumer flags that apply (--target, --global, --force,
--dry-run), see Deploy a local bundle.
Pitfalls
Section titled “Pitfalls”Do not use --format apm for bundles you expect consumers to install.
The legacy APM bundle layout has no plugin.json and apm install rejects
it with a targeted error. The flag exists for tooling that still consumes
the older layout; new bundles should use the default --format plugin. If
you only have a legacy artifact, repack it:
apm pack --format plugin --archiveDo not set --target. The flag is deprecated. Bundles are
target-agnostic: the consumer’s project decides which harness layouts
receive files at install time. APM records the value in pack.target as
informational metadata only and prints a deprecation warning.
Empty bundle warning. If apm pack reports “No deployed files found”,
your apm.lock.yaml has no deployed_files entries. Run apm install first
to populate it — apm pack packs the files your last install actually
deployed, not the raw .apm/ source tree.
Dry-run before sharing. Use apm pack --dry-run --verbose to see the
full file list (and any path remappings) without writing anything.
What to read next
Section titled “What to read next”- Deploy a local bundle — the consumer side of this hand-off.
- Publish to a marketplace — when a registry entry is a better fit than a bundle.
- Package anatomy — the file layout and schema reference.