# Technical Documentation: coreybutler/nvm-windows

> ℹ️ **Provenance:** Multi-Tier Ingestion · [CodeWiki Reference](https://codewiki.google/github.com/coreybutler/nvm-windows)

### Overview (`README.md`)

<a href="https://trendshift.io/repositories/4201" target="_blank"><img src="https://trendshift.io/api/badge/repositories/4201" alt="nvm-windows | Trendshift" style="width: 250px; height: 55px;" width="250" height="55"/></a>

# <sub><img src="https://github.com/nvm-windows.png?s=50" width="32" align="bottom" /></sub> NVM for Windows

The <a href="https://docs.microsoft.com/en-us/windows/nodejs/setup-on-windows">Microsoft</a>/<a href="https://cloud.google.com/nodejs/docs/setup#installing_nvm">Google</a> recommended Node.js version manager for millions of Windows developers. 

> [!IMPORTANT]
> **You may already have NVM for Windows.** [Microsoft Zenith](https://blogs.windows.com/windowsdeveloper/2026/09/04/announcing-project-zenith-the-ready-to-code-windows-experience/) preconfigures NVM, starting with AMD Ryzen AI Halo devices. More devices from OEM and silicon partners will be available in the coming months.  

<details>
<summary><b>NVM for Windows is not the same thing as nvm!</b> (expand for details)</summary>

_The original [nvm](https://github.com/nvm-sh/nvm) is a completely separate project for Mac/Linux only._ This project uses an entirely different philosophy and is not just a clone of nvm.
</details>


[](https://github.com/nvm-windows/nvm/releases/tag/v2.0.1)   [](https://twitter.com/intent/tweet?hashtags=nodejs&original_referer=http%3A%2F%2F127.0.0.1%3A91%2F&text=NVM%20for%20Windows%20v2%20is%20available.&tw_p=tweetbutton&url=https%3A%2F%2Fnvm-windows.com)


<table>
  <tr>
    <td>
      <h3>🚀 Version 2 is available</h3>
      <p>NVM for Windows has been <a href="https://medium.com/@goldglovecb/why-we-rewrote-nvm-for-windows-3b6fa5be3e7f?sharedUserId=goldglovecb">fully rewritten</a> for modern workflows.</p>
      <p><strong><a href="https://docs.nvm-windows.com/features/newv2">Explore what’s new →</a></strong></p>
    </td>
  </tr>
  <tr>
    <td>
      <h3>🏢 Introducing Certified Builds</h3>
      <p>Deploy NVM for Windows in controlled environments with commercial Certified Builds and optional add-ons:</p>
      <ul>
        <li><strong>IT-managed deployment</strong> with MSI and Intune</li>
        <li><strong>Centralized policy enforcement</strong></li>
        <li><strong>Auditable operations</strong> with advanced logging</li>
        <li><strong>Supply-chain confidence</strong> with verifiable trust artifacts</li>
      </ul>
      <p><strong><a href="https://nvm-windows.com/certified">Explore Certified Builds →</a></strong></p>
    </td>
  </tr>
</table>

## Resources

- [Official Website](https://nvm-windows.com)
- [Documentation](https://docs.nvm-windows.com)
- [Announcements](https://github.com/orgs/nvm-windows/discussions/categories/announcements)
- [Why We Rewrote NVM for Windows](https://medium.com/@goldglovecb/why-we-rewrote-nvm-for-windows-3b6fa5be3e7f?sharedUserId=goldglovecb)

## Features

> [!IMPORTANT]
> **Community Edition installers are now code-signed as of v2.0.0-hotfix.2.**

|Feature|Description|
|:-|:-|
|Compatibility<br/><br/><br/>|&bull; No mandatory administrator privileges.<br/>&bull; Shim mode - no symlinks, fast (written in Zig).<br/>&bull; Link mode - Zero-latency, junctions with symlink fallback.|
|Automation<br/><br/><br/>|&bull; Per-directory version switching (pinning).<br/>&bull; Auto-install missing versions.<br/>&bull; Auto-install default global modules.|
|Speed<br/><br/><br/><br/>|&bull; Parallel (multiple) simultaneous installations.<br/>&bull; Smaller downloads (7z).<br/>&bull; Native extraction.<br/>&bull; Caching.|
|Native&nbsp;Integrations<br/><br/><br/><br/>|&bull; Windows Apps<br/>&bull; Logging (Windows Event Viewer)<br/>&bull; Windows Registry<br/>&bull; Desktop Notification Center|
|Customization<br/><br/><br/>|&bull; User-defined aliases.<br/>&bull; User-defined default global modules.<br/>&bull; Configure local (air-gapped) downloads.|

### Certified Builds

Commercial **Certified Builds** are now available for controlled environments. [Learn more](https://nvm-windows.com/certified).

Not sure which edition is right for you? See [Choosing a Build](https://docs.nvm-windows.com/guide/builds/).

|Feature|Description|
|:-|:-|
|IT-Managed Installation<br/><br/>|&bull; Windows-protected installation directory<br />&bull; Administrator-controlled deployment and device management|
|Installers<br/><br/>|&bull; MSI/MST<br />&bull; Microsoft Intune|
|Advanced Logging ⭐<br/><br/><br/><br/>|&bull; Fully auditable<br />&bull; Structured<br />&bull; Dedicated Event Source<br />&bull; Native SIEM integration|
|Policy Enforcement ⭐<br/><br/><br/><br/><br/>|&bull; Active Directory/Entra integration<br/>&bull; Restrict Node.js versions/ranges (e.g. no EOL versions, LTS only, etc.)<br/>&bull; Control nvm-windows, Node/npm/npx settings<br/>&bull; Advanced proxy (IWA, WPAD/PAC) support<br />&bull; Private Node.js download mirror|
|Trust Artifacts ⭐<br/><br/><br/>|&bull; SBOM<br />&bull; SLSA Provenance<br />&bull; VEX Reports|

⭐ = Add-on package

## :pray: Thanks

Thanks to everyone who has submitted issues on and off GitHub, made suggestions, and generally helped make this a better project. Special thanks and the full contributor list is available **[here](THANKS.md)**.

---

### Overview (`build/README.md`)

# Community build

Authenticode-signed Inno Setup pipeline for NVM for Windows (core / community). No COSE worker signing, no SBOM, no SLSA, no ADMX, no MSI/Intune.

Produces `nvm.exe`, ETW event provider assets (`NVMWindows.Events.man` + `NVMWindows.Events.dll`), shims (`node` / `proxy` / `reshim`), `sync.exe`, and one Inno Setup `.exe`. Sync worker DLLs come from the certified release CDN (`assets.nvm-windows.com`) — this build does not compile them (CDN workers are already COSE Sign1'd by the certified pipeline).

`NVMWindows.Events.dll` is a wevtutil message/resource DLL (`/NOENTRY`). It is **Authenticode-signed** with product `.exe`/`.msi` artifacts (same Artifact Signing account). It is **not** COSE-signed (COSE is for sync workers only).

The `sync` Git submodule is **private**. Maintainers/CI compile it from source. Public from-source builds use `-DownloadSync` to fetch the matching release asset.

## Local

Requires: Go (see `cli/src/go.mod`), [qgo](https://github.com/quikdev/go), Zig (`shim/.zigversion`), [Inno Setup](https://jrsoftware.org/isdl.php) 6.7.1+, `go-winres`.

```powershell
# Maintainer / CI (sync submodule present)
.\build\main.ps1
.\build\main.ps1 -Architecture amd64
.\build\main.ps1 -Architecture arm64 -SkipInstaller
.\build\main.ps1 -Component Cli
.\build\main.ps1 -Hotfix beta.1
.\build\main.ps1 -Hotfix 2
.\build\main.ps1 -Version 2.0.1-hotfix.2

# Public clone (no sync source): download prebuilt sync.exe from the GitHub Release
.\build\main.ps1 -DownloadSync
.\build\main.ps1 -DownloadSync -SyncReleaseTag v2.0.0
.\build\main.ps1 -Component Sync -DownloadSync
```

`.\build.ps1` still forwards to `.\build\main.ps1`.

| Flag | Purpose |
|------|---------|
| `-Hotfix` | Same as GHA `prerelease`: any stamp → `{manifest}-{stamp}` (e.g. `beta.1` → `2.0.1-beta.1`). Bare digit `1` → `-hotfix.1` (WiX/Inno revision). Temp-stamps `cli/src/manifest.json` for qgo embed, sets process `NVM_CLI_VERSION`, restores both after build (git stays clean). Mutually exclusive with `-Version`. |
| `-Version` | Full special version override (e.g. `2.0.1-beta.1`). Same temp stamp/restore as `-Hotfix`. Mutually exclusive with `-Hotfix`. |
| `-DownloadSync` | Fetch `nvm-<version>-<x64\|arm64>-sync.exe` from GitHub Releases instead of compiling sync |
| `-SyncReleaseTag` | Override release tag (default: `v` + `cli/src/manifest.json` version) |
| `-SyncReleaseRepo` | Override `owner/repo` (default: `nvm-windows/nvm`) |

Output:

- Executables → `bin\`
- Event provider → `bin\NVMWindows.Events.man`, `bin\NVMWindows.Events.dll` (shipped next to `nvm.exe` in the installer)
- Installer → `.dist\nvm-<version>-<x64|arm64>-setup.exe` (`-Architecture amd64` writes `x64`)
- Staged sync release asset → `.dist\nvm-<version>-<x64|arm64>-sync.exe`

Requires Windows SDK (`mc.exe` / `rc.exe`) and Visual Studio `link.exe` for the event resource DLL.

## GHA

Workflow: [Release Community Build](../.github/workflows/release.yml) (`workflow_dispatch`).

| Input | Default | Purpose |
|-------|---------|---------|
| `architecture` | `both` | `amd64`, `arm64`, or both |
| `publish_release` | true | Draft → upload assets → publish |
| `override_existing_release` | false | Replace setup.exe **and** sync.exe on existing tag |
| `release_kind` | `General` | Release Type. `General` publishes the manifest version. `alpha`, `beta`, and `rc` prerelease that manifest version. `hotfix` patches a prior general release. The workflow assigns the next number. |
| `hotfix_base` | _(empty)_ | Hotfix Mainline. Specify the general release to apply the hotfix to, for example `2.0.1`. Leave empty to use the latest general release. Ignored unless Release Type is `hotfix`. |

GitHub Release assets per architecture:

- `nvm-<version>-x64-setup.exe` and `nvm-<version>-arm64-setup.exe` — Inno Setup installers
- `nvm-<version>-x64-sync.exe` and `nvm-<version>-arm64-sync.exe` — prebuilt sync for `-DownloadSync`

Tag = `v` + effective version. `General` uses `cli/src/manifest.json` (`2.0.2`). `alpha`, `beta`, and `rc` use that manifest plus the kind and the next unused number (`2.0.2-beta.3` already published means the next beta is `2.0.2-beta.4`). `hotfix` uses the Hotfix Mainline plus the next `-hotfix.N` (`2.0.1-hotfix.2` already published means the next hotfix of `2.0.1` is `2.0.1-hotfix.3`), not the current manifest. The runner patches the manifest before the CLI and Inno build so the embedded version and `AppVersion` match. Inno `VersionInfoVersion` maps the trailing `-word.N` to the fourth numeric field (`2.0.1-hotfix.1` → `2.0.1.1`). Any `x.y.z-*` release is marked GitHub **`--prerelease`**.

### WinGet

Workflow: [Publish to WinGet](../.github/workflows/winget.yml) (`workflow_dispatch`).

Use it only after a public GitHub Release has both `x64` and `arm64` setup assets. It:

1. Downloads release installers.
2. Generates `AuthorSoftware.NVMWindows` manifests and SHA256 values.
3. Verifies anonymous public release URLs produce matching hashes.
4. Runs `winget validate`.
5. By default, runs a silent install smoke test from the downloaded x64 setup asset, runs `nvm --version`, then uninstalls.
6. Uploads the generated manifests as a workflow artifact.
7. When `dry_run` is **false**, opens a pull request from `nvm-windows/winget-pkgs` that adds `AuthorSoftware.NVMWindows`. The first submission is a new package. Later runs add a version. This does not update `CoreyButler.NVMforWindows`.

`dry_run` defaults to **true** (validate only). Live submit needs secret `WINGET_CREATE_GITHUB_TOKEN` (classic PAT with `public_repo` and `workflow` for a user who can push `nvm-windows/winget-pkgs`). The `workflow` scope is required because syncing that fork fast-forwards Microsoft's Actions workflow changes.

Inputs:

| Input | Default | Purpose |
|-------|---------|---------|
| `release` | `latest` | `latest` = newest stable GitHub Release (no drafts/pre-releases). `custom` = use `release_tag`. |
| `release_tag` | empty | Tag for `custom` (e.g. `v2.0.0-alpha.2`). Ignored when `release=latest`. |
| `dry_run` | true | **On:** generate manifest, `winget validate`, upload artifact — no PR. **Off:** open a `microsoft/winget-pkgs` pull request from `nvm-windows/winget-pkgs` for `AuthorSoftware.NVMWindows`. |
| `install_test` | true | Silent install smoke test via local `release-assets` installer (not `winget install`). 4 min process timeout + 5 min step cap. Warns/skips on failure; never fails dry-run. |
| `verify_public_urls` | true | Anonymous GitHub release download + SHA256 must match manifest hashes. Fails workflow on mismatch (dry-run or publish). |

### Secrets

| Name | Purpose |
|------|---------|
| `GH_APP_CLIENT_ID` | GitHub App client ID (submodule checkout) |
| `GH_APP_PRIVATE_KEY` | App private key PEM |
| `WINGET_CREATE_GITHUB_TOKEN` | Classic PAT (`public_repo` and `workflow`) that can push `nvm-windows/winget-pkgs` when `dry_run=false` |

App install on `nvm-windows` must include **nvm**, **cli**, **common**, **shim**, **sync** (or all repos), **Contents: Read**. Inno Setup lives in-repo at `installer/` (not a submodule). Release publish uses `github.token` (`contents: write`).

Immutable releases: published tag locks forever. Bump manifest version, or turn immutable off and set `override_existing_release`.

---

### Overview (`installer/README.md`)

# Installer

The installer requires [InnoSetup](https://jrsoftware.org/isdl.php) 6.7.1 or above.

---

--- METRICS ---
- Files Extracted: 3
- Estimated Token Budget: ~3179 tokens
- Canonical Reference: https://codewiki.google/github.com/coreybutler/nvm-windows
