Skip to main content
Packages in WinGet represent installable software applications. Each package contains metadata describing the application, its installers, localization information, and system requirements.

Package Structure

A WinGet package consists of three core components:
1

Package Identifier

A unique identifier in Publisher.Application format (e.g., Microsoft.WindowsTerminal)
2

Version Information

Semantic version number and optional channel information
3

Manifest Data

YAML files containing installer, localization, and metadata

Package Manifest Object

At runtime, packages are represented by the Manifest structure:
// From Manifest.h:15-74
struct Manifest
{
    string_t Id;                          // Package identifier
    string_t Version;                     // Package version
    string_t Channel;                     // Distribution channel
    string_t Moniker;                     // Short alias (e.g., "vscode")
    ManifestVer ManifestVersion;          // Schema version
    
    ManifestInstaller DefaultInstallerInfo;
    std::vector<ManifestInstaller> Installers;
    
    ManifestLocalization DefaultLocalization;
    std::vector<ManifestLocalization> Localizations;
    ManifestLocalization CurrentLocalization;
    
    // SHA256 hash of the manifest stream itself
    Utility::SHA256::HashBuffer StreamSha256;
};

Package Identifier

The PackageIdentifier must follow a strict format:
// From manifest.singleton.latest.json:6-10
"PackageIdentifier": {
  "type": "string",
  "pattern": "^[^\\.\\s\\\\/:\\*\\?\"<>\\|\\x01-\\x1f]{1,32}(\\.[^\\.\\s\\\\/:\\*\\?\"<>\\|\\x01-\\x1f]{1,32}){1,7}$",
  "maxLength": 128,
  "description": "The package unique identifier"
}
Format: Publisher.Application (e.g., Microsoft.PowerToys)
  • Maximum 128 characters
  • 2-8 segments separated by periods
  • Each segment: 1-32 characters
  • No spaces or special characters: \ / : * ? " < > |
Examples:
# Valid identifiers
Microsoft.WindowsTerminal
Google.Chrome
Mozilla.Firefox.DeveloperEdition
Contoso.Internal.ProductivityTools

# Invalid identifiers
Microsoft Windows Terminal  # Contains spaces
Chrome                      # Missing publisher
..InvalidPackage            # Invalid segment format

Package Version

Version strings follow semantic versioning principles:
// From manifest.singleton.latest.json:12-16
"PackageVersion": {
  "type": "string",
  "pattern": "^[^\\\\/:\\*\\?\"<>\\|\\x01-\\x1f]+$",
  "maxLength": 128,
  "description": "The package version"
}
Version format examples:
1.0.0
2.1.5.300
3.0.0-beta.1
2024.03.15

Moniker

A short, memorable alias for quick installation:
// From Manifest.h:25
string_t Moniker;
# Install using moniker instead of full identifier
winget install vscode
# Equivalent to:
winget install Microsoft.VisualStudioCode
If only one package has a specific moniker, users can install using just the moniker for convenience.

Package Metadata

Packages contain rich metadata through localization objects:

Default Localization

Required metadata in the package’s primary language:
# From manifest.md:125-152 (Windows Terminal example)
PackageIdentifier: Microsoft.WindowsTerminal
PackageVersion: 1.6.10571.0
PackageLocale: en-US
Publisher: Microsoft
PublisherURL: https://www.microsoft.com/
PrivacyURL: https://privacy.microsoft.com/
PackageName: Windows Terminal
PackageURL: https://docs.microsoft.com/windows/terminal/
License: MIT
LicenseURL: https://github.com/microsoft/terminal/blob/master/LICENSE
ShortDescription: The new Windows Terminal, a tabbed command line experience for Windows.
Tags:
- console
- command-line
- shell
- cmd
- powershell
- wsl

Additional Localizations

Packages can include multiple language translations:
# From manifest.md:154-164 (French localization)
PackageIdentifier: Microsoft.WindowsTerminal
PackageVersion: 1.6.10571.0
PackageLocale: fr-FR
Publisher: Microsoft
ShortDescription: Le nouveau terminal Windows, une expérience de ligne de commande à onglets pour Windows.
ManifestType: locale
ManifestVersion: 1.4.0

Locale Format

// From manifest.installer.latest.json:18-22
"Locale": {
  "type": [ "string", "null" ],
  "pattern": "^([a-zA-Z]{2,3}|[iI]-[a-zA-Z]+|[xX]-[a-zA-Z]{1,8})(-[a-zA-Z]{1,8})*$",
  "maxLength": 20,
  "description": "The installer meta-data locale"
}
Locales follow BCP 47 format (e.g., en-US, fr-FR, zh-CN).

Installer Information

Packages specify one or more installers with platform-specific details:

Supported Installer Types

// From manifest.installer.latest.json:55-70
"InstallerType": {
  "type": [ "string", "null" ],
  "enum": [
    "msix",
    "msi",
    "appx",
    "exe",
    "zip",
    "inno",
    "nullsoft",
    "wix",
    "burn",
    "pwa",
    "portable",
    "font"
  ]
}

Architecture Support

// From manifest.installer.latest.json:114-123
"Architecture": {
  "type": "string",
  "enum": [
    "x86",
    "x64",
    "arm",
    "arm64",
    "neutral"
  ]
}

Installer Example

# From manifest.md:166-193
PackageIdentifier: Microsoft.WindowsTerminal
PackageVersion: 1.6.10571.0
Platform:
 - Windows.Desktop
MinimumOSVersion: 10.0.18362.0
InstallerType: msix
InstallModes:
 - silent
PackageFamilyName: Microsoft.WindowsTerminal_8wekyb3d8bbwe
Installers:
 - Architecture: x64
   InstallerUrl: https://github.com/microsoft/terminal/releases/download/v1.6.10571.0/Microsoft.WindowsTerminal_1.6.10571.0_8wekyb3d8bbwe.msixbundle
   InstallerSha256: 092aa89b1881e058d31b1a8d88f31bb298b5810afbba25c5cb341cfa4904d843
   SignatureSha256: e53f48473621390c8243ada6345826af7c713cf1f4bbbf0d030599d1e4c175ee
 - Architecture: arm64
   InstallerUrl: https://github.com/microsoft/terminal/releases/download/v1.6.10571.0/Microsoft.WindowsTerminal_1.6.10571.0_8wekyb3d8bbwe.msixbundle
   InstallerSha256: 092aa89b1881e058d31b1a8d88f31bb298b5810afbba25c5cb341cfa4904d843
   SignatureSha256: e53f48473621390c8243ada6345826af7c713cf1f4bbbf0d030599d1e4c175ee

Package Discovery

The manifest provides methods to aggregate information across installers and localizations:
// From Manifest.h:43-65
// Get all tags across localizations
std::vector<string_t> GetAggregatedTags() const;

// Get all commands across installers
std::vector<string_t> GetAggregatedCommands() const;

// Get package family names across installers, Case folded.
std::vector<string_t> GetPackageFamilyNames() const;

// Get product codes across installers, Case folded.
std::vector<string_t> GetProductCodes() const;

// Get upgrade codes across installers, Case folded.
std::vector<string_t> GetUpgradeCodes() const;

// Get package names across localizations and installers, Case folded.
std::vector<string_t> GetPackageNames() const;

// Get publishers across localizations and instalizers, Case folded.
std::vector<string_t> GetPublishers() const;

Install Scope

Packages can be installed at user or machine scope:
// From manifest.installer.latest.json:125-131
"Scope": {
  "type": [ "string", "null" ],
  "enum": [
    "user",
    "machine"
  ],
  "description": "Scope indicates if the installer is per user or per machine"
}
winget install Microsoft.PowerToys --scope user

Platform Targeting

// From manifest.installer.latest.json:30-42
"Platform": {
  "type": [ "array", "null" ],
  "items": {
    "type": "string",
    "enum": [
      "Windows.Desktop",
      "Windows.Universal"
    ]
  },
  "maxItems": 2,
  "uniqueItems": true
}

Install Modes

Packages declare supported installation modes:
// From manifest.installer.latest.json:133-146
"InstallModes": {
  "type": [ "array", "null" ],
  "items": {
    "type": "string",
    "enum": [
      "interactive",
      "silent",
      "silentWithProgress"
    ]
  },
  "maxItems": 3,
  "uniqueItems": true
}

ARP Correlation

Packages are correlated with installed applications via Add/Remove Programs (ARP):
# From TestArpVersionMapping_SameAsPackageVersion.yaml:15-16
AppsAndFeaturesEntries:
- DisplayVersion: "1.0"
// From Manifest.h:49-50
// Gets ARP version range if declared, otherwise an empty range is returned
Utility::VersionRange GetArpVersionRange() const;
This enables WinGet to:
  • Detect already-installed packages
  • Support upgrade scenarios
  • Track installation state

Repository Organization

Packages in the winget-pkgs repository follow a specific folder structure:
manifests/<first-letter>/<publisher>/<application>/<version>/
Example:
manifests/m/Microsoft/WindowsTerminal/1.6.10571.0/
  ├── Microsoft.WindowsTerminal.yaml           (version file)
  ├── Microsoft.WindowsTerminal.installer.yaml (installer info)
  ├── Microsoft.WindowsTerminal.locale.en-US.yaml (default locale)
  └── Microsoft.WindowsTerminal.locale.fr-FR.yaml (additional locale)
The partitioning scheme (first letter folder) helps with GitHub’s UX, as folders with thousands of children don’t render well in the browser.

Best Practices

  • Use Publisher.Application format consistently
  • Don’t create multiple publisher folders (e.g., avoid both “Contoso” and “Contoso Ltd.”)
  • Ensure identifiers match Add/Remove Programs entries for correlation
  • Only one pull request per package version allowed
  • Version must match folder structure
  • Use DisplayVersion in AppsAndFeaturesEntries for upgrade support
  • Provide as many optional fields as possible
  • Include monikers for popular packages
  • Add comprehensive tags for discoverability
  • Include product codes for MSI installers
  • Translate descriptions for global audiences
  • All installers must support silent installation
  • Include SHA256 hash for verification
  • Specify correct InstallerType for optimal UX
  • For Nullsoft/Inno installers, WinGet auto-configures silent switches

Next Steps

Manifests

Deep dive into manifest file structure and schemas

Sources

Learn how sources provide package repositories

Build docs developers (and LLMs) love