Pack & Distribute
Bundle your resolved APM dependencies into a portable artifact that can be distributed, cached, and consumed without APM, Python, or network access.
Why bundles?
Section titled “Why bundles?”Every CI job that runs apm install pays the same tax: install APM, authenticate against GitHub, clone N repositories, compile prompts. Multiply that across a matrix of jobs, nightly builds, and staging environments and the cost adds up fast.
A bundle removes all of that. You resolve once, pack the output, and distribute the artifact. Consumers extract it and get the exact files that apm install would have produced — no toolchain required.
Common motivations:
- CI cost reduction — resolve once, fan out to many jobs
- Air-gapped environments — no network access at deploy time
- Reproducibility — the bundle is a snapshot of exactly what was resolved
- Faster onboarding — new contributors get pre-built context without running install
- Audit trail — attach the bundle to a release for traceability
The pipeline
Section titled “The pipeline”The pack/distribute workflow fits between install and consumption:
apm install -> apm pack -> upload artifact -> download -> apm unpack (or tar xzf)The left side (install, pack) runs where APM is available. The right side (download, unpack) runs anywhere — a CI job, a dev container, a colleague’s laptop. The bundle is the boundary.
apm pack
Section titled “apm pack”Creates a self-contained bundle from installed dependencies. Reads the deployed_files manifest in apm.lock as the source of truth — it does not scan the disk.
# Default: apm format, target auto-detected from apm.ymlapm pack
# Filter by targetapm pack --target vscode # only .github/ filesapm pack --target claude # only .claude/ filesapm pack --target all # both targets
# Bundle formatapm pack --format plugin # valid plugin directory structure
# Produce a .tar.gz archiveapm pack --archive
# Custom output directory (default: ./build)apm pack -o ./dist/
# Preview without writingapm pack --dry-runOptions
Section titled “Options”| Flag | Default | Description |
|---|---|---|
--format | apm | Bundle format (apm or plugin) |
-t, --target | auto-detect | File filter: vscode, claude, all |
--archive | off | Produce .tar.gz instead of directory |
-o, --output | ./build | Output directory |
--dry-run | off | List files without writing |
Target filtering
Section titled “Target filtering”The target flag controls which deployed files are included based on path prefix:
| Target | Includes |
|---|---|
vscode | Paths starting with .github/ |
claude | Paths starting with .claude/ |
all | Both .github/ and .claude/ |
When no target is specified, APM auto-detects from the target field in apm.yml, falling back to all.
Bundle structure
Section titled “Bundle structure”The bundle mirrors the directory structure that apm install produces. It is not an intermediate format — extract it at the project root and the files land exactly where they belong.
Output is written to ./build/<name>-<version>/ by default, where name and version come from apm.yml.
VS Code / Copilot target
Section titled “VS Code / Copilot target”build/my-project-1.0.0/ .github/ prompts/ design-review.prompt.md code-quality.prompt.md agents/ architect.md skills/ security-scan/ skill.md apm.lock # enriched copy (see below)Claude target
Section titled “Claude target”build/my-project-1.0.0/ .claude/ commands/ review.md debug.md skills/ code-analysis/ skill.md apm.lockAll targets
Section titled “All targets”build/my-project-1.0.0/ .github/ prompts/ ... agents/ ... .claude/ commands/ ... apm.lockThe bundle is self-describing: its apm.lock lists every file it contains and the dependency graph that produced them.
Lockfile enrichment
Section titled “Lockfile enrichment”The bundle includes a copy of apm.lock enriched with a pack: section. The project’s own apm.lock is never modified.
pack: format: apm target: vscode packed_at: '2025-07-14T09:30:00+00:00'lockfile_version: '1'generated_at: '2025-07-14T09:28:00+00:00'apm_version: '0.5.0'dependencies: - repo_url: microsoft/apm-sample-package host: github.com resolved_commit: a1b2c3d4 resolved_ref: main version: 1.0.0 depth: 1 package_type: apm deployed_files: - .github/prompts/design-review.prompt.md - .github/agents/architect.mdThe pack: section records:
- format — the bundle format used (
apmorplugin) - target — the effective target filter applied
- packed_at — UTC timestamp of when the bundle was created
This metadata lets consumers verify what they received and trace it back to a build.
apm unpack
Section titled “apm unpack”Extracts an APM bundle into a project directory. Accepts both .tar.gz archives and unpacked bundle directories.
# Extract and verifyapm unpack ./build/my-project-1.0.0.tar.gz
# Extract to a specific directoryapm unpack ./build/my-project-1.0.0.tar.gz -o ./
# Skip integrity checkapm unpack --skip-verify ./build/my-project-1.0.0.tar.gz
# Preview without writingapm unpack ./build/my-project-1.0.0.tar.gz --dry-runOptions
Section titled “Options”| Flag | Default | Description |
|---|---|---|
-o, --output | . (current dir) | Target project directory |
--skip-verify | off | Skip completeness check against lockfile |
--dry-run | off | List files without writing |
Behavior
Section titled “Behavior”- Additive-only:
unpackwrites files listed in the bundle’s lockfile. It never deletes existing files in the target directory. - Overwrite on conflict: if a file already exists at the target path, the bundle file wins.
- Verification: by default,
unpackchecks that every path in the bundle’sdeployed_filesmanifest exists in the bundle before extracting. Pass--skip-verifyto skip this check for partial bundles. - Lockfile not copied: the bundle’s enriched
apm.lockis metadata for verification only — it is not written to the output directory.
Consumption scenarios
Section titled “Consumption scenarios”CI: cross-job artifact sharing
Section titled “CI: cross-job artifact sharing”Resolve once in a setup job, fan out to N consumer jobs. No APM installation in downstream jobs.
jobs: setup: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: microsoft/apm-action@v1 - run: apm pack --archive - uses: actions/upload-artifact@v4 with: name: apm-bundle path: build/*.tar.gz
test: needs: setup runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/download-artifact@v4 with: name: apm-bundle path: ./bundle - run: tar xzf ./bundle/*.tar.gz -C . # Prompts and agents are now in place — no APM neededAgentic workflows
Section titled “Agentic workflows”GitHub’s agentic workflow runners operate in sandboxed environments with no network access. Pre-pack the bundle and include it as a workflow artifact so the agent has full context from the start.
Release audit trail
Section titled “Release audit trail”Attach the bundle as a release artifact. Anyone auditing the release can inspect exactly which prompts, agents, and skills shipped with that version.
apm pack --archive -o ./release-artifacts/gh release upload v1.2.0 ./release-artifacts/*.tar.gzDev Containers and Codespaces
Section titled “Dev Containers and Codespaces”Include a pre-built bundle in the dev container image or restore it during onCreateCommand. New contributors get working AI context without running apm install.
{ "onCreateCommand": "tar xzf .devcontainer/apm-bundle.tar.gz -C ."}Org-wide distribution
Section titled “Org-wide distribution”A central platform team maintains the canonical prompt library. Monthly, they run apm install && apm pack --archive, publish the bundle to an internal artifact registry, and downstream repos pull it during CI or onboarding.
apm-action integration
Section titled “apm-action integration”The official apm-action supports pack and restore as first-class modes.
Pack mode
Section titled “Pack mode”Generate a bundle as part of a GitHub Actions workflow:
- uses: microsoft/apm-action@v1 with: pack: trueRestore mode
Section titled “Restore mode”Consume a bundle without installing APM. The action extracts the archive directly:
- uses: microsoft/apm-action@v1 with: bundle: ./path/to/bundle.tar.gzNo APM binary, no Python runtime, no network calls. The action handles extraction and verification internally.
Prerequisites
Section titled “Prerequisites”apm pack requires two things:
apm.lock— the resolved lockfile produced byapm install. Pack reads thedeployed_filesmanifest from this file to know what to include.- Installed files on disk — the actual files referenced in
deployed_filesmust exist at their expected paths. Pack verifies this and fails with a clear error if files are missing.
The typical sequence is:
apm install # resolve dependencies and deploy filesapm pack # bundle the deployed filesPack reads from the lockfile, not from a disk scan. If a file exists on disk but is not listed in apm.lock, it will not be included. If a file is listed in apm.lock but missing from disk, pack will fail and prompt you to re-run apm install.
Troubleshooting
Section titled “Troubleshooting””apm.lock not found”
Section titled “”apm.lock not found””Pack requires a lockfile. Run apm install first to resolve dependencies and generate apm.lock.
”deployed files are missing on disk”
Section titled “”deployed files are missing on disk””The lockfile references files that do not exist. This usually means dependencies were installed but the files were deleted. Run apm install to restore them.
”bundle verification failed”
Section titled “”bundle verification failed””During unpack, verification found files listed in the bundle’s lockfile that are missing from the bundle itself. The bundle may have been created from a partial install or corrupted during transfer. Re-pack from a clean install, or pass --skip-verify if you know the bundle is intentionally partial.
Empty bundle
Section titled “Empty bundle”If apm pack produces zero files, check that your dependencies have deployed_files entries in apm.lock. This can happen if apm install completed but no integration files were deployed (e.g., the package has no prompts or agents for the active target).