Contributing to Winapp2.ini
July 28, 2026 · View on GitHub
This guide covers how to add and update entries in winapp2.ini under the current build workflow.
How Winapp2.ini is maintained
Winapp2.ini is no longer edited directly. Instead, it is assembled from the source files in the Assembler/ directory by winapp2ool.
All contributions must target those source files, not any Winapp2.ini file directly.
Building and publishing are automated. Once your change is merged, a scheduled GitHub Actions workflow rebuilds winapp2.ini and every flavor of it from the current sources, commits the results, and cuts a tagged release with each flavor and its changelog attached. Nobody runs the build by hand, and you never need to generate any output file yourself. Only edit the source files. In practice a merged entry appears in winapp2.ini, and in a release, within a day.
Table of contents
- Quick reference
- Finding the source of an existing entry
- Adding your first entry
- Updating an existing entry
- Retiring an entry
- General rules
- Standard entries
- Browser entries
- UWP entries
- EntryBuilder entries
- Winapp3.ini
- Flavor corrections
- How to submit
- What happens after you open a PR
Quick reference
| What you want to do | Where to edit |
|---|---|
| Add, update, or remove an entry for a win32-only application (traditional desktop software) | Assembler/EntryBuilder/<letter>.ini |
| Add, update, or remove an entry for an application with a UWP (or UWP and also a win32) version (Windows Store apps, generally) | Assembler/UWP/AppInfo/<letter>.ini |
| Add, update, or remove support for a Chromium-based web browser | Assembler/BrowserBuilder/chromium.ini |
| Add, update, or remove support for a Gecko-based web browser | Assembler/BrowserBuilder/gecko.ini |
| Add a browser entry; Update or remove a generated browser entry | Assembler/BrowserBuilder/browser_*.ini |
| Add, update, or remove an entry for a power-user or aggressive operation | Winapp3/Winapp3.ini |
| Fix an entry that already exists in winapp2.ini | Find its source file first. See Finding the source of an existing entry |
| Retire an entry for software that no longer exists | Move it from its source file to Winapp3/Archived entries.ini. See Retiring an entry |
| Report a flavor-specific issue | Open an issue, or edit the appropriate flavor file in Assembler/<FlavorName>. The <FlavorName> is simply the name of the tool whose flavor you want to modify: CCleaner, CCleaner7, BleachBit, SystemNinja,Tron, or FluentCleaner |
All base entries live in Assembler/EntryBuilder/<letter>.ini. Standard winapp2.ini syntax is valid there. The folder name refers to the winapp2ool module that processes it, and an optional shorthand exists but is never required. The files under Assembler/Entries/ are build artifacts regenerated from these sources on every build; do not edit them. See EntryBuilder entries.
Editing a build artifact instead of its source is an easy mistake to make, but it is a mistake. Your committed changes will be silently destroyed when the next build regenerates the artifact from the unmodified source files. CI checks for this: if your PR changes a file under Assembler/Entries/, or a published winapp2.ini or diff.txt file, without also changing the source file that produces it, the generated artifact guard fails and names the source file you should have edited instead. See What happens after you open a PR.
Finding the source of an existing entry
Winapp2.ini is assembled from several source file sets and generators, so many entries do not exist verbatim anywhere in this repository. Searching for a generated entry by name may find nothing. To locate the source of an entry you want to change:
| If the entry... | Its source is |
|---|---|
Is named Browser Name Category * (e.g. Brave Caches *) for a browser described in chromium.ini or gecko.ini | Generated by BrowserBuilder from Assembler/BrowserBuilder/. Fixes for a specific browser go in the browser_*.ini correction files. See Browser entries |
Targets paths under %LocalAppData%\Packages\ (Microsoft Store apps) | Generated by UWPBuilder from Assembler/UWP/AppInfo/<letter>.ini. See UWP entries |
| Appears in only one flavor of winapp2.ini | Added by that flavor: Assembler/<FlavorName>/*_additions.ini. See Flavor corrections |
| Anything else | Assembler/EntryBuilder/<letter>.ini, where <letter> is the first letter of the entry name |
Search tip: use GitHub's repository search for the entry name without the trailing *]. A base entry matches twice: its source in Assembler/EntryBuilder/ (edit this one) and its regenerated artifact in Assembler/Entries/ (never edit this one). If only an artifact or a built winapp2.ini matches, the entry is generated. Search for a distinctive fragment of one of its FileKey or RegKey paths to find the generator source.
Adding your first entry
1. Decide what kind of entry you're adding
| If the app is... | You're adding | Edit |
|---|---|---|
| A traditional desktop install (.exe, .msi) | A standard entry | Assembler/EntryBuilder/<letter>.ini |
| A Microsoft Store app, or has both Store and desktop versions | A UWP entry | Assembler/UWP/AppInfo/<letter>.ini |
| A web browser | A browser definition | Assembler/BrowserBuilder/chromium.ini or gecko.ini |
| An aggressive operation aimed at power users | A Winapp3 entry | Winapp3/Winapp3.ini |
When in doubt, write a standard entry and place it in the appropriate <letter>.ini file in Assembler/EntryBuilder.
2. Find what to clean
Install the app, use it normally for a while, and do whatever produces the data you want gone: open files, browse around, sign in, run several times, etc. Identify the location of this data on disk. Be careful to make sure that this data isn't comingled with important data such as application configuration.
3. Write the entry
Open the right source file, find the alphabetical spot for your entry, and write it. Follow the Standard entries, UWP entries, or Browser entries section depending on what you're adding. Again, when in doubt, always create a standard entry.
4. Validate
See Verifying your work.
5. Submit
Open a PR against master.
Updating an existing entry
- Locate the entry's source.
- Make your change in that source file. If the entry lives in
Assembler/EntryBuilder/, recall that standard winapp2.ini syntax is still valid there. See EntryBuilder entries. - Validate.
- Open a PR describing what changed and why (e.g. "version X moved its cache to a new location").
Retiring an entry
Entries for software that is no longer available are moved to the archive at Winapp3/Archived entries.ini rather than deleted, preserving them for users who still run the software.
- Remove the entry from its source file.
- Add it to
Winapp3/Archived entries.iniin alphabetical order, written in standard winapp2.ini syntax. A base entry written in standard syntax can be moved as-is from itsAssembler/EntryBuilder/source file. If the entry is generated (BrowserBuilder, UWPBuilder, or EntryBuilder shorthand), archive the generated form by copying it from the artifact underAssembler/Entries/and adding aSkip=key to its source section. - In your PR, note why the software has been archived (e.g. the vendor site is gone or a live service has been discontinued).
General rules
Software availability
Entries are generally accepted for any software currently available for download. Direct vendor downloads are preferred; entries for software only available through download aggregators (e.g. Softonic, Uptodown) will be accepted, but entries are periodically audited, and software no longer available from its original vendor may be moved to the archive at Winapp3/Archived entries.ini (see Retiring an entry).
Categorization
- Games and directly gaming-related software (launchers, modding tools, ancillary utilities, etc.) must use
Section=Games. - Web browsers are primarily generated entries. Their categorization is handled in the
BrowserInfosection for that browser (see Browser entries). - Everything else should use the most appropriate
LangSecRef. PreferLangSecRefoverSectionwhen a standard CCleaner category fits. See the table in Standard entries for valid values.
Safety
Entries should clean transient, rebuildable data such as caches, logs, temporary files, recently-used lists or similar. Don't target settings, configurations, or anything a user would expect to survive a clean.
Standard entries
Standard entries cover desktop (Win32) applications that are not web browsers and do not have UWP versions. They use standard winapp2.ini syntax and live in Assembler/EntryBuilder/.
Where to edit
Each file in Assembler/EntryBuilder/ contains entries whose names begin with a particular letter. Add your entry to the file matching the first letter of the entry name. Numbers and symbols go in #.ini.
Entry name
Entry names must end with *]: a space, an asterisk, and a closing bracket. This trailing * is required.
[Application Name *]
Style rules
Run WinappDebug on your entry before submitting to catch style and syntax issues. Many common issues can be automatically repaired by WinappDebug.
| Rule | Detail |
|---|---|
| Alphabetical order | Entries must be sorted alphabetically within the file. Numbers and symbols sort before letters. |
| Key order | Within each entry: categorization → detection → warnings → deletion. Within a group, keys of the same type come before keys of a different type in alphabetical order by key name (Detect before DetectFile), and keys of the same type are sorted numerically by their index. |
| Key numbering | Keys of the same type are numbered sequentially starting from 1 with no gaps (FileKey1, FileKey2, ...). Detect and DetectFile may omit the 1 in the case that there's only a single key. FileKey, RegKey, and ExcludeKey always have numbers, even when there is only one |
| No blank lines within an entry | A single blank line separates entries from each other. No blank lines inside an entry. Winapp2ool will automatically remove blank lines from inside entries. |
| No trailing whitespace | Lines must not have trailing spaces or tabs. |
| Use environment variables | All filesystem paths must use environment variables. Never use hardcoded drive letters. |
| Comments are welcome where helpful | A comment is a line beginning with ; placed directly above an entry. Use one to record context future maintainers will need, such as why an unusual path is targeted. Comments live permanently in the source files but are stripped from the generated artifacts and the final winapp2.ini. |
Valid LangSecRef values
LangSecRef values are defined by CCleaner v6.39 and some (but not all) are supported by other tools. Values marked "CCleaner only" are not supported by other tools and will display the number instead of the CCleaner section heading.
| LangSecRef | CCleaner section | Notes |
|---|---|---|
| 3001 | Internet Explorer | Deprecated |
| 3005 | Microsoft Edge (legacy) | Deprecated |
| 3006 | Edge Chromium | Called Microsoft Edge in BleachBit |
| 3021 | Applications | |
| 3022 | Internet | |
| 3023 | Multimedia | |
| 3024 | Utilities | |
| 3025 | Windows | Called Microsoft Windows in BleachBit |
| 3026 | Firefox | |
| 3027 | Opera | |
| 3028 | Safari | |
| 3029 | Google Chrome | |
| 3030 | Thunderbird | |
| 3031 | Windows Store | |
| 3032 | CCleaner Browser | CCleaner only |
| 3033 | Vivaldi | |
| 3034 | Brave | |
| 3035 | Opera GX | CCleaner only |
| 3036 | Spotify | CCleaner only |
| 3037 | Avast Secure Browser | CCleaner only |
| 3038 | AVG Secure Browser | CCleaner only |
| 3039 | Arc Browser | CCleaner only |
| 3040 | iTunes | CCleaner only |
| 3042 | CCleaner only | |
| 3043 | Norton Private Browser | CCleaner only |
| 3044 | Avira Secure Browser | CCleaner only |
Note: 3041 is not a valid LangSecRef value.
Key syntax reference
Categorization
Required (exactly one). Defines the UI category the entry appears under.
Examples
LangSecRef=3021
Section=Games
Detection
At least one Detect or DetectFile key is required.
Detection keys control whether or not an entry is displayed to the user. If at least one detection key matches a path, file, or registry key on the current system, the entry is displayed.
Scope detection keys to the target application as tightly as possible to avoid false positives. You may wish to capture individual versions or all of them, depending on the scope of the entry.
The last path segment of a DetectFile accepts wildcards.
Nested wildcards are not supported by DetectFile in any tool except winapp2ool.
Detect (registry) paths do not support wildcards.
System Ninja does not support wildcards anywhere within a DetectFile.
Examples
Detect1=HKCU\Software\Vendor\AppName
Detect2=HKCU\Software\Vendor\AppName\AppVersion
DetectFile1=%LocalAppData%\Vendor\AppName
DetectFile2=%LocalAppData%\Vendor\AppName\AppVersion\App.exe
Warnings
Optional. Shows a message when the cleaning routine moves from unchecked to checked in the UI. Many users skip them, so keep warnings short and specific.
Not supported by System Ninja or R-Wipe&Clean
Warning=This will delete your saved session data.
Deletion
At least one required. Use FileKey for filesystem paths and RegKey for registry paths.
FileKey Example
FileKey1=%LocalAppData%\App\Temp|*.tmp
FileKey2=%LocalAppData%\App\Cache|*|RECURSE
FileKey3=%LocalAppData%\App\OldVersions|*|REMOVESELF
- A
|separates the path from the pattern. - Multiple patterns in one key:
FileKey1=%Path%|file1.log;file2.log;*.tmp RECURSEdeletes matching files in all subdirectories. In CCleaner, also deletes empty subdirectories when provided*.*REMOVESELFdoes the same as RECURSE, but always removes empty subdirectories left behind. Implies RECURSE. Will delete the parent folder if it is empty when the clean completes.
RegKey Example
RegKey1=HKCU\Software\App\RecentFiles
RegKey2=HKCU\Software\App\Settings|LastOpenedPath
A |value suffix deletes only that named value, not the key itself.
RegKey does not support wildcards.
Exclusions
Optional. Preserves specific files or registry keys from deletion. Prefer tightening deletion keys over adding exclusions.
ExcludeKey1=FILE|%AppData%\App\|important.db
ExcludeKey2=PATH|%AppData%\App\|*.cfg
ExcludeKey3=REG|HKCU\Software\App\Preserve
FILEexcludes a specific named file from deletionPATHexcludes files matching a wildcard pattern; covers the directory and all subdirectoriesREGexcludes a registry key and all values and subkeys beneath it
ExcludeKey has no RECURSE or REMOVESELF equivalent. Subdirectories are covered by use of the PATH flag.
Complete example
[Example Application *]
LangSecRef=3021
Detect=HKCU\Software\Example\ExampleApp
FileKey1=%LocalAppData%\Example\ExampleApp\Cache|*|REMOVESELF
FileKey2=%LocalAppData%\Example\ExampleApp\Logs|*.log
RegKey1=HKCU\Software\Example\ExampleApp\RecentFiles
Environment variables
All filesystem paths must use environment variables. Never use hardcoded drive letters.
Variables marked with * check both 64-bit and 32-bit locations on 64-bit systems.
Variables marked "CCleaner only" do not expand to anything in other tools and will not work with them. Avoid using CCleaner-only variables in submissions.
| Variable | Windows Vista–11 path | Notes |
|---|---|---|
%AppData% | C:\Users\%UserName%\AppData\Roaming | |
%CommonAppData% | C:\ProgramData | CCleaner only |
%CommonProgramFiles%* | C:\Program Files\Common Files | |
%Documents% | C:\Users\%UserName%\Documents | CCleaner only |
%LocalAppData% | C:\Users\%UserName%\AppData\Local | |
%LocalLowAppData% | C:\Users\%UserName%\AppData\LocalLow | CCleaner only |
%Music% | C:\Users\%UserName%\Music | CCleaner only |
%Pictures% | C:\Users\%UserName%\Pictures | CCleaner only |
%ProgramData% | C:\ProgramData | |
%ProgramFiles%* | C:\Program Files | |
%Public% | C:\Users\%UserName%\Public | |
%SystemDrive% | C: | |
%UserProfile% | C:\Users\%UserName% | |
%Video% | C:\Users\%UserName%\Videos | CCleaner only |
%WinDir% | C:\Windows |
Registry variables
| Variable | Registry hive |
|---|---|
HKCR | HKEY_CLASSES_ROOT |
HKCU | HKEY_CURRENT_USER |
HKLM | HKEY_LOCAL_MACHINE |
HKU | HKEY_USERS |
HKCC | HKEY_CURRENT_CONFIG |
Keys not accepted in contributions
The following keys are valid CCleaner-only syntax but are not used in winapp2.ini and should not appear in submitted entries.
| Key | Notes |
|---|---|
Default | Controls whether an entry is enabled by default in CCleaner. All winapp2.ini entries are opt-in. |
DetectOS | Limits an entry to specific Windows versions by kernel number. CCleaner only. |
SpecialDetect | Uses CCleaner's internal application detection patterns. CCleaner only. Deprecated. |
Browser entries
Web browser entries are generated automatically by winapp2ool's BrowserBuilder module. Do not add browser entries manually to Assembler/EntryBuilder/. Instead, edit the files in Assembler/BrowserBuilder/.
How BrowserBuilder works
BrowserBuilder reads two files, chromium.ini and gecko.ini, and generates a cleaning entry for every browser/category combination described in them. Each browser is a [BrowserInfo: Browser Name] section. Each cleaning category (Caches, Cookies, History, etc.) is an [EntryScaffold: Category Name] section. BrowserBuilder produces one entry per browser per category.
After generating the base entries, BrowserBuilder applies corrections from the browser flavor files to handle cases where the generated output is wrong or incomplete for specific browsers.
Adding a new browser
To add a new Chromium-based browser, add a [BrowserInfo: Browser Name] section to chromium.ini. For a Gecko-based browser, add to gecko.ini. Place the section alphabetically by browser name within the file.
Required keys
| Key | Purpose |
|---|---|
Section= | The CCleaner section name for all generated entries for this browser. Use the format Browser Name Web Browser to group entries under their own section. Sections beginning with a number will fail to display correctly in CCleaner. Prepend them with a . eg. .360 Secure Web Browser |
UserDataPath= | The filesystem path to the directory containing the browser's user profile data. For Chromium browsers this is the User Data folder. For Gecko browsers this is the Profiles folder. This path is also used to generate a DetectFile for every entry. |
Optional keys
| Key | Purpose |
|---|---|
RegistryRoot= | The registry root key for this browser. Multiple values can be provided on separate lines. If omitted, RegKeys won't be created and EntryScaffolds carrying a RequiresRegistryRoot key will skip this browser. |
TruncateDetect= | Provide this key (any value) to strip \User Data\ from the generated DetectFile. Required when the UserDataPath contains a wildcard in the direct parent directory name. This value appears boolean but it is not, provide this key if and only if you want the DetectFile truncated. |
Skip= | Provide this key (any value) to exclude this browser from generation. Used to retire support without losing the configuration. This value appears boolean but it is not, provide this key if and only if you want the entry skipped |
Multiple UserDataPath= and RegistryRoot= values are supported; list them as separate keys.
Style rules
| Rule | Detail |
|---|---|
| Section name format | Must be [BrowserInfo: Browser Name] exactly. |
| Alphabetical order | Sections must be sorted alphabetically by browser name within the file. |
| No trailing whitespace | Lines must not have trailing spaces or tabs. |
Chromium example
[BrowserInfo: Example Browser]
Section=Example Web Browser
UserDataPath=%LocalAppData%\Example\ExampleBrowser\User Data
RegistryRoot=HKCU\Software\Example\ExampleBrowser
[BrowserInfo: Example Browser 2]
Section=Example Web Browser 2
UserDataPath=%LocalAppData%\RegistryLess\Browser\User Data
TruncateDetect Example
When a TruncateDetect key is provided, BrowserBuilder drops the last directory in the generated DetectFile to avoid problems with the CCleaner DetectFile parser.
Note: DetectFile keys containing a wildcard generated with TruncateDetect are still incompatible with System Ninja due to System Ninja not supporting wildcards in DetectFile.
[BrowserInfo: Brave]
Section=Brave Web Browser
TruncateDetect=True
UserDataPath=%LocalAppData%\BraveSoftware\Brave-Browser*\User Data
RegistryRoot=HKCU\Software\BraveSoftware\Brave-Browser
RegistryRoot=HKCU\Software\BraveSoftware\Brave-Browser-Beta
RegistryRoot=HKCU\Software\BraveSoftware\Brave-Browser-Nightly
Generated DetectFile
DetectFile=%LocalAppData%\BraveSoftware\Brave-Browser*
Gecko-specific variables
Gecko's gecko.ini supports an additional inferred variable in EntryScaffold patterns:
%LocalDataPath%: Gecko profile user data is stored in a folder located within%AppData%. Cache data is stored in a folder by the same name in%LocalAppData%. The%LocalAppData%path is inferred from%UserDataPath%.
This is handled automatically and requires no action from contributors adding a Gecko browser.
Applying corrections to generated browser entries
Generated entries aren't always right for every browser. The correction files let you fix or extend individual entries without touching the scaffolds.
Section names in correction files must exactly match the generated entry name, which follows the pattern Browser Name Category * (e.g. Brave Caches *).
BrowserBuilder corrections use the same Flavorize winapp2ool module as the tool-specific flavors. These files live in /Assembler/BrowserBuilder/
When to use each file
| File | Use when |
|---|---|
1. browser_section_removals.ini | An entire generated entry does not apply to a specific browser. |
2. browser_name_removals.ini | A specific key name should be removed from a browser's entry. Number-sensitive match, key numbers must match. (eg. FileKey3= won't remove FileKey1=) |
3. browser_value_removals.ini | A specific key value is wrong for a browser regardless of which numbered key it appears on. Write the key with the target value; the number you give it is irrelevant. (eg. FileKey=some\path |
4. browser_section_replacements.ini | The generated entry for a browser is so different from the default that it needs to be replaced entirely. |
5. browser_key_replacements.ini | A specific key needs a different value for a browser (exact name and section match). |
6. browser_additions.ini | A browser needs extra keys beyond what the scaffold generates, or needs an entirely new entry that BrowserBuilder does not produce. |
Style rules for correction files
| Rule | Detail |
|---|---|
| Section name must match exactly | The section name must match the generated entry name precisely, including the *] suffix. |
| Include a comment | Add a brief comment above each correction explaining why it is needed. A comment is a line which begins with ; and appears directly above an entry. |
| Keys only in the right files | browser_section_removals.ini ignores key content. Only the section name matters. browser_name_removals.ini ignores key values. Only the name matters. Follow each file's rules. |
| No trailing whitespace | Lines must not have trailing spaces or tabs. |
Addition example
; Example Browser stores crash reports in a non-standard location not covered by the scaffold
[Example Browser Telemetry *]
FileKey1=%LocalAppData%\Example\ExampleBrowser\CrashReports|*|REMOVESELF
Section removal example
Section removals are performed on a name-only basis and need not contain any keys. Any provided keys will be ignored.
; Example Browser does not support pinned tabs
[Example Browser Pinned Tabs *]
Adding new EntryScaffolds
Adding a new EntryScaffold (a new cleaning category applied across all browsers) is possible. New scaffolds must be consistent: if the data exists across all browsers, the scaffold should generate correct entries for all of them, or corrections must be provided for browsers where it does not apply.
Every EntryScaffold section name must follow the format [EntryScaffold: Category Name]. The category name is appended to the browser name: [EntryScaffold: Example Category] produces entries named Browser Name Example Category *.
Keys
| Key | Purpose |
|---|---|
FileKeyBase= | A FileKey template. BrowserBuilder substitutes browser-specific variables and adds the result as a numbered FileKey in the generated entry. Multiple values are supported; list them as separate keys. |
RegKeyBase= | A RegKey template. BrowserBuilder substitutes %RegistryRoot% and adds the result as a numbered RegKey. Multiple values are supported. |
RequiresRegistryRoot= | BrowserBuilder skips this scaffold for any browser without a RegistryRoot= key. |
A scaffold with neither FileKeyBase= nor RegKeyBase= produces no output.
Variables
Each template variable resolves to a value from the browser's BrowserInfo section.
| Variable | Available in | Expands to |
|---|---|---|
%UserDataPath% | FileKeyBase | The browser's user data directory, as declared by UserDataPath= in its BrowserInfo section. |
%BrowserPath% | FileKeyBase | The parent directory of %UserDataPath%. For Chromium browsers, also generates a second FileKey with the path mirrored under %ProgramFiles%. |
%LocalDataPath% | FileKeyBase (Gecko only) | The cache directory inferred from %UserDataPath% by substituting %LocalAppData% for %AppData%. |
%RegistryRoot% | RegKeyBase | The browser's registry root path, as declared by RegistryRoot= in its BrowserInfo section. Expands once per RegistryRoot= value, producing one RegKey per root. |
Example
[BrowserInfo: Example Browser]
Section=Example Web Browser
UserDataPath=%AppData%\Example Browser\User Data
RegistryRoot=HKCU\Software\ExampleBrowser
[EntryScaffold: Example Category]
FileKeyBase=%UserDataPath%\*\ExampleData|*|REMOVESELF
FileKeyBase=%BrowserPath%\Application|example.log
RegKeyBase=%RegistryRoot%\ExampleKey
[Example Browser Example Category *]
Section=Example Web Browser
FileKey1=%AppData%\Example Browser\User Data\ExampleData|*|REMOVESELF
FileKey2=%AppData%\Example Browser\Application|example.log
RegKey1=HKCU\Software\ExampleBrowser\ExampleKey
UWP entries
UWP entries cover Universal Windows Platform applications generally installed from the Microsoft Store. They are generated by winapp2ool's UWPBuilder module and live in Assembler/UWP/AppInfo/.
How UWPBuilder works
UWPBuilder reads Assembler/UWP/UWP.ini (the baseline cleaning scaffold applied to every UWP app) alongside all 27 alphabetical AppInfo files. For each application, it generates a complete winapp2.ini entry by combining the scaffold's FileKeyBase patterns with app-specific keys, substituting the app's package folder name wherever %Package% appears.
[EntryScaffold: UWP App]
DetectFileBase=%Package%
FileKeyBase=%Package%\AC|*|RECURSE
FileKeyBase=%Package%\Settings|*.log*
FileKeyBase=%Package%\SystemAppData\Helium|*.log*
FileKeyBase=%Package%\TempState|*|REMOVESELF
The baseline scaffold above targets the standard UWP storage locations present in nearly every UWP application:
\AC\: Application cache\Settings\*.log*: Settings logs\SystemAppData\Helium\*.log*: Helium logs\TempState\: Temporary state
Likewise, it also creates one DetectFile per provided package.
UWPBuilder adds app-specific keys after the scaffold keys.
Where to edit
Add your entry to Assembler/UWP/AppInfo/<letter>.ini, where <letter> is the first letter of the application name. Numbers and symbols go in #.ini.
Finding the package folder name
The package folder name is the value for the Package= key. It is the name of the application's folder under %LocalAppData%\Packages\. You can find it by:
- Browsing
%LocalAppData%\Packages\in Explorer and looking for a folder matching the application name. - Running
Get-AppxPackage | Where-Object {$_.Name -like "*AppNameHere*"}in PowerShell. ThePackageFamilyNamefield gives you the folder name.
For multi-package applications, list each package folder separately as Package1=, Package2=, etc.
Style rules
| Rule | Detail |
|---|---|
| Section name format | Must be [Application Name *] the trailing * is required. This is the name that the generated entry will have. |
| Alphabetical order | Entries must be sorted alphabetically within the file. |
| Categorization | Exactly one of LangSecRef= or Section= is required. Use Section=Games for games and gaming-related apps. |
| Package key | At least one Package= key is required. Single-package apps use Package=. Multi-package apps use Package1=, Package2=, etc. |
| No trailing whitespace | Lines must not have trailing spaces or tabs. |
| No blank lines within an entry | A single blank line separates entries from each other. |
Supported keys
| Key | Required | Purpose |
|---|---|---|
Package= | Yes (at least one) | Package folder name under %LocalAppData%\Packages\. |
LangSecRef= or Section= | Yes (exactly one) | Categorization. |
Detect=, Detect1, Detect2=, ... | No | Additional registry detection criteria. Passed through verbatim and renumbered. |
DetectFile= | No | Additional filesystem detection criteria. Useful for hybrid win32+UWP apps. Each package folder is always generated as a DetectFile due to the root UWP.ini's scaffold containing DetectFileBase=%Package% |
FileKeyBase= | No | App-specific FileKey templates using %Package% or %PackageN% variables. Added after the scaffold keys. This is a stylistic choice only, and providing a FileKey will also work. |
FileKey= | No | Standard winapp2.ini FileKey targeting win32 or non-package locations. Can also use %Package% variables. This is a stylistic choice only, and providing a FileKeyBase will also work. |
RegKey= | No | Standard winapp2.ini RegKey. Passed through verbatim and renumbered. |
ExcludeKey= | No | Standard winapp2.ini ExcludeKey. Can use %Package% variables. |
Skip= | No | Provide this key (any value) to exclude the app from generation without removing its configuration. This value appears boolean but it is not, provide this key if and only if you want the entry skipped |
The %Package% variable
In FileKeyBase=, FileKey=, and ExcludeKey= values, %Package% expands to the full path %LocalAppData%\Packages\<PackageFolderName> in the generated output.
For multi-package apps, %Package% expands to each of the packages. Use %Package1%, %Package2%, etc. to target a specific package.
Single-package example
UWP AppInfo Input
[Example UWP App *]
LangSecRef=3024
Package=ExampleCorp.ExampleApp_abc123xyz
FileKeyBase=%Package%\LocalCache\Local\Logs|*.log
UWPBuilder output (after linting)
[Example UWP App *]
LangSecRef=3024
DetectFile=%LocalAppData%\Packages\ExampleCorp.ExampleApp_abc123xyz
FileKey1=%LocalAppData%\Packages\ExampleCorp.ExampleApp_abc123xyz\AC|*|RECURSE
FileKey2=%LocalAppData%\Packages\ExampleCorp.ExampleApp_abc123xyz\LocalCache\Local\Logs|*.log
FileKey3=%LocalAppData%\Packages\ExampleCorp.ExampleApp_abc123xyz\Settings|*.log*
FileKey4=%LocalAppData%\Packages\ExampleCorp.ExampleApp_abc123xyz\SystemAppData\Helium|*.log*
FileKey5=%LocalAppData%\Packages\ExampleCorp.ExampleApp_abc123xyz\TempState|*|REMOVESELF
Multi-package example
UWP AppInfo Input
[Multi-Package App *]
LangSecRef=3021
Package1=Vendor.AppCore_abc123
Package2=Vendor.AppService_def456
FileKeyBase=%Package%\LocalCache\Local\Logs|*.log
FileKeyBase=%Package2%\LocalState\Logs|*.log
FileKey=%ProgramData%\Vendor\AppService\Logs|*
UWPBuilder output (after linting)
[Multi-Package App *]
LangSecRef=3021
DetectFile1=%LocalAppData%\Packages\Vendor.AppCore_abc123
DetectFile2=%LocalAppData%\Packages\Vendor.AppService_def456
FileKey1=%LocalAppData%\Packages\Vendor.AppCore_abc123\AC|*|RECURSE
FileKey2=%LocalAppData%\Packages\Vendor.AppCore_abc123\LocalCache\Local\Logs|*.log
FileKey3=%LocalAppData%\Packages\Vendor.AppCore_abc123\Settings|*.log*
FileKey4=%LocalAppData%\Packages\Vendor.AppCore_abc123\SystemAppData\Helium|*.log*
FileKey5=%LocalAppData%\Packages\Vendor.AppCore_abc123\TempState|*|REMOVESELF
FileKey6=%LocalAppData%\Packages\Vendor.AppService_def456\AC|*|RECURSE
FileKey7=%LocalAppData%\Packages\Vendor.AppService_def456\LocalCache\Local\Logs|*.log
FileKey8=%LocalAppData%\Packages\Vendor.AppService_def456\LocalState\Logs|*.log
FileKey9=%LocalAppData%\Packages\Vendor.AppService_def456\Settings|*.log*
FileKey10=%LocalAppData%\Packages\Vendor.AppService_def456\SystemAppData\Helium|*.log*
FileKey11=%LocalAppData%\Packages\Vendor.AppService_def456\TempState|*|REMOVESELF
FileKey12=%ProgramData%\Vendor\AppService\Logs|*
This generates DetectFile entries for both packages. The scaffold is applied once per package. %Package2% targets only the second package in the app-specific FileKey.
Hybrid win32 + UWP example
Some applications have both a traditional desktop (Win32) installer and a Microsoft Store (UWP) release. Winapp2.ini bundles these into a single entry generated through the UWP process. Win32-targeted paths use FileKey= alongside the package-targeted FileKeyBase= entries.
UWP AppInfo Input
[Hybrid App *]
LangSecRef=3021
Package=Vendor.HybridApp_ghi789
DetectFile=%LocalAppData%\Vendor\HybridApp
FileKeyBase=%Package%\LocalState\Cache|*|RECURSE
FileKey=%LocalAppData%\Vendor\HybridApp\Cache|*|RECURSE
FileKey=%LocalAppData%\Vendor\HybridApp\Logs|*.log
UWPBuilder Output
[Hybrid App *]
LangSecRef=3021
DetectFile1=%LocalAppData%\Packages\Vendor.HybridApp_ghi789
DetectFile2=%LocalAppData%\Vendor\HybridApp
FileKey1=%LocalAppData%\Packages\Vendor.HybridApp_ghi789\AC|*|RECURSE
FileKey2=%LocalAppData%\Packages\Vendor.HybridApp_ghi789\LocalState\Cache|*|RECURSE
FileKey3=%LocalAppData%\Packages\Vendor.HybridApp_ghi789\Settings|*.log*
FileKey4=%LocalAppData%\Packages\Vendor.HybridApp_ghi789\SystemAppData\Helium|*.log*
FileKey5=%LocalAppData%\Packages\Vendor.HybridApp_ghi789\TempState|*|REMOVESELF
FileKey6=%LocalAppData%\Vendor\HybridApp\Cache|*|RECURSE
FileKey7=%LocalAppData%\Vendor\HybridApp\Logs|*.log
EntryBuilder entries
EntryBuilder is the winapp2ool module that turns the base entry sources in Assembler/EntryBuilder/<letter>.ini into the artifacts in Assembler/Entries/. Every base entry lives in an EntryBuilder source file. Standard winapp2.ini syntax passes through generation unchanged, so for most contributions the folder is simply where base entries live; an optional shorthand DSL is additionally available.
You do not need to learn the shorthand to contribute.
- Adding an entry? Write a standard entry in
Assembler/EntryBuilder/<letter>.ini. When in doubt, always contribute standard syntax. If shorthand would benefit the entry, maintainers will help convert it during review. - Fixing an existing entry? Edit its source in
Assembler/EntryBuilder/, in standard syntax. Any valid winapp2.ini key passes through EntryBuilder unchanged. Leave any shorthand keys you don't recognize as they are rather than rewriting them. - Want to use the shorthand? Welcome, but never required. The EntryBuilder readme documents the full DSL: list variables with
<Name>token fan-out, and scaffold families for applications embedding WebView2 or QtWebEngine.
The Scaffolds directory
Assembler/Scaffolds/ holds shared catalogs of cleaning patterns (webview.ini, qtwebengine.ini) drawn on by EntryBuilder and UWPBuilder. A change to a scaffold catalog affects every entry that uses it. Open an issue before editing these files.
Winapp3.ini
Winapp3/Winapp3.ini is an extension to winapp2.ini for power users. It uses identical syntax to standard winapp2.ini entries. Entries target operations that are more aggressive, broader in scope, or otherwise carry a higher risk of unintended data loss than entries in the main database. Users should understand what an entry does before enabling it.
Contributions to Winapp3.ini are subject to additional scrutiny. Entries must be clearly scoped, accurately described, and appropriate for a knowing power user. Include a Warning= key for entries that could affect application functionality.
Edit Winapp3/Winapp3.ini directly. The same style rules as standard entries apply.
Flavor corrections
Flavors are custom builds of winapp2.ini with certain tweaks applied to make it more compatible with particular tools.
Each flavor is built by applying a set of Transmute operations (structured changes in the form of additions, removals, and substitutions) to the base file. Correction files for each flavor live in Assembler/<FlavorName>/. If you find a flavor-specific problem or shortcoming, you can submit changes to these files or open an issue.
Each flavor directory contains the same six file types:
| File | What it does |
|---|---|
*_section_removals.ini | Removes entire entries from the flavor output. |
*_name_removals.ini | Removes specific keys from entries by key name (number-sensitive). |
*_value_removals.ini | Removes specific keys from entries by exact value match (number-insensitive). |
*_section_replacements.ini | Replaces entire entries in the flavor output. |
*_key_replacements.ini | Replaces specific keys in entries. |
*_additions.ini | Adds new entries or appends keys to existing entries. |
Corrections are applied in the order listed above. The same style rules apply as for the equivalent browser correction files: section names must exactly match the target entry name. Comments are helpful in the flavor files and will not be compiled into the final winapp2.ini.
Some flavor files also contain sections named [*] or [*Map: label]. These are Transmute global operations: rules applied against every entry in the file rather than one named section (for example, remapping browser Section= values to their CCleaner LangSecRef numbers across all generated browser entries). Leave these sections alone unless you understand how they work. See the Transmute readme for the full specification.
How to submit
Pull request: The preferred method. Fork the repository, make your changes to the appropriate source files in Assembler/, Winapp3/, or wherever relevant, and open a pull request against the master branch. Describe what changed and why.
No git experience? You can contribute entirely from your browser: navigate to the source file on GitHub, click the pencil icon ("Edit this file"), make your change, and choose "Propose changes". GitHub creates the fork and the pull request for you. Most contributions are single-file edits, and this workflow handles them fine.
Issue: If you found a problem but aren't comfortable making the change yourself, an issue works just as well. Include enough detail (application name, affected paths, what is wrong or missing) for maintainers to act on it.
What to include in your PR
Commit source files only. Do not include build outputs:
- any flavor of
winapp2.ini, or anydiff.txt - anything under
Assembler/Entries/: every file there opens with a header sayingDO NOT EDIT THIS FILE DIRECTLYand naming its source
The build regenerates all of these files from your source change after it merges.
The reliable way to do this is to stage your source files by name:
git add "Assembler/EntryBuilder/A.ini"
git commit -m "add an entry for Example App"
Avoid git add -A and git add ..
If you ran the full build to check your work, your working copy now contains 29 regenerated artifacts plus all seven rebuilt published outputs.
The generated artifact guard will tell you, and git restore on the files it names will fix it
Verifying your work
This is entirely optional, and you can open a PR without doing any of it. CI builds your PR and reports back, and a maintainer reviews it either way.
Everything below requires winapp2ool. It is also attached to every release.
If you edited a generator's source files, regenerate its output before linting. In every case, finish by running WinappDebug on the file in the last column:
| You edited | Generate with | Menu path | File to lint |
|---|---|---|---|
Assembler/EntryBuilder/<letter>.ini | EntryBuilder | 6 (Entry Lab), then 3 | entrybuilder.ini |
Assembler/BrowserBuilder/... | BrowserBuilder | 6 (Entry Lab), then 1 | browsers.ini |
Assembler/UWP/AppInfo/<letter>.ini | UWPBuilder | 6 (Entry Lab), then 2 | uwp.ini |
Each builder's README covers usage in depth.
Launch Winapp2ool and input 1 to open WinappDebug. Point it at the file from the table above. A single source file or generated output works directly; you do not need a built winapp2.ini. Make any corrections necessary (or allow WinappDebug to make them if possible) such that your entries do not cause any errors. WinappDebug is a static analysis tool that catches and repairs a wide variety of style and syntax issues in winapp2.ini. See the WinappDebug README (linked above) for usage guidance.
Running the full build
CI runs this on every PR, but you can run it locally too
- Clone the repo. The build script runs from the
Assembler/directory and finds and places each flavor of winapp2.ini via relative paths; it will fail without the surrounding directory structure. - Make your changes to the source files.
- Run
& '.\build winapp2.ps1'from PowerShell inAssembler/. If you get an execution policy error, runSet-ExecutionPolicy -Scope Process RemoteSigned. A clone already contains thewinapp2ool.exethe script needs. - Open the built
winapp2.ini(each flavor is written to its home location) and check that your entry is there and looks the way you expected. - Optionally, drop the built
winapp2.iniinto a cleaning tool and scan with it to confirm your entry targets what you expected and nothing else. Then run the clean and verify that what should survive did.
The build rewrites all 29 artifacts under Assembler/Entries/ and all seven published output files in your working copy. Rather than cleaning that up afterwards, stage your source files by name and ignore the rest.
& '.\build winapp2.ps1' -Verify is the maintainer-side variant: it builds nothing, regenerating every artifact into a scratch folder and byte-comparing against the committed Assembler/Entries/ files instead, and failing on any mismatch. CI runs it automatically on every push to catch artifacts that have drifted from their sources (e.g. bad generator output).
What happens after you open a PR
Two automated checks run against your pull request. Neither needs anything from you beyond the PR itself, and a maintainer always reviews your change.
The generated artifact guard
Runs on every PR. It checks one thing: that you edited sources rather than build output. It runs in a few seconds
It fails if your PR changes a generated file without changing the source that produces it. When it fails, it marks the offending files directly in the Files changed tab, each with a message naming the source file to edit instead:
Assembler/Entries/A.inigenerated by EntryBuilder; editAssembler/EntryBuilder/A.iniinstead
To fix it, move your edit into the named source file and git restore the generated one. You never need to run winapp2ool or regenerate anything to make this check pass.
The PR build
If your PR touches anything under Assembler/, a bot builds winapp2.ini twice: once from master alone, then again with your change merged in, and posts a single comment that it updates on each push. It tells you one of:
- The PR builds cleanly, followed by the changelog your change produces. Read it as a description of what your change does to the published file, and check it matches what you intended.
- The build failed, with the output showing where. Usually a syntax error in an edited source file.
- The PR no longer merges cleanly with
master, which you fix by updating your branch.
PRs that only touch Winapp3/ get no build comment. Winapp3.ini is not assembled by the build, so there is nothing to build. That is expected, not a problem with your PR.
After merge
You don't need to do anything else. A scheduled workflow rebuilds winapp2.ini and every flavor from the updated sources, commits the results, and publishes a tagged release with each flavor and its changelog attached. Typically, this is within a day of your merge.