Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
1ac749b
Adds winapp run command.
azchohfi Mar 3, 2026
40fb57d
Merge branch 'main' into alzollin/run
nmetulev Mar 3, 2026
e39f53a
PR feedback.
azchohfi Mar 4, 2026
1519007
Minor fix.
azchohfi Mar 4, 2026
4bbabed
Merge branch 'main' into alzollin/run
azchohfi Mar 4, 2026
347d336
Fixed tests.
azchohfi Mar 4, 2026
e249d1f
Merge remote-tracking branch 'refs/remotes/origin/alzollin/run' into …
azchohfi Mar 4, 2026
d9dbe81
Merge branch 'main' into alzollin/run
azchohfi Mar 4, 2026
fd66257
Fixed build.
azchohfi Mar 5, 2026
dfdc1eb
Merge branch 'main' into alzollin/run
azchohfi Mar 5, 2026
c7ef301
Update artifact upload actions to v7 and add NuGet package handling i…
azchohfi Mar 5, 2026
6df0327
Merge main into alzollin/run and update skill command mapping
nmetulev Mar 5, 2026
faab579
updating skills
nmetulev Mar 5, 2026
1ff44b6
Document winapp run in README, agent, and setup skill
nmetulev Mar 5, 2026
a142455
Differentiate winapp run from create-debug-identity in docs
nmetulev Mar 5, 2026
f348e74
Document NuGet package for automatic dotnet run support
nmetulev Mar 5, 2026
c1cf450
Clarify that winapp init auto-adds the WinApp NuGet package
nmetulev Mar 5, 2026
0a43dec
Migrate .NET samples from create-debug-identity to WinApp NuGet package
nmetulev Mar 5, 2026
554b58b
updating wpf sample
nmetulev Mar 5, 2026
41102a5
skills updated
nmetulev Mar 5, 2026
f0a35e0
updates skills
nmetulev Mar 5, 2026
45345e6
Merge branch 'main' into alzollin/run
nmetulev Mar 6, 2026
f069b93
(winapp run) Adding --with-alias (#346)
nmetulev Mar 6, 2026
71f65a9
Merge branch 'main' into alzollin/run
nmetulev Mar 6, 2026
f8fc5c9
Merge branch 'main' into alzollin/run
azchohfi Mar 6, 2026
17a8edf
fixed duplicate function
nmetulev Mar 7, 2026
4675c12
winapp run --debug-output (#350)
nmetulev Mar 7, 2026
7ade706
adding clear
nmetulev Mar 7, 2026
65a69af
Merge branch 'alzollin/run' of https://github.com/microsoft/winappcli…
nmetulev Mar 7, 2026
3f0ae2b
remove nuget.config
nmetulev Mar 7, 2026
4d728ad
refactor MsixService
nmetulev Mar 7, 2026
5b3f954
Improve winapp run: incremental copy, direct invocation, and XML han…
nmetulev Mar 12, 2026
77ba783
updated samples and skills for winapp run and guidance on when to use…
nmetulev Mar 13, 2026
2d2f90a
refactor to ensure pack, run, and debug identity use the same code pa…
nmetulev Mar 13, 2026
b4606b9
Merge branch 'main' into alzollin/run
nmetulev Mar 13, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .gitattributes
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
# Auto detect text files and perform LF normalization
* text=auto

# Generated LLM documentation - always use LF to match what generate-llm-docs.ps1 writes
# Generated files - always use LF to match what generate-llm-docs.ps1 writes
docs/cli-schema.json text eol=lf
.github/plugin/plugin.json text eol=lf
.github/plugin/skills/** text eol=lf
docs/npm-usage.md text eol=lf
src/winapp-npm/src/winapp-commands.ts text eol=lf

# Shell scripts should use LF
*.sh text eol=lf
Expand Down
45 changes: 35 additions & 10 deletions .github/plugin/agents/winapp.agent.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,10 @@ Does the project already have an appxmanifest.xml?
│ └─ winapp package <build-output-dir>
│ (add --cert ./devcert.pfx to sign in one step)
├─ Need package identity for debugging Windows APIs?
│ └─ winapp create-debug-identity <exe-path>
│ ├─ Is the exe in the same folder as your build output? (most frameworks)
│ │ └─ winapp run <build-output-dir> (registers loose layout + launches)
│ └─ Is the exe separate from your app code? (Electron, sparse package testing)
│ └─ winapp create-debug-identity <exe-path> (registers sparse package)
├─ Need to sign an existing MSIX or exe?
│ └─ winapp sign <file> <cert>
└─ Need to run a Windows SDK tool directly (makeappx, signtool, makepri)?
Expand All @@ -54,7 +57,7 @@ Does the project already have an appxmanifest.xml?

4. **`cert install` requires administrator elevation.** Always warn the user that `winapp cert install` must be run in an elevated (administrator) terminal. Without this, the certificate won't be trusted and MSIX installation will fail.

5. **Re-run `create-debug-identity` after manifest or asset changes.** The sparse package registration uses the manifest and assets at the time it was created. Any changes require re-running the command.
5. **Re-run `winapp run` or `create-debug-identity` after manifest or asset changes.** Both commands use the manifest and assets at registration time. Any changes require re-running the command. Use `winapp run` for most frameworks; use `create-debug-identity` only when the exe lives outside your build output folder (e.g., Electron) or when testing sparse package scenarios specifically.

6. **Use `--use-defaults` for non-interactive/CI scenarios.** When running `winapp init` in scripts or CI pipelines, pass `--use-defaults` (alias: `--no-prompt`) to skip interactive prompts and use sensible defaults.

Expand Down Expand Up @@ -100,14 +103,26 @@ Does the project already have an appxmanifest.xml?
**Requires:** Built app output directory + `appxmanifest.xml`

### `winapp create-debug-identity [entrypoint]`
**Purpose:** Register a sparse package with Windows so your app gets package identity during development without creating a full MSIX.
**When to use:** When you need Windows APIs that require package identity (push notifications, background tasks, share target, startup tasks) during development/debugging.
**Purpose:** Register a *sparse package* with Windows so an existing exe gets package identity without creating a full MSIX. The exe stays in its original location — Windows uses `Add-AppxPackage -ExternalLocation` to associate identity with it.
**When to use:** When the exe is **separate from your app code** (e.g., `electron.exe` in `node_modules`), or when you specifically need to test sparse package behavior. For most frameworks where the exe is in your build output folder, prefer `winapp run` instead.
**Key options:**
- `--manifest <path>` — path to `appxmanifest.xml`
- `--keep-identity` — don't append `.debug` to package name
- `--no-install` — create but don't register the package
**Requires:** `appxmanifest.xml` + path to your built `.exe`

### `winapp run <input-folder>`
**Purpose:** Create a loose layout package from a build output folder, register it with Windows via `Add-AppxPackage`, and launch the app — simulating a full MSIX install for debugging.
**When to use:** The **preferred command** for iterative development and debugging with package identity. Use this whenever your exe lives inside the build output folder (most .NET, C++, Rust, Flutter, Tauri projects).
**Key options:**
- `--manifest <path>` — path to `appxmanifest.xml` (default: auto-detect)
- `--args <string>` — command-line arguments to pass to the app
- `--no-launch` — register the package without launching
- `--with-alias` — launch via execution alias (console apps run in current terminal)
- `--debug-output` — capture `OutputDebugString` messages and first-chance exceptions (prevents other debuggers like VS/VS Code from attaching)
- `--output-appx-directory <path>` — custom output directory for loose layout
**Requires:** Built app output directory + `appxmanifest.xml`

### `winapp cert generate`
**Purpose:** Create a self-signed PFX certificate for local testing.
**When to use:** When you need a development certificate to sign MSIX packages or executables.
Expand Down Expand Up @@ -175,7 +190,8 @@ Does the project already have an appxmanifest.xml?

### .NET (WPF, WinForms, Console)
- **Setup:** `winapp init --use-defaults`
- **Package:** `dotnet build`, then `winapp package bin\Release\net10.0-windows --cert devcert.pfx`
- **Run with identity:** `winapp init` auto-adds the `Microsoft.Windows.SDK.BuildTools.WinApp` NuGet package, so just `dotnet run` registers a loose layout package and launches with identity. Without the NuGet package, use `dotnet build` then `winapp run ./bin/Debug`.
- **Package:** `dotnet build -c Release`, then `winapp package bin\Release\net10.0-windows --cert devcert.pfx`
- No native addons needed — .NET has direct Windows API access via `Microsoft.Windows.SDK.NET.Ref`
- Guide: https://github.com/microsoft/WinAppCli/blob/main/docs/guides/dotnet.md

Expand Down Expand Up @@ -215,12 +231,20 @@ winapp package ./dist --cert ./devcert.pfx # Package and sign
winapp cert install ./devcert.pfx # Trust cert (admin required, one-time)
```

### Add package identity for debugging
### Run and debug with package identity
```bash
winapp init . # If not already set up
# ... build your app ...
winapp run ./bin/Debug # Register loose layout package + launch
# Your app runs as if MSIX-installed, with full package identity
```

### Add sparse package identity (Electron or separate exe)
```bash
winapp init . # If not already set up
# ... build your app ...
winapp create-debug-identity ./myapp.exe # Register sparse package
# Your app now has identity for push notifications, share target, etc.
winapp create-debug-identity ./myapp.exe # Register sparse package for exe
# Launch your exe normally — it now has package identity
```

### Clone and build existing project
Expand Down Expand Up @@ -257,5 +281,6 @@ When the user encounters an error, check these common causes:
- **`Assets/`** — Icon and tile images referenced by the manifest. Generated by `init` or `manifest generate`.
- **`.winapp/`** — Local directory with downloaded SDK packages, generated headers, and libs. Gitignored.
- **`devcert.pfx`** — Self-signed development certificate for local testing. Never use in production.
- **Sparse package** — A package registration that gives a desktop app package identity without full MSIX deployment. Used by `create-debug-identity`.
- **Package identity** — A Windows concept that enables certain APIs (notifications, background tasks, share target). Obtained either via full MSIX packaging or sparse package registration.
- **Sparse package** — A lightweight package registration that gives a desktop app package identity without full MSIX deployment. The exe stays in its original location; Windows associates identity with it via `Add-AppxPackage -ExternalLocation`. Used by `create-debug-identity`. Best for scenarios where the exe is separate from the app code (e.g., Electron).
- **Loose layout package** — A folder-based package registered with Windows via `Add-AppxPackage`, simulating a full MSIX install without creating an `.msix` file. Used by `winapp run`. The preferred approach for most frameworks during development.
- **Package identity** — A Windows concept that enables certain APIs (notifications, background tasks, share target). Obtained via full MSIX packaging, loose layout registration (`winapp run`), or sparse package registration (`create-debug-identity`).
27 changes: 26 additions & 1 deletion .github/plugin/skills/winapp-cli/frameworks/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,18 @@ Additional Electron guides:
- Projects with NuGet references to `Microsoft.Windows.SDK.BuildTools` or `Microsoft.WindowsAppSDK` **don't need `winapp.yaml`** — winapp auto-detects SDK versions from the `.csproj`
- The key prerequisite is `appxmanifest.xml`, not `winapp.yaml`
- No native addon step needed — unlike Electron, .NET can call Windows APIs directly
- `winapp init` automatically adds the `Microsoft.Windows.SDK.BuildTools.WinApp` NuGet package, enabling `dotnet run` with automatic identity registration

Quick start:
```powershell
winapp init --use-defaults
dotnet run
```

If not using the NuGet package, build and run manually:
```powershell
dotnet build
winapp create-debug-identity ./bin/Debug/net10.0-windows/myapp.exe
winapp run ./bin/Debug
```

### C++ (CMake, MSBuild)
Expand All @@ -80,6 +86,25 @@ C++ projects use winapp primarily for SDK projections (CppWinRT headers) and pac
- Use winapp specifically for **MSIX distribution** and package identity features
- winapp adds capabilities beyond what Tauri's built-in bundler provides (identity, sparse packages, Windows API access)

## Debugging by framework

| Framework | Recommended command | Notes |
|-----------|-------------------|-------|
| **.NET** | `winapp run .\bin\Debug` | GUI apps launch directly; console apps need `--with-alias` |
| **C++** | `winapp run .\build\Debug --with-alias` | Console apps need `--with-alias` + `uap5:ExecutionAlias` in manifest |
| **Rust** | `winapp run .\target\debug --with-alias` | Console apps need `--with-alias` + `uap5:ExecutionAlias` in manifest |
| **Flutter** | `winapp run .\build\windows\x64\runner\Debug` | GUI app — plain `winapp run` works |
| **Tauri** | `winapp run .\dist` | Stage exe to `dist/` first (avoids copying entire `target/` tree); GUI app |
| **Electron** | `npx winapp node add-electron-debug-identity` | Uses Electron-specific identity registration; `winapp run` is **not** recommended for Electron |

**Key rules:**
- **GUI apps** (Flutter, Tauri, WPF): use `winapp run <build-output>` — launches via AUMID activation
- **Console apps** (C++, Rust, .NET console): use `winapp run <build-output> --with-alias` — launches via execution alias to preserve stdin/stdout. Requires `uap5:ExecutionAlias` in `appxmanifest.xml`
- **Electron**: different mechanism — uses `npx winapp node add-electron-debug-identity` because `electron.exe` is in `node_modules/`, not your build output
- **Startup debugging (any framework)**: use `winapp create-debug-identity <exe>` so your IDE can F5-launch the exe with identity from the first instruction

For full debugging scenarios and IDE setup, see the [Debugging Guide](https://github.com/microsoft/WinAppCli/blob/main/docs/debugging.md).

## Related skills
- **Setup**: `winapp-setup` — initial project setup with `winapp init`
- **Manifest**: `winapp-manifest` — creating and customizing `appxmanifest.xml`
Expand Down
55 changes: 51 additions & 4 deletions .github/plugin/skills/winapp-cli/identity/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@ version: 0.2.1
## When to use

Use this skill when:
- **Debugging Windows APIs** that require package identity (push notifications, background tasks, share target, startup tasks, etc.)
- **Testing identity-dependent features** without creating and installing a full MSIX package
- **Registering a sparse package** with Windows for development
- **The exe is separate from your app code** — e.g., Electron apps where `electron.exe` is in `node_modules`, not your build output
- **Testing sparse package behavior** specifically — `AllowExternalContent`, `TrustedLaunch`, etc.
- **Registering identity without copying files** — `create-debug-identity` leaves the exe in place

> **Prefer `winapp run` for most frameworks.** If your exe is inside your build output folder (.NET, C++, Rust, Flutter, Tauri), use `winapp run <build-output>` instead — it registers a full loose layout package and launches the app, simulating an MSIX install. Use `create-debug-identity` only when `winapp run` doesn't fit your scenario.

## Prerequisites

Expand All @@ -26,7 +28,7 @@ Windows package identity enables your app to use restricted APIs and OS integrat
- **Windows AI APIs** (Phi Silica, OCR, etc.)
- **File type associations** registered properly in Settings

A standard `.exe` (from `dotnet build`, `cmake`, etc.) does **not** have identity. `create-debug-identity` registers a *sparse package* with Windows, giving your exe identity without packaging it into an MSIX.
A standard `.exe` (from `dotnet build`, `cmake`, etc.) does **not** have identity. `create-debug-identity` registers a *sparse package* with Windows — the exe stays in its original location and Windows associates identity with it via `Add-AppxPackage -ExternalLocation`. This is different from `winapp run`, which copies files into a loose layout package.

## Usage

Expand Down Expand Up @@ -81,6 +83,51 @@ After running, launch your exe normally — Windows will recognize it as having
- If you have both a debug identity and an installed MSIX, they may conflict — use `--keep-identity` carefully
- For Electron apps, use `npx winapp node add-electron-debug-identity` instead (handles Electron-specific paths)

## Debugging: `winapp run` vs `create-debug-identity`

| | `winapp run` | `create-debug-identity` |
|---|---|---|
| **What it registers** | Full loose layout package (entire folder) | Sparse package (single exe) |
| **How the app launches** | Launched by winapp (AUMID activation or execution alias) | You launch the exe yourself (command line, IDE, etc.) |
| **Simulates MSIX install** | Yes — closest to production behavior | No — sparse identity only |
| **Files stay in place** | Copied to an AppX layout directory | Yes — exe stays at its original path |
| **Debugger-friendly** | Attach to PID after launch, or use `--no-launch` then launch via alias | Launch directly from your IDE's debugger — the exe has identity regardless |
| **Console app support** | `--with-alias` keeps stdin/stdout in terminal | Run exe directly in terminal |
| **Best for** | Most frameworks (.NET, C++, Rust, Flutter, Tauri) | Electron, or when you need full IDE debugger control (F5 startup debugging) |

### When to use which

**Default to `winapp run`** for most development — it simulates a real MSIX install with full identity, capabilities, and file associations:

```powershell
winapp run .\build\output # GUI apps
winapp run .\build\output --with-alias # console apps (preserves stdin/stdout)
```

**Use `create-debug-identity` when:**
- **Debugging startup code** — your IDE launches + debugs the exe directly; identity is attached from the first instruction
- **Exe is separate from build output** — e.g., Electron where `electron.exe` is in `node_modules/`
- **Testing sparse package behavior** — `AllowExternalContent`, `TrustedLaunch`

```powershell
winapp create-debug-identity .\bin\Debug\myapp.exe
# Now launch any way you like — F5, terminal, script — the exe has identity
```

### Common debugging scenarios

| Scenario | Command | Notes |
|----------|---------|-------|
| **Just run with identity** | `winapp run .\build\Debug` | Simplest workflow; add `--with-alias` for console apps |
| **Attach debugger to running app** | `winapp run .\build\Debug`, then attach to PID | Misses startup code |
| **Register identity, launch via AUMID** | `winapp run .\build\Debug --no-launch` | Launch with `start shell:AppsFolder\<AUMID>` or the execution alias (not the exe directly) |
| **F5 startup debugging** | `winapp create-debug-identity .\bin\myapp.exe` | IDE controls process from first instruction; best for debugging activation/startup code |
| **Capture debug output** | `winapp run .\build\Debug --debug-output` | Captures `OutputDebugString`; **blocks other debuggers** (one debugger per process) |

> **Using Visual Studio with a packaging project?** VS already handles identity, AUMID activation, and debugger attachment from F5. These workflows are most useful for VS Code, terminal-based development, and frameworks VS doesn't natively package (Rust, Flutter, Tauri, Electron, C++).

For full details including IDE setup examples, see the [Debugging Guide](https://github.com/microsoft/WinAppCli/blob/main/docs/debugging.md).

## Related skills
- Need a manifest? See `winapp-manifest` to generate `appxmanifest.xml`
- Need a certificate? See `winapp-signing` — a trusted cert is required for identity registration
Expand Down
33 changes: 32 additions & 1 deletion .github/plugin/skills/winapp-cli/manifest/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,25 @@ winapp manifest update-assets ./my-logo.png --manifest ./path/to/appxmanifest.xm

The source image should be at least 400x400 pixels (PNG recommended). The command reads the manifest to determine which asset sizes are needed and generates them all.

### Add an execution alias

Execution aliases let users launch the app by typing its name in a terminal (e.g. `myapp`).

```powershell
# Add alias inferred from the Executable attribute in the manifest
winapp manifest add-alias

# Specify the alias name explicitly
winapp manifest add-alias --name myapp

# Target a specific manifest file
winapp manifest add-alias --manifest ./path/to/appxmanifest.xml
```

This adds a `uap5:AppExecutionAlias` extension to the manifest. If the alias already exists, the command reports it and exits successfully.

> **When combined with `winapp run --with-alias`** or the `WinAppRunUseExecutionAlias` MSBuild property, this enables apps to run in the current terminal with inherited stdin/stdout/stderr instead of opening a new window.

## Manifest structure overview

A typical `appxmanifest.xml` looks like:
Expand Down Expand Up @@ -168,4 +187,16 @@ Generate new assets for images referenced in an appxmanifest.xml from a single s
<!-- auto-generated from cli-schema.json -->
| Option | Description | Default |
|--------|-------------|---------|
| `--manifest` | Path to AppxManifest.xml file (default: search current directory) | (none) |
| `--manifest` | Path to AppxManifest.xml or Package.appxmanifest file (default: search current directory) | (none) |

### `winapp manifest add-alias`

Add an execution alias (uap5:AppExecutionAlias) to an appxmanifest.xml. This allows launching the packaged app from the command line by typing the alias name. By default, the alias is inferred from the Executable attribute (e.g. $targetnametoken$.exe becomes $targetnametoken$.exe alias).

#### Options
<!-- auto-generated from cli-schema.json -->
| Option | Description | Default |
|--------|-------------|---------|
| `--app-id` | Application Id to add the alias to (default: first Application element) | (none) |
| `--manifest` | Path to AppxManifest.xml or Package.appxmanifest file (default: search current directory) | (none) |
| `--name` | Alias name (e.g. 'myapp.exe'). Default: inferred from the Executable attribute in the manifest. | (none) |
Loading
Loading