npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@microsoft/winappcli

v0.7.1

Published

Windows App Development CLI and BuildTools utilities for Node.js native addon development

Readme

Windows App Development CLI

Status: Public Preview - The Windows App Development CLI is experimental and in active development. We'd love your feedback! Share your thoughts by creating an issue.

The Windows App Development CLI is a single command-line interface for managing Windows SDKs, packaging, generating app identity, manifests, certificates, and using build tools with any app framework. The NPM package extends the CLI with Electron specific tools. This CLI gives you access to:

  • Modern Windows APIs - Windows App SDK and Windows SDK with automatic setup and code generation
  • App Identity - Debug and test by adding app identity without full packaging in a snap
  • MSIX Packaging - App packaging with signing and Store readiness
  • Developer Tools - Manifests, certificates, assets, and build integration

Perfect for:

  • Electron/cross-platform developers wanting native Windows features or targeting Windows
  • Developers testing and deploying adding app identity for development or packaging for deployment
  • CI/CD pipelines automating Windows app builds

Get started

Checkout our getting started guide for step by step instructions: Electron guide.

📋 Usage

Install as a development dependency:

npm install @microsoft/winappcli --save-dev

once installed, call it with npx.

npx winapp --help

Commands Overview

Setup Commands:

  • new - Create a new WinUI app from an official Windows App SDK template
  • init - Initialize project with Windows SDK and App SDK
  • restore - Restore packages and dependencies (also runs the bindings step when the winapp.jsBindings namespace is declared in package.json)
  • update - Update packages and dependencies to latest versions

App Identity & Debugging:

Certificates & Signing:

  • cert - Generate and install development certificates
  • sign - Sign MSIX packages and executables
  • az-sign - Sign packages and executables with Azure Trusted Signing

Development Tools:

Node.js/Electron Specific:

The full CLI usage can be found here: Documentation

Programmatic API

The package also exports typed async functions for all CLI commands and utility helpers, so you can use them directly from TypeScript/JavaScript without spawning a CLI process:

import { init, packageApp, certGenerate } from '@microsoft/winappcli';

await init({ useDefaults: true });
await certGenerate({ install: true });
await packageApp({ inputFolder: './dist', cert: './devcert.pfx' });

Full programmatic API reference: NPM API Documentation

Note — the programmatic API runs the CLI non-interactively. The wrapper functions capture output and give the native process piped stdin, so commands that would normally prompt cannot do so. For azSign in particular this means you must pass either a metadataFile or a fully specified identity (subscription, resourceGroup, account, and profile), and a non-interactive Azure credential must already be available (for example AZURE_TENANT_ID/AZURE_CLIENT_ID/AZURE_CLIENT_SECRET, OIDC, a managed identity, or an existing az login session). Calls that would otherwise require a selection prompt or an interactive az login fail instead of prompting.

Cancelling a call

Every command option object accepts a signal. It cancels the whole native invocation and rejects with an AbortError:

const controller = new AbortController();
setTimeout(() => controller.abort(), 30_000);

await uiClick({ app: 'notepad', selector: 'btn-save-c3d4', signal: controller.signal });

On Windows the child is force-terminated, so the CLI's own cleanup may not run. That is safe — Windows releases the process's coordination handles and other winapp ui processes reclaim its queue entry — but if the abort lands after the command already had the desktop, UI side effects may already have happened, and aborting an active recording can leave partial output with no graceful MP4 finalization.

Driving UI from several workflows

winapp ui commands that touch the physical desktop always arbitrate for it — that is on by default and cannot be turned off, so two agents can never type into each other's windows.

What is opt-in is continuity. Pass the same workflowId to every call that belongs to one logical workflow and they keep the desktop reserved between invocations for a short idle grace, may overlap with each other (a recording and the clicks it is recording), and are never interleaved with another workflow's input:

const workflowId = crypto.randomUUID();

await uiClick({ app: 'notepad', selector: 'btn-file-a1b2', workflowId });
await uiSendKeys({ app: 'notepad', keys: 'hello', workflowId });

workflowId is applied to the spawned child only — the wrapper never mutates process.env, so it cannot leak into unrelated concurrent calls. Setting WINAPP_UI_WORKFLOW_ID in the environment works too and is inherited by every child.

Without a workflowId each call is a self-contained one-shot: it still waits its turn, but releases the desktop the moment it finishes. That also means a no-workflowId uiRecord blocks every other workflow for its whole duration — to record and click at the same time, give both calls the same workflowId.

See UI Automation → Coordinating concurrent UI workflows.

uiRecord still requires a finite positive durationSec: signal can only stop a recording by killing it, which does not produce a valid MP4.

🔧 Feedback

We are actively working on improving Node and Python support. These features are experimental and we are aware of several issues with these app types.

🧾 Samples

Electron sample: a default Electron Forge generated application + initialized a winapp project with appxmanifest, assets + native addon + C# addon + generates cert

Support

Need help or have questions about the Windows App Development CLI? Visit our Support Guide for information about our issue templates and triage process.

Trademarks

This project may contain trademarks or logos for projects, products, or services. Authorized use of Microsoft trademarks or logos is subject to and must follow Microsoft's Trademark & Brand Guidelines. Use of Microsoft trademarks or logos in modified versions of this project must not cause confusion or imply Microsoft sponsorship. Any use of third-party trademarks or logos are subject to those third-party's policies.