Reading the repo
Reading the repo
How to install on Windows
A simple, lightweight PowerShell script that allows you to remove pre-installed apps, disable telemetry, as well as perform various other changes to declutter and customize your Windows experience. Win11Debloat works for both Windows 10 and Windows 11.
Fresh setup, read just now
Will it work on Windows?
The maintainers included Run.bat. Run it from the cloned folder after reading it.
.\Run.bat
.github/CONTRIBUTING.mdWe welcome contributions from the community. You can contribute to Win11Debloat by:
You can help us test the latest changes and additions to the script. If you encounter any issues, please report them here.
[!WARNING] The prerelease version of Win11Debloat is meant for developers to test the script. Don't use this in production environments!
You can launch the prerelease version of Win11Debloat by running this command:
& ([scriptblock]::Create((irm "https://debloat.raphi.re/"))) -Dev
Fork the project on GitHub by clicking the "Fork" button at the top right of the repository page.
Clone the repository to your local machine:
git clone https://github.com/YOUR-USERNAME/Win11Debloat.git
cd Win11Debloat
Create a new branch for your contribution:
git checkout -b feature/your-feature-name
Open PowerShell as an administrator
Enable script execution if necessary:
Set-ExecutionPolicy Bypass -Scope Process -Force
Navigate to your Win11Debloat directory
Run the script:
.\Win11Debloat.ps1
The automated tests use Pester 5 and are found in the Tests directory. They cover registry operations, app removal, CLI/GUI logic, and config handling. Some Windows behavior is mocked so the tests can run safely, but they do not replace manual testing on a Windows test environment.
The bootstrap option can be used to automatically install Pester on your machine and run the full suite of tests:
.\Tools\Run-Tests.ps1 -Bootstrap
After the initial setup, you can simply run the full suite with:
.\Tools\Run-Tests.ps1
For a focused test run during development, you can also call Pester directly:
Invoke-Pester -Path .\Tests\Invoke-Changes.Tests.ps1 -Output Detailed
GitHub Actions runs the same suite with Windows
PowerShell 5.1 for pull requests and pushes to master.
Win11Debloat is a PowerShell script with a WPF (Windows Presentation Foundation)-based GUI and command-line interface. The CLI provides an alternative to the GUI, allowing most features to be invoked directly through command-line parameters. The project uses a data-driven architecture, separating feature and application definitions from the logic that applies them.
Win11Debloat.ps1 is the main entry point and can be launched directly or through one of the provided launchers:
Run.bat launches a locally downloaded copy of Win11Debloat.ps1.Get.ps1 downloads Win11Debloat and launches Win11Debloat.ps1.Both Get.ps1 and Win11Debloat.ps1 support command-line parameters, allowing Win11Debloat to be configured and run without using the GUI.
Win11Debloat.ps1 loads the configuration and shared functions, then routes execution through either the WPF GUI or CLI. Both interfaces use the same underlying feature and app-removal engine.
flowchart TB
Main[Win11Debloat.ps1] --> GUI[WPF GUI]
Main --> CLI[CLI]
Config["Config Files (JSON)"] --> GUI
Config --> CLI
GUI --> Changes[Apply Selected Changes]
CLI --> Changes
Config --> Changes
Changes --> Regfiles[Regfiles]
Changes --> Tools[Appx / WinGet]
Win11Debloat/
├── Win11Debloat.ps1 # Main PowerShell script
├── Run.bat # Local launcher
├── Scripts/ # Additional PowerShell scripts and functions
│ ├── Get.ps1 # Download-and-launch script
│ ├── AppRemoval/ # App package removal logic
│ ├── CLI/ # Command-line interface helpers
│ ├── Features/ # Feature apply, undo, backup, and restore logic
│ ├── FileIO/ # File input/output helpers
│ ├── GUI/ # GUI window definitions and logic
│ ├── Helpers/ # Shared helper functions
│ └── Threading/ # Threading utilities
├── Config/
│ ├── Apps.json # List of supported apps for removal
│ ├── DefaultSettings.json # Default configuration preset
│ ├── Features.json # All features with metadata
│ ├── LastUsedSettings.json # Last used configuration (generated during use)
│ └── Languages/ # GUI translation files, one folder per culture code (e.g. en-US/)
├── Regfiles/ # Registry files for all features
│ ├── Undo/ # Registry files for reverting features
│ └── Sysprep/ # Registry files for Sysprep mode
├── Schemas/ # XAML views and shared GUI resources
├── Assets/ # Static assets (icons, start menu templates)
├── Tools/ # Development scripts (excluded from release packages)
│ ├── Build-Release.ps1 # Runtime release packaging
│ └── Run-Tests.ps1 # Pester test runner (optionally bootstraps Pester)
├── Tests/ # Pester tests for script and XAML contracts
├── Backups/ # Registry backups (generated during use)
└── Logs/ # Script logs (generated during use)
README.md, wiki, and other relevant documentation.MinVersion and MaxVersion if a feature only applies to specific Windows versions.Avoid these common mistakes when contributing:
Forgetting Get.ps1: When adding a new command-line parameter, contributors often remember to add it to Win11Debloat.ps1 but forget to add the same parameter to Scripts/Get.ps1. Both files must have matching parameters.
Missing Registry Files: For registry-backed features, create an Undo registry file for reversibility and a Sysprep registry file for applying changes to other users and Sysprep mode.
Incorrect Registry Hives for Sysprep: Sysprep registry files are meant to apply changes to a different user. Registry keys in the HKEY_CURRENT_USER hive must use hkey_users\default instead. Ensure you update all registry keys in the file.
Wrong Registry File Location:
Regfiles/Regfiles/Undo/Regfiles/Sysprep/Placing files in the wrong directory may cause the script to fail when trying to apply or undo changes.
Not Testing Undo Functionality: Always test that your undo registry file properly reverts all changes.
Not Testing User/Sysprep Functionality: Always test that your feature works when applied to another user or to the Windows default user with Sysprep. Sysprep changes can be tested by creating new users after running the script.
Missing Category: Features without a Category field (set to null) won't appear in the GUI. This is intentional for command-line-only features, make sure this is what you want before submitting.
Hardcoded Paths: When writing PowerShell logic, use $PSScriptRoot and script variables instead of hardcoded paths. This ensures the script works regardless of where it's installed.
Missing Translation Entry: A new Feature, Category, UI Group, or App needs a matching entry in Config/Languages/en-US/ (see Localizing UI Text). Without one, the GUI silently falls back to displaying the raw FeatureId/CategoryId/GroupId/AppId instead of your Label/ToolTip/FriendlyName/Description text.
[!NOTE] The script generates the GUI app options from
Config/Apps.json, using names and descriptions fromConfig/Languages/<locale>/Apps.jsonwith English fallback.
To add a new app that can be removed via Win11Debloat:
Find the AppId: For an Appx app, find the package name with:
Get-AppxPackage | Select-Object Name, PackageFullName
For a WinGet app, use winget list and use its Id value.
Edit Config/Apps.json: Add a new entry to the "Apps" array:
{
"AppId": "AppPackageIdentifier",
"SelectedByDefault": false,
"Recommendation": "optional",
"RemovalMethod": "Appx"
}
Field Descriptions:
AppId: The package name from Get-AppxPackage or the Id from
winget list, depending on removal method. Use an array when one app
requires multiple identifiers. The GUI looks up the translation entry by
the first ID in the array, key Apps.json by that one.SelectedByDefault: Set to true only for apps that are largely considered bloatware, otherwise set to false.Recommendation: Indicates how strongly the app is recommended for removal. One of:
safe — safe to remove for most usersoptional — can be safely removed if the user doesn't need the appunsafe — should only remove if the user knows what they are doingRemovalMethod: The method used to remove the app. One of:
Appx — remove as a standard Appx package via Remove-AppxPackage (most apps)WinGet — remove via WinGet (winget uninstall). Use for non-Appx apps such as Microsoft Copilot.Add the English Translation Entry: Add a matching entry for your AppId to Config/Languages/en-US/Apps.json (see Localizing UI Text). Names and descriptions belong only in the language catalogs:
"AppPackageIdentifier": {
"FriendlyName": "Display Name",
"Description": "Brief description of the app"
}
Add translations to the other shipped language catalogs. Missing translations fall back to English; a missing English entry displays the raw AppId.
Follow the Guidelines:
FriendlyNameFeatures are defined in Config/Features.json and can modify Windows settings via registry files or PowerShell commands.
[!NOTE] For simple features that just include a registry change, no actual coding is required in the main script except for adding the corresponding command-line parameters. The GUI is automatically built using the information in the Features.json file.
Create new registry files in the Regfiles/ directory:
Disable_YourFeature.regUndo/Enable_YourFeature.reg (for reverting)Sysprep/Disable_YourFeature.reg (for Sysprep mode)Example registry file structure:
Windows Registry Editor Version 5.00
[HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\YourPath]
"SettingName"=dword:00000000
A Sysprep registry file should apply the same changes as the normal action. Replace the hive of registry keys that start with HKEY_CURRENT_USER with hkey_users\default. For example:
Windows Registry Editor Version 5.00
[hkey_users\default\Software\Microsoft\Windows\CurrentVersion\YourPath]
"SettingName"=dword:00000000
If your feature requires more than just applying a registry file, add custom logic to the main script in the appropriate section. In most cases this will involve creating a new entry in the Invoke-FeatureApply function (in Scripts/Features/Invoke-Changes.ps1) for your new feature. If your feature also requires custom undo logic (beyond a simple registry file import), add a corresponding entry to the Invoke-FeatureUndo function in the same file.
Add your feature to the "Features" array in Config/Features.json:
{
"FeatureId": "YourFeatureId",
"Category": "Privacy & Suggested Content",
"Priority": 1,
"RegistryKey": "Disable_YourFeature.reg",
"RegistryUndoKey": "Enable_YourFeature.reg",
"RequiresReboot": false,
"DisableWhenApplied": false,
"MinVersion": null,
"MaxVersion": null
}
Field Descriptions:
FeatureId: Unique identifier, this must match parameter name in the Win11Debloat.ps1 and Get.ps1 files.Category: One of the predefined categories (see Categories array in Features.json), features without a category won't be loaded into the GUI.Priority: Optional. The priority value (int) is used to sort features within a category. If this field is omitted the feature will be sorted based on the order in the Features.json file.RegistryKey: Filename of the registry file to apply (in Regfiles/ directory) or null if feature does not require registry changes.RegistryUndoKey: Filename of the registry file to revert changes or null if feature does not require registry changes.RequiresReboot: Optional boolean. Set to true if the feature requires a system reboot to take effect.DisableWhenApplied: Optional boolean. Set to true if the feature has no supported undo method.MinVersion: Minimum Windows build version (e.g., "22000") or null.MaxVersion: Maximum Windows version or null.Add a corresponding parameter to both Win11Debloat.ps1 AND Scripts/Get.ps1, the parameter name should match the FeatureId you have defined in Features.json. In most cases this will be a switch parameter, example:
[switch]$YourFeatureId,
Add a matching entry for your FeatureId to Config/Languages/en-US/Features.json (see Localizing UI Text). Labels, tooltips, and apply/undo messages belong only in the language catalogs.
Add or update Pester coverage for the new behavior, then run the full suite.
[!IMPORTANT] The default preset is intentionally conservative. Features added to it should be thoroughly tested and widely beneficial. When in doubt, leave the feature out of the default preset.
The default preset (Config/DefaultSettings.json) defines which features are automatically applied when users run Win11Debloat in "Default Mode" or with the -RunDefaults parameter. This preset should include features that are widely considered to improve the Windows experience without breaking functionality.
When to add a feature to the default preset:
When NOT to add a feature to the default preset:
To add your feature to the default preset, edit Config/DefaultSettings.json and add a new entry to the "Settings" array:
{
"Name": "YourFeatureId",
"Value": true
}
Field Descriptions:
Name: Must exactly match the FeatureId from Features.jsonValue: Set to true to enable the feature in default modeExample:
{
"Version": "1.0",
"Settings": [
{
"Name": "CreateRestorePoint",
"Value": true
},
{
"Name": "DisableTelemetry",
"Value": true
},
{
"Name": "YourFeatureId",
"Value": true
}
]
}
To add a new category for organizing features:
Add a new category entry to the "Categories" array in Config/Features.json:
{
"CategoryId": "YourCategoryId",
"Name": "Your Category Name",
"Icon": "####;"
}
CategoryId is required for tweak presets and localization. Name must match the Category value on features and groups. Add the display label to Config/Languages/en-US/Categories.json, keyed by CategoryId.
[!TIP] Use Segoe Fluent Icon Assets for icon codes.
UI Groups allow features to be grouped together in the GUI with a combobox
(dropdown) selection. Add the group to the top-level "UiGroups" array in
Config/Features.json and use a unique GroupId:
{
"GroupId": "UniqueGroupId",
"Category": "Category Name",
"Priority": 1,
"Values": [
{
"FeatureIds": ["FeatureId1"]
},
{
"FeatureIds": ["FeatureId2"]
}
]
}
[!IMPORTANT] Define the referenced features before adding a group. Each
FeatureIdin a group'sValueslist must already be defined in the"Features"array inFeatures.json. Features referenced by a group are shown through that group rather than as standalone controls.
Add a matching entry for your GroupId to Config/Languages/en-US/Features.json (see Localizing UI Text) so the GUI shows your Label/ToolTip/option text instead of the raw GroupId.
GUI text lives in Config/Languages/en-US/, not hardcoded in Schemas/*.xaml, Scripts/GUI/*.ps1 or Config/Features.json. Adding or changing a Feature, Category, UI Group, or App means updating the matching English entry, or the GUI falls back to showing the raw ID.
Config/Languages/en-US/Features.json, under "Features", keyed by FeatureId: Label describes the feature, ToolTip explains its impact, and ApplyText is the operation message. For features supporting undo, also add UndoLabel and ApplyUndoText.Config/Languages/en-US/Features.json, under "UiGroups", keyed by GroupId. Add Label, ToolTip, and a Values map of FeatureId: "Option label" matching the group's Values array.Config/Languages/en-US/Categories.json, keyed by CategoryId. Add a Label for every new category.Config/Languages/en-US/Apps.json, keyed by AppId. Add FriendlyName and Description for every new app.[!Warning] Great care went into making sure this script does not unintentionally break any OS functionality, but use at your own risk! If you run into any issues, please report them here.
Download & run the script automatically via PowerShell.
& ([scriptblock]::Create((irm "https://debloat.raphi.re/")))
This method supports command-line parameters to customize the behaviour of the script. Please click here for more information.
Run.bat file to start the script. NOTE: If the console window immediately closes and nothing happens, try the advanced method below.Set-ExecutionPolicy Bypass -Scope Process -Force
cd c:\Win11Debloat.\Win11Debloat.ps1
This method supports command-line parameters to customize the behaviour of the script. Please click here for more information.
</details>Then run powershell -ExecutionPolicy Bypass -File .\setup.ps1. It stops at the first error and is safe to run again. Servers and tests aren't started; it lists them at the end. Read it first.
Needs Git: winget install Git.Git
git clone https://github.com/Raphire/Win11Debloat.git cd Win11Debloat
In the maintainers' order. Do the README instructions above first — they cover steps outside the terminal.
& ([scriptblock]::Create((irm "https://debloat.raphi.re/"))) Set-ExecutionPolicy Bypass -Scope Process -Force .\Win11Debloat.ps1
No reports for Windows yet.
Opens a chat with this manual already filled in, for Windows. It uses your own account; gitmanual sends nothing.