The single most underrated winget feature is import. It turns "setting up a new Windows machine" from a half-day chore into a 5-minute command. Here's how it works.
What is winget import?
Winget can read a JSON file listing apps and install them all in one shot. Combined with winget export, you can:
- Save your current Windows setup to a file
- Replay it on a fresh machine (or a teammate's machine)
- Version-control your machine config in Git
- Share a "perfect dev setup" with your team
The 60-second version
On your existing machine:
winget export -o my-apps.json --include-versions
On the new machine:
winget import -i my-apps.json
Done. Winget reads the file, installs everything, exits when finished. Typical time: 5–15 minutes depending on apps + internet speed.
The JSON format
Open a generated file — it looks like this:
{
"$schema": "https://aka.ms/winget-packages.schema.2.0.json",
"CreationDate": "2026-05-27T00:00:00.000-00:00",
"Sources": [
{
"Packages": [
{ "PackageIdentifier": "Microsoft.VisualStudioCode" },
{ "PackageIdentifier": "Git.Git" },
{ "PackageIdentifier": "OpenJS.NodeJS.LTS" }
],
"SourceDetails": {
"Argument": "https://cdn.winget.microsoft.com/cache",
"Identifier": "Microsoft.Winget.Source_8wekyb3d8bbwe",
"Name": "winget",
"Type": "Microsoft.PreIndexed.Package"
}
}
],
"WinGetVersion": "1.10.340"
}
It's plain JSON. Each PackageIdentifier is the winget ID you'd normally pass to --id. You can:
- Edit it by hand to add/remove apps
- Generate it from scratch (no machine needed — see below)
- Check it into Git
Pinning specific versions
By default import installs the latest version of each app. To force exact versions:
{
"Packages": [
{ "PackageIdentifier": "OpenJS.NodeJS", "Version": "20.18.0" }
]
}
Or when exporting:
winget export -o my-apps.json --include-versions
…and the file will include the version of every app currently installed.
Generating an import file without a source machine
You can build the JSON before you even have a new machine. We made a tool for exactly this:
- Go to winget.tech
- Browse and click + to add apps to your script
- Click Generate script
- Pick the Winget Import (.json) tab
- Click Download
The downloaded winstall.json is a valid winget import file. Move it to the new machine and run winget import -i winstall.json.
💡 You can also use a pre-made bundle (Developer, Gaming, Designer…) and add it to your script with one click.
Useful flags
winget import -i file.json --ignore-unavailable # skip apps not in catalog
winget import -i file.json --ignore-versions # always use latest
winget import -i file.json --accept-package-agreements
--accept-source-agreements # for unattended runs
For automated / CI use:
winget import -i file.json `
--ignore-unavailable `
--ignore-versions `
--accept-package-agreements `
--accept-source-agreements `
--disable-interactivity
A real example: my actual machine setup
Here's a minimal dev.json I run on every new dev machine:
{
"$schema": "https://aka.ms/winget-packages.schema.2.0.json",
"CreationDate": "2026-05-27T00:00:00.000-00:00",
"Sources": [{
"Packages": [
{ "PackageIdentifier": "Microsoft.VisualStudioCode" },
{ "PackageIdentifier": "Microsoft.WindowsTerminal" },
{ "PackageIdentifier": "Microsoft.PowerShell" },
{ "PackageIdentifier": "Microsoft.PowerToys" },
{ "PackageIdentifier": "Git.Git" },
{ "PackageIdentifier": "GitHub.cli" },
{ "PackageIdentifier": "OpenJS.NodeJS.LTS" },
{ "PackageIdentifier": "Python.Python.3.13" },
{ "PackageIdentifier": "Docker.DockerDesktop" },
{ "PackageIdentifier": "BurntSushi.ripgrep.MSVC" },
{ "PackageIdentifier": "Starship.Starship" },
{ "PackageIdentifier": "voidtools.Everything" },
{ "PackageIdentifier": "Google.Chrome" },
{ "PackageIdentifier": "Discord.Discord" },
{ "PackageIdentifier": "Spotify.Spotify" }
],
"SourceDetails": {
"Argument": "https://cdn.winget.microsoft.com/cache",
"Identifier": "Microsoft.Winget.Source_8wekyb3d8bbwe",
"Name": "winget",
"Type": "Microsoft.PreIndexed.Package"
}
}],
"WinGetVersion": "1.10.340"
}
15 essentials. Save it, push to a private repo, clone on every new machine, run winget import -i dev.json.
Version-controlling your machine
If you treat your dotfiles / scripts as code, do the same with your machine setup:
my-machine/
├── dev.json # winget packages
├── vscode-settings.json # editor config
├── windows-terminal.json # terminal config
├── powershell-profile.ps1
└── setup.ps1 # script that ties it all together
setup.ps1 example:
# Install all winget packages
winget import -i $PSScriptRoot\dev.json --accept-package-agreements --accept-source-agreements
# Symlink configs
$vsCodeDir = "$env:APPDATA\Code\User"
Copy-Item $PSScriptRoot\vscode-settings.json $vsCodeDir\settings.json -Force
# PowerShell profile
Copy-Item $PSScriptRoot\powershell-profile.ps1 $PROFILE -Force
Write-Host "Done. Restart shells to apply config."
Now setting up a new machine is:
git clone https://github.com/me/my-machine.git
cd my-machine
.\setup.ps1
When import fails partially
winget import is mostly all-or-nothing — if one package fails, it moves on. Common reasons:
- Package ID was renamed upstream → edit the JSON, update ID
- Network blip → re-run, it'll skip already-installed
- App needs a dependency winget can't auto-resolve → install dep manually first
- Hash mismatch → publisher updated installer, catalog stale → wait or
--force
Use --ignore-unavailable to skip rather than fail on missing packages.
See also
- Browse and build your import file → — visual tool, no CLI required
- Pre-made bundles → — Developer, Gaming, Office, Designer…
- Winget commands cheatsheet → — full reference
- Best winget packages for developers → — curated list
Got a setup workflow you love? Send it in — we feature the best ones in this post.
