winget-bundle
winget-bundle is a package manager wrapper for Windows, inspired by Homebrew's bundle subcommand.
Declare all your packages in a single Bundlefile, then run one command to install or upgrade everything — across both winget and Scoop.
Features
- Declarative — list all packages in one
Bundlefile - Multi-source — supports
winget,msstore, andscoopsources in a single file - State file — a
Bundlefile.staterecords the installed state ofwingetpackages - Smart upgrade — upgrades outdated packages automatically; opt out per-package or globally
- Cleanup — uninstalls packages that have been removed from the
Bundlefile(dry-run by default)
Requirements
- Windows 10 / 11
- winget (for
wingetandmsstoresources) - Scoop (for
scoopsource, optional) - Rust toolchain (to build from source)
Installation
From source
Bundlefile
winget-bundle looks for your Bundlefile in the following locations, in order:
| Condition | Path |
|---|---|
$env:XDG_CONFIG_HOME is set |
$env:XDG_CONFIG_HOME\winget-bundle\Bundlefile |
| (default) | $env:USERPROFILE\.Bundlefile |
Syntax
# This is a comment
<source> "<id>" [, <key>: <value> ...]
| Field | Description |
|---|---|
source |
One of winget, msstore, or scoop |
id |
The package identifier (or name for msstore) |
name |
(optional) Human-readable label shown in output |
no_upgrade |
(optional, bool) Skip upgrade for this package if true |
Example
# Editors
winget "Microsoft.VisualStudioCode", name: "VS Code"
winget "Neovim.Neovim"
# Terminal
winget "Microsoft.WindowsTerminal", no_upgrade: true
# Microsoft Store
msstore "9N0DX20HK701", name: "Windows Terminal (Store)"
# Scoop
scoop "git"
scoop "ripgrep"
scoop "fd"
Usage
Install (default command)
Install all packages declared in the Bundlefile. Outdated packages are upgraded unless opted out.
winget-bundle
# or explicitly:
winget-bundle install
Upgrade behavior
By default, outdated packages are upgraded during install.
Set the environment variable $env:WINGET_BUNDLE_NO_UPGRADE to disable upgrades globally:
$env:WINGET_BUNDLE_NO_UPGRADE = "1"
winget-bundle
Use the flags below to override this behavior on a per-run basis:
| Flag | Description |
|---|---|
--upgrade |
Always upgrade, even if WINGET_BUNDLE_NO_UPGRADE is set |
--no-upgrade |
Never upgrade, regardless of env var |
winget-bundle install --upgrade
winget-bundle install --no-upgrade
Per-package opt-out is also available via the no_upgrade option in the Bundlefile.
Cleanup
Uninstall packages that are no longer present in the Bundlefile.
# Dry run — shows what would be removed
winget-bundle cleanup
# Actually uninstall
winget-bundle cleanup --force
Help
winget-bundle --help
winget-bundle install --help
winget-bundle cleanup --help
State File
After a successful install, winget-bundle writes a Bundlefile.state file next to your Bundlefile.
This TOML file records the installed winget packages, and is used by cleanup to track what was installed by winget-bundle.
Note:
msstoreandscooppackages are excluded from the state file.msstorepackages are managed directly through winget without version tracking, andscooppackages are excluded becausewinget-bundlequeries Scoop's own state directly to determine what is installed.
Environment Variables
| Variable | Description |
|---|---|
USERPROFILE |
Used to locate %USERPROFILE%\.Bundlefile when XDG_CONFIG_HOME is not set |
WINGET_BUNDLE_NO_UPGRADE |
When set, disables automatic upgrades during install (same as --no-upgrade) |
XDG_CONFIG_HOME |
If set, the Bundlefile is read from $XDG_CONFIG_HOME\winget-bundle\Bundlefile |
Contributing
If you find a bug or have a question, feel free to open an issue.
License
This project is licensed under the MIT License.