| name | winapp-package |
| description | Package a Windows app as an MSIX installer for distribution or testing. Use when creating a Windows installer, packaging an Electron/Flutter/.NET/Rust/C++/Tauri app for Windows, building an MSIX, distributing a desktop app, packaging a console app or CLI tool, or adding MSIX packaging to a build script or CI/CD pipeline. |
When to use
Use this skill when:
- Creating an MSIX installer from a built app for distribution or testing
- Packaging any Windows app — GUI apps, console apps, CLI tools, services, or background processes
- Signing a package with a development or production certificate
- Bundling the Windows App SDK runtime for self-contained deployment
Prerequisites
Before packaging, you need:
- Built app output in a folder (e.g.,
bin/Release/, dist/, build/)
Package.appxmanifest — from winapp init or winapp manifest generate
- Certificate (optional) —
devcert.pfx from winapp cert generate for signing
Usage
Basic packaging (unsigned)
# Package from build output — manifest auto-detected from current dir or input folder
winapp package ./bin/Release
# Specify manifest location explicitly
winapp package ./dist --manifest ./Package.appxmanifest
Package and sign in one step
# Sign with existing certificate
winapp package ./bin/Release --cert ./devcert.pfx
# Custom certificate password
winapp package ./bin/Release --cert ./devcert.pfx --cert-password MyP@ssw0rd
Generate certificate + package in one step
# Auto-generate cert, sign, and package
winapp package ./bin/Release --generate-cert
# Also install the cert to trust it on this machine (requires admin)
winapp package ./bin/Release --generate-cert --install-cert
Self-contained deployment
# Bundle Windows App SDK runtime so users don't need it installed (must have winappsdk reference in the winapp.yaml or *.csproj)
winapp package ./bin/Release --cert ./devcert.pfx --self-contained
Custom output path and name
# Specify output file
winapp package ./dist --output ./releases/myapp-v1.0.msix --cert ./devcert.pfx
# Custom package name
winapp package ./dist --name "MyApp_1.0.0_x64" --cert ./devcert.pfx
What the command does
- Locates
Package.appxmanifest — looks in input folder, then current directory (or uses --manifest)
- Copies manifest + assets into a staging layout alongside your app files
- Discovers manifest-referenced files — any non-image file referenced in the manifest (e.g., AppExtension payloads like
manifest.json, config files) is automatically copied from the manifest directory or input folder if missing from staging
- Generates
resources.pri — Package Resource Index for UWP-style resource lookup (skip with --skip-pri)
- Runs
makeappx pack — creates the .msix package file
- Signs the package (if
--cert provided) — calls signtool with your certificate
Output: a .msix file that can be installed on Windows via double-click or Add-AppxPackage.
Installing the MSIX for testing
# Trust the dev certificate first (one-time, requires admin)
winapp cert install ./devcert.pfx
# Install the MSIX
Add-AppxPackage ./myapp.msix
# Uninstall if needed
Get-AppxPackage *myapp* | Remove-AppxPackage
Recommended workflow
- Build your app (
dotnet build, cmake --build, npm run make, etc.)
- Package —
winapp package <build-output> --cert ./devcert.pfx
- Trust cert (first time) —
winapp cert install ./devcert.pfx (admin)
- Install — double-click the
.msix or Add-AppxPackage ./myapp.msix
- Test the installed app from the Start menu
Advanced: External content catalog
For sparse packages with AllowExternalContent, you may need a code integrity catalog:
# Generate CodeIntegrityExternal.cat for external executables
winapp create-external-catalog "./bin/Release"
# Include subdirectories and specify output path
winapp create-external-catalog "./bin/Release" --recursive --output ./catalog/CodeIntegrityExternal.cat
Bundling multiple architectures
Create an MSIX bundle from multiple per-architecture build outputs:
# Create unsigned bundle for Store submission (x64 + arm64)
winapp package ./publish/x64 ./publish/arm64
# Create signed bundle for sideloading
winapp package ./publish/x64 ./publish/arm64 --cert ./devcert.pfx
# Self-contained bundle with Windows App SDK runtime per arch
winapp package ./publish/x64 ./publish/arm64 --self-contained --generate-cert
How it works: When multiple input folders are passed, winapp package:
- Detects the architecture of each folder's primary executable from its PE header
- Resolves a manifest for each slice (see below)
- Validates that all slices share the same Identity, Capabilities, and Dependencies
- Packs each folder into an intermediate unsigned
.msix
- Bundles them into a single
.msixbundle using makeappx bundle
- Signs only the bundle (not individual slices) — the signature covers all packages inside
Manifest resolution: Each slice needs a manifest. Resolution order:
--manifest <path> uses one manifest for all slices (architecture auto-stamped per folder)
- Per-folder
Package.appxmanifest if present in the input folder
- Fallback to
Package.appxmanifest in the current working directory
The ProcessorArchitecture is always force-set to the detected architecture per-slice. All other Identity fields must be consistent across slices.
Output: <Name>_<Version>_<arch1>_<arch2>.msixbundle (architectures sorted alphabetically).
Store submission: An unsigned bundle is valid for Store upload — Partner Center signs it with your reserved identity certificate. For sideloading, pass --cert or --generate-cert.
This hashes executables in the specified directories so Windows trusts them when running with sparse package identity.
CI/CD
GitHub Actions
Use the microsoft/setup-winapp action to install winapp on GitHub-hosted runners:
- uses: microsoft/setup-winapp@v1
- name: Package
run: winapp package ./dist --cert ${{ secrets.CERT_PATH }} --cert-password ${{ secrets.CERT_PASSWORD }} --quiet
Tips for CI/CD pipelines:
- Use
--quiet (or -q) to suppress progress output
- Use
--if-exists skip with winapp cert generate to avoid regenerating existing certificates
- Store your PFX certificate as a repository secret and decode it in CI
- Use
--use-defaults (or --no-prompt) with winapp init to avoid interactive prompts
Tips
- The
package command aliases to pack — both work identically
Package.appxmanifest Publisher must match the certificate publisher — use winapp cert generate --manifest to ensure they match
- Use
--skip-pri if your app doesn't use Windows resource loading (e.g., most Electron/Rust/C++ apps without UWP resources)
- For framework-specific packaging paths (Electron, .NET, Rust, etc.), see the
winapp-frameworks skill
- The
--executable flag overrides the entry point in the manifest — useful when your exe name differs from what's in Package.appxmanifest
- For production distribution, use a certificate from a trusted CA and add
--timestamp when signing with winapp sign
Sparse identity packages
To grant identity to an app distributed by an existing installer (not as MSIX), build an identity-only sparse package: pass a sparse appxmanifest.xml (one declaring <uap10:AllowExternalContent>true</uap10:AllowExternalContent> under <Properties>) to winapp pack instead of a folder.
# 1. Generate the sparse manifest for your exe (skips SDK install)
winapp init --exe ./bin/Release/MyApp.exe --sparse --use-defaults
# 2. Build & sign the identity-only .msix (just the manifest)
winapp pack ./sparse/appxmanifest.xml --cert ./devcert.pfx
# 3. Embed identity into the exe, then register in your installer
winapp embed-identity ./bin/Release/MyApp.exe
The .msix contains only the manifest — binaries and assets are resolved from the external content location at runtime via Add-AppxPackage -ExternalLocation. If you pack a folder whose manifest declares AllowExternalContent, winapp pack warns about any assets/binaries found. See the Sparse Packaging Guide.
Related skills
- Need a manifest first? See
winapp-manifest to generate Package.appxmanifest
- Need a certificate? See
winapp-signing for certificate generation and management
- Having issues? See
winapp-troubleshoot for a command selection flowchart and error solutions
Troubleshooting
| Error | Cause | Solution |
|---|
| "Package.appxmanifest not found" | No manifest in input folder or current dir | Run winapp init or winapp manifest generate first |
| "Publisher mismatch" | Cert publisher ≠ manifest publisher | Regenerate cert with winapp cert generate --manifest, or edit manifest |
| "Package installation failed" | Cert not trusted or stale package | Run winapp cert install ./devcert.pfx (admin), then Get-AppxPackage <name> | Remove-AppxPackage |
| "makeappx not found" | Build tools not downloaded | Run winapp update or winapp tool makeappx --help to trigger download |
CLI reference
Run winapp <command> --help for current command options, or winapp --cli-schema for the complete machine-readable command schema.