---
name: winapp-setup
description: Set up a Windows app project for MSIX packaging, Windows SDK access, or Windows API usage. Use when adding Windows support to an Electron, .NET, C++, Rust, Flutter, or Tauri project, or restoring SDK packages after cloning.
version: 0.3.2
---
## When to use
Use this skill when:
- **Adding Windows platform support** to an existing project (Electron, .NET, C++, Rust, Flutter, Tauri, etc.)
- **Cloning a repo** that already uses winapp and need to restore SDK packages
- **Updating SDK versions** to get the latest Windows SDK or Windows App SDK
## Prerequisites
Install the winapp CLI before running any commands:
```powershell
# Via winget (recommended for non-Node projects)
winget install Microsoft.WinAppCli --source winget
# Via npm (recommended for Electron/Node projects — includes Node.js SDK)
npm install --save-dev @microsoft/winappcli
```
You need an **existing app project** — `winapp init` does **not** create new projects, it adds Windows platform files to your existing codebase.
> **Already have a `Package.appxmanifest`?** .NET projects that already have a packaging manifest (e.g., WinUI 3 apps or projects with an existing MSIX packaging setup) likely **don't need `winapp init`**. Ensure your `.csproj` references the `Microsoft.WindowsAppSDK` NuGet package and has the right properties for packaged builds (e.g., `MSIX`). WinUI 3 apps created from Visual Studio templates are typically already fully configured — you can go straight to building and using `winapp run` or `winapp package`.
## Key concepts
**`Package.appxmanifest`** is the most important file winapp creates — it declares your app's identity, capabilities, and visual assets. Most winapp commands require it (`package`, `run`, `cert generate --manifest`).
**`winapp.yaml`** is only needed for SDK version management via `restore`/`update`. Projects that already reference Windows SDK packages (e.g., via NuGet in a `.csproj`) can use winapp commands without it.
**`.winapp/`** is the local folder where SDK packages and generated projections (e.g., CppWinRT headers) are stored. This folder is `.gitignore`d — team members recreate it via `winapp restore`.
## Usage
### Initialize a new winapp project
```powershell
# Interactive — prompts for app name, publisher, SDK channel, etc.
winapp init .
# Non-interactive — accepts all defaults (stable SDKs, current folder name as app name)
winapp init --use-defaults
# Skip SDK installation (just manifest + config)
winapp init --use-defaults --setup-sdks none
# Install preview SDKs instead of stable
winapp init --use-defaults --setup-sdks preview
```
After `init`, your project will contain:
- `Package.appxmanifest` — package identity and capabilities
- `Assets/` — default app icons (Square44x44Logo, Square150x150Logo, etc.)
- `winapp.yaml` — SDK version pinning for `restore`/`update`
- `.winapp/` — downloaded SDK packages and generated projections
- `.gitignore` update — excludes `.winapp/` and `devcert.pfx`
### Restore after cloning
```powershell
# Reinstall SDK packages from existing winapp.yaml (does not change versions)
winapp restore
# Restore into a specific directory
winapp restore ./my-project
```
Use `restore` when you clone a repo that already has `winapp.yaml` but no `.winapp/` folder.
### Update SDK versions
```powershell
# Check for and install latest stable SDK versions
winapp update
# Switch to preview channel
winapp update --setup-sdks preview
```
This updates `winapp.yaml` with the latest versions and reinstalls packages.
### Run and debug with identity
```powershell
# Register debug identity and launch app from build output
winapp run ./bin/Debug
# Launch with custom manifest and pass arguments to the app
winapp run ./dist --manifest ./out/Package.appxmanifest --args "--my-flag value"
# Pass arguments after -- to avoid escaping (equivalent to --args)
winapp run ./bin/Debug -- --my-flag value
# Register identity without launching (useful for attaching a debugger manually)
winapp run ./bin/Debug --no-launch
# Launch and capture OutputDebugString messages and crash diagnostics
# Note: prevents other debuggers (VS, VS Code) from attaching — use --no-launch if you need those instead
winapp run ./bin/Debug --debug-output
```
Use `winapp run` during iterative development — it creates a loose layout package, registers a debug identity, and launches the app in one step. For identity-only registration without loose layout, use `winapp create-debug-identity` instead.
#### Choosing between `run` and `create-debug-identity`
| | `winapp run` | `create-debug-identity` |
|---|---|---|
| **Registers** | Full loose layout package (entire folder) | Sparse package (single exe) |
| **App launch** | Winapp launches via AUMID or alias | You launch the exe yourself |
| **Simulates MSIX** | Yes — closest to production | No — identity only |
| **Files** | Copied to AppX layout dir | Exe stays in place |
| **Best for** | Most frameworks (.NET, C++, Rust, Flutter, Tauri) | Electron, or F5 startup debugging |
**Default to `winapp run`.** Use `create-debug-identity` when you need your IDE to launch and debug the exe directly (startup debugging), or when the exe is separate from your source (Electron).
For console apps, add `--with-alias` to preserve stdin/stdout in the current terminal.
> **`--debug-output` caveat:** Captures `OutputDebugString` and crash diagnostics (minidump + automatic analysis for both managed and native crashes) but attaches winapp as the debugger — you cannot also attach VS Code or WinDbg. Use `--no-launch` if you need your own debugger. Add `--symbols` to download PDB symbols for richer native crash analysis.
For full debugging scenarios and IDE setup, see the [Debugging Guide](https://github.com/microsoft/WinAppCli/blob/main/docs/debugging.md).
## Recommended workflow
1. **Initialize** — `winapp init --use-defaults` in your existing project
2. **Configure** — edit `Package.appxmanifest` to add capabilities your app needs (e.g., `runFullTrust`, `internetClient`)
3. **Build** — build your app as usual (dotnet build, cmake, npm run build, etc.)
4. **Run with identity** — `winapp run ./bin/Debug` to register identity and launch for debugging
5. **Package** — `winapp package ./bin/Release --cert ./devcert.pfx` to create MSIX
## Tips
- Use `--use-defaults` (alias: `--no-prompt`) in CI/CD pipelines and scripts to avoid interactive prompts
- If you only need `Package.appxmanifest` without SDK setup, use `winapp manifest generate` instead of `init`
- `winapp init` is idempotent for the config file — re-running it won't overwrite an existing `winapp.yaml` unless you use `--config-only`
- For Electron projects, prefer `npm install --save-dev @microsoft/winappcli` and use `npx winapp init` instead of the standalone CLI
## Related skills
- After setup, see `winapp-manifest` to customize your `Package.appxmanifest`
- Ready to package? See `winapp-package` to create an MSIX installer
- Need a certificate? See `winapp-signing` for certificate generation
- Not sure which command to use? See `winapp-troubleshoot` for a command selection flowchart
## Troubleshooting
| Error | Cause | Solution |
|-------|-------|----------|
| "winapp.yaml not found" | Running `restore`/`update` without config | Run `winapp init` first, or ensure you're in the right directory |
| "Directory not found" | Target directory doesn't exist | Create the directory first or check the path |
| SDK download fails | Network issue or firewall | Ensure internet access; check proxy settings |
| `init` prompts unexpectedly in CI | Missing `--use-defaults` flag | Add `--use-defaults` to skip all prompts |
## Command Reference
### `winapp init`
Start here for initializing a Windows app with required setup. Sets up everything needed for Windows app development: creates Package.appxmanifest with default assets, downloads Windows SDK and Windows App SDK packages, and generates projections. When SDK packages are managed (--setup-sdks stable/preview/experimental), also creates winapp.yaml to pin versions for 'restore'/'update'; with --setup-sdks none (e.g., for Rust/Tauri projects that bring their own SDK bindings), no winapp.yaml is created. Interactive by default (use --use-defaults to skip prompts). Use 'restore' instead if you cloned a repo that already has winapp.yaml. Use 'manifest generate' if you only need a manifest, or 'cert generate' if you need a development certificate for code signing.
#### Arguments
| Argument | Required | Description |
|----------|----------|-------------|
| `` | No | Base/root directory for the winapp workspace, for consumption or installation. |
#### Options
| Option | Description | Default |
|--------|-------------|---------|
| `--config-dir` | Directory to read/store configuration (default: current directory) | (none) |
| `--config-only` | Only handle configuration file operations (create if missing, validate if exists). Skip package installation and other workspace setup steps. | (none) |
| `--ignore-config` | Don't use configuration file for version management | (none) |
| `--no-gitignore` | Don't update .gitignore file | (none) |
| `--setup-sdks` | SDK installation mode: 'stable' (default), 'preview', 'experimental', or 'none' (skip SDK installation) | (none) |
| `--use-defaults` | Do not prompt, and use default of all prompts | (none) |
### `winapp restore`
Use after cloning a repo or when .winapp/ folder is missing. Reinstalls SDK packages from existing winapp.yaml without changing versions. Requires winapp.yaml (created by 'init'). To check for newer SDK versions, use 'update' instead.
#### Arguments
| Argument | Required | Description |
|----------|----------|-------------|
| `` | No | Base/root directory for the winapp workspace |
#### Options
| Option | Description | Default |
|--------|-------------|---------|
| `--config-dir` | Directory to read configuration from (default: current directory) | (none) |
### `winapp update`
Check for and install newer SDK versions. Updates winapp.yaml with latest versions and reinstalls packages. Requires existing winapp.yaml (created by 'init'). Use --setup-sdks preview for preview SDKs. To reinstall current versions without updating, use 'restore' instead.
#### Options
| Option | Description | Default |
|--------|-------------|---------|
| `--setup-sdks` | SDK installation mode: 'stable' (default), 'preview', 'experimental', or 'none' (skip SDK installation) | (none) |
### `winapp run`
Creates packaged layout, registers the Application, and launches the packaged application.
#### Arguments
| Argument | Required | Description |
|----------|----------|-------------|
| `` | Yes | Input folder containing the app to run |
| `` | No | Arguments to pass to the launched application. Provide after -- (e.g., winapp run . -- --flag value). |
#### Options
| Option | Description | Default |
|--------|-------------|---------|
| `--args` | Command-line arguments to pass to the application. Alternatively, use -- followed by arguments to avoid escaping (e.g., winapp run . -- --flag value). | (none) |
| `--clean` | Remove the existing package's application data (LocalState, settings, etc.) before re-deploying. By default, application data is preserved across re-deployments. | (none) |
| `--debug-output` | Capture OutputDebugString messages and first-chance exceptions from the launched application. Only one debugger can attach to a process at a time, so other debuggers (Visual Studio, VS Code) cannot be used simultaneously. Use --no-launch instead if you need to attach a different debugger. Cannot be combined with --no-launch or --json. | (none) |
| `--detach` | Launch the application and return immediately without waiting for it to exit. Useful for CI/automation where you need to interact with the app after launch. Prints the PID to stdout (or in JSON with --json). | (none) |
| `--executable` | Path to the executable relative to the input folder. Use to disambiguate when the manifest contains a $targetnametoken$ placeholder and multiple .exe files are present in the input folder. | (none) |
| `--json` | Format output as JSON | (none) |
| `--manifest` | Path to the Package.appxmanifest (default: auto-detect from input folder or current directory) | (none) |
| `--no-launch` | Only create the debug identity and register the package without launching the application | (none) |
| `--output-appx-directory` | Output directory for the loose layout package. If not specified, a directory named AppX inside the input-folder directory will be used. | (none) |
| `--symbols` | Download symbols from Microsoft Symbol Server for richer native crash analysis. Only used with --debug-output. First run downloads symbols and caches them locally; subsequent runs use the cache. | (none) |
| `--unregister-on-exit` | Unregister the development package after the application exits. Only removes packages registered in development mode. | (none) |
| `--with-alias` | Launch the app using its execution alias instead of AUMID activation. The app runs in the current terminal with inherited stdin/stdout/stderr. Requires a uap5:ExecutionAlias in the manifest. Use "winapp manifest add-alias" to add an execution alias to the manifest. | (none) |