Deploy a local bundle
You have a bundle on disk — a directory or .zip someone handed you (or a
legacy .tar.gz), or the output of apm pack --format plugin. Drop it into a
project with one command:
apm install ./path/to/bundleapm install ./dist/my-pkg-1.0.0.zipThis is a sibling flow to Install packages. Instead
of declaring a dependency in apm.yml and resolving it from a registry, you
deploy a self-contained bundle directly. apm.yml is not modified —
the install is imperative, like dpkg -i next to apt install.
What counts as a bundle
Section titled “What counts as a bundle”A plugin-format bundle is a directory, zip archive, or legacy gzipped tarball
with a plugin.json at the root and primitive folders alongside it:
my-bundle/+-- plugin.json+-- agents/+-- skills/+-- commands/+-- hooks/+-- apm.lock.yaml # optional: bundle integrity manifestplugin.json requires only a name. APM also recognises plugin.json
under .github/plugin/, .claude-plugin/, or .cursor-plugin/. For the
full schema see Package anatomy.
The optional apm.lock.yaml carries pack.bundle_files — a SHA-256
manifest written by apm pack --format plugin. When present, APM verifies
every listed file before deploying. When absent, older bundles still install
with a warning unless policy requires hashes. With
security.integrity.require_hashes: true, APM fails closed before deploy.
How the install works
Section titled “How the install works”$ apm install ./dist/my-pkg-1.0.0.zip --target copilot[>] Installing local bundle from ./dist/my-pkg-1.0.0.zip[+] Bundle integrity verified[+] Deployed 7 files to .github/Steps APM runs:
- Detect. Path exists and contains
plugin.jsonat the bundle root (zip archives and legacy tarballs are extracted to a temp directory first). - Apply cached policy. Resolve the actual targets, then apply any cached
org policy to bundle MCP entries and targets before files are written.
Bundle install never fetches policy from the network.
--no-policyskips this local gate for one invocation. - Verify integrity. Hash every file listed in
pack.bundle_files; reject any symlink, hash mismatch, or unlisted file. - Deploy. Map
agents/,skills/,commands/,hooks/into the harness layout for each--targetyou passed. - Record. Write a lockfile entry under the project’s
apm.lock.yamlso drift detection can audit the deployed files later.
apm.yml is never touched. Re-running the same command re-deploys (use
--force to overwrite locally-edited files).
For centrally governed installs, warm the policy cache before distributing an
offline bundle. See APM policy.
Flags that apply
Section titled “Flags that apply”Most apm install flags target the registry/resolver pipeline and are
rejected with a single error when used with a local bundle. The flags
that do work:
| Flag | Use |
|---|---|
--target, -t | Pick which harness layouts receive files. |
--global, -g | Deploy to ~/.apm/ instead of the current project. |
--force | Overwrite locally-edited files on collision. |
--dry-run | Show what would be deployed; write nothing. |
--no-policy | Skip policy preflight for this invocation only. |
--verbose, -v | Print per-file deploy details. |
--as ALIAS | Override the display label in logs (local-bundle only). |
Flags like --update, --only, --dev, --mcp, --registry, and
--allow-insecure are not meaningful here — the imperative deploy path
does not run the dependency resolver or registry lookup that those flags
configure. APM rejects them up front with one consolidated error.
For the full flag list see the apm install reference.
Targets
Section titled “Targets”Pass --target to scope the deploy. Without it APM auto-detects from the
current project. If the bundle was packed for targets you are not
installing into, APM prints a warning naming the missing targets and
proceeds with what it can deploy.
A bundle packed with pack.target: all is target-agnostic and installs
cleanly into any harness layout.
Legacy --format apm bundles are rejected
Section titled “Legacy --format apm bundles are rejected”Bundles produced by the older apm pack --format apm carry an
apm.lock.yaml at their root but no plugin.json. apm install
rejects these with a targeted error:
'./dist/my-pkg-0.1.0.tar.gz' was packed with '--format apm' (legacyformat). 'apm install <bundle>' requires the plugin format. Repack with'apm pack --format plugin --archive', or use 'apm unpack' to deploy thelegacy bundle.Two ways forward:
- Repack. If you own the bundle, run
apm pack --format plugin --archiveand install the new artifact. - Unpack. If you only have the legacy artifact, use
apm unpack <bundle>to extract it.apm unpackis deprecated and will be removed in a future release; prefer repacking when you can.
A plain directory without plugin.json is not treated as a bundle at all.
APM falls through to the dependency resolver and treats the path as a
local-path dependency — a different flow covered in Install packages.
What to read next
Section titled “What to read next”- Install packages — the manifest-driven flow.
- Drift and secure by default — audit what a bundle deployed.
- Package anatomy — the file layout reference.