windowsweep 1.3.2 → 1.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,7 +3,7 @@
3
3
  This is the contract an automated caller can rely on: what windowsweep promises, what it refuses, what it
4
4
  prints, and what it returns. It is written for an agent or a script rather than a person. For what the tool
5
5
  *is*, read the [README](https://github.com/aoneahsan/windowsweep#readme); for what each section touches, read
6
- [Sections 0-25](https://github.com/aoneahsan/windowsweep/blob/main/docs/sections.md).
6
+ [Sections 0-29](https://github.com/aoneahsan/windowsweep/blob/main/docs/sections.md).
7
7
 
8
8
  **windowsweep deletes files.** Every command below that is not marked read-only can remove data. There is no
9
9
  undo for caches. Treat a real run as an irreversible operation and preview it first.
@@ -22,17 +22,17 @@ summary**, and every human-readable line goes to stderr. `--json` also implies `
22
22
 
23
23
  ## What `--yes` covers, and what it never covers
24
24
 
25
- `--yes` auto-confirms **regenerable caches only**: sections 0-3, 5-10, 21, and 12-13 when the console is
25
+ `--yes` auto-confirms **regenerable caches and superseded releases only**: sections 0-3, 5-10, 21, 28, and 12-13 when the console is
26
26
  already elevated.
27
27
 
28
28
  | Never covered by `--yes` | Behaviour |
29
29
  |---|---|
30
- | Sections 17, 18, 19, 23 | The selection prompt appears even with `--yes` and defaults to none. With no console attached nothing is selected, and each asks a final question `--yes` does not answer. Only `--select` / `--select-file` supply a choice (see below) |
31
- | Sections 11, 15, 16, 20 | Deep. Refused in batch mode unless `--i-understand-deep` is also passed |
30
+ | Sections 17, 18, 19, 23, 26, 27 | The selection prompt appears even with `--yes` and defaults to none. With no console attached nothing is selected, and each asks a final question `--yes` does not answer. Only `--select` / `--select-file` supply a choice (see below) |
31
+ | Sections 11, 15, 16, 20, 29 | Deep. Refused in batch mode unless `--i-understand-deep` is also passed |
32
32
  | `--uninstall-data` | Always asks; `--yes` does not answer it |
33
33
  | `--purge-all` | From a console it asks for a typed `purge` once per run. In a batch run `--yes` is the confirmation |
34
34
 
35
- In batch mode (`--all`, `--only`, `--profile`) sections 17, 18, 19 and 23 are refused outright and reported as
35
+ In batch mode (`--all`, `--only`, `--profile`) sections 17, 18, 19, 23, 26 and 27 are refused outright and reported as
36
36
  `refused`, unless a `--select` or `--select-file` choice was supplied. They need a person choosing items -
37
37
  in advance is fine, absent is not.
38
38
 
@@ -133,7 +133,7 @@ answered by a script, so `--elevate` does not belong in an unattended context.
133
133
  - - **Protected paths are refused regardless of flags**: every drive root, fifteen declared roots (Windows, System32, SysWOW64, both Program Files folders, ProgramData, `C:\Users` with Default and Public, the profile root, and the AppData Roaming, Local and LocalLow folders), 66 protected subtrees, 50 path patterns and 13 file names. Two paths are declared exceptions - `%LOCALAPPDATA%\Android\Sdk\.temp` and `.downloadIntermediates` - and there are no others. No flag bypasses any of it.
134
134
  - **Junctions and symlinks are removed as links, never followed.**
135
135
  - **`--dry-run` and `--scan` write nothing** but the log and the report.
136
- - **Section numbers are a public contract.** 0-25 today; a section may be retired as a no-op, and a number is
136
+ - **Section numbers are a public contract.** 0-29 in the current source; a section may be retired as a no-op, and a number is
137
137
  never reused. Read `--list --json` rather than hard-coding the set.
138
138
  - **Zero runtime dependencies.** The package is PowerShell plus a Node launcher that uses only built-in
139
139
  modules.
@@ -144,7 +144,7 @@ answered by a script, so `--elevate` does not belong in an unattended context.
144
144
  local package and the command fails. Run it from anywhere else.
145
145
  - Do not schedule `npx windowsweep` as a task action. The npx cache is evicted and the task breaks; install
146
146
  globally and use `--install-task`, which refuses under npx for this reason.
147
- - Do not pipe `y` into the tool to force a personal section. Sections 17, 18, 19 and 23 are interactive by
147
+ - Do not pipe `y` into the tool to force a personal section. Sections 17, 18, 19, 23, 26 and 27 are interactive by
148
148
  design and a piped answer selects nothing - pass `--select` or `--select-file` instead, which is the
149
149
  supported way and names exactly what goes.
150
150
  - Do not treat a green `--dry-run` as proof that a real run frees the same amount: an app that is open at run
@@ -152,7 +152,7 @@ answered by a script, so `--elevate` does not belong in an unattended context.
152
152
 
153
153
  ## Driving the interactive sections (1.1.0+)
154
154
 
155
- Sections 17, 18, 19 and 23 refuse to run unattended, because they delete things a person should choose. Two
155
+ Sections 17, 18, 19, 23, 26 and 27 refuse to run unattended, because they delete things a person should choose. Two
156
156
  flags supply that choice in advance, and either one lifts the refusal:
157
157
 
158
158
  ```powershell
package/CHANGELOG.md CHANGED
@@ -9,6 +9,96 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
9
9
 
10
10
  ## [Unreleased]
11
11
 
12
+ ## [1.4.1] - 2026-11-03
13
+
14
+ ### Fixed
15
+
16
+ - The desktop app now reads published release records on start, resume and reconnect. An urgent release blocks an older build immediately; a normal release is announced immediately and required from the next start. Its Update button uses the signed updater.
17
+ - Removed the desktop updater's six-hour network timer. Release broadcasts and lifecycle events trigger the checks.
18
+ - Corrected the package's release notes and documentation for section 19's Recycle Bin rule and section 26's permanent uninstall action.
19
+
20
+ ## [1.4.0] - 2026-11-03
21
+
22
+ ### Added
23
+
24
+ - **Section 26 - uninstall the programs you pick.** It lists the installed programs - never Windows parts,
25
+ runtimes, drivers, hardware software, build kits or patches - and removes the ones you select with their own
26
+ uninstaller, one at a time, silently where the uninstaller has a silent form (MSI, Inno Setup, NSIS, Chromium
27
+ family, WiX bundles, winget, Docker Desktop, Qt, Adobe Creative Cloud, rustup) and in the vendor's own window
28
+ otherwise. A program installed for all users needs an elevated run. After a real uninstall it offers the
29
+ folders the program left for the Recycle Bin. `--yes` never selects here; `--select` or `--select-file` does.
30
+ - **Section 27 - folders uninstalled programs left behind.** It lists the top-level folders in Program Files,
31
+ both Common Files and ProgramData that no installed program, service, driver, PATH or environment entry, Run
32
+ entry, shortcut, scheduled task or running process still uses and that have been idle `--days`, and moves the
33
+ ones you pick to the Recycle Bin. A folder inside a protected location is shown, never removed, and an
34
+ unreadable registry offers nothing. Registered COM servers and type libraries count as use too (shared Office
35
+ and ADO components live in Common Files and are registered only that way), and shared Microsoft folders,
36
+ install caches and hardware-driver folders are never offered. It also lists environment entries that name
37
+ something that no longer exists (report only). Administrator; it joins the elevated walkthrough.
38
+ - **`--json` candidates can carry a `label`.** Section 26's program candidates use the program's uninstall
39
+ registry key as their `path` and its name as `label`; the folders it offers after an uninstall carry
40
+ `leftover: <program>`.
41
+ - **Section 4 also clears what emulators leave behind.** It looks in every folder the emulator may keep AVDs in
42
+ (`ANDROID_AVD_HOME`, `ANDROID_EMULATOR_HOME`, `ANDROID_SDK_HOME`, `ANDROID_PREFS_ROOT`), moves pointer `.ini` files
43
+ whose AVD is gone to the Recycle Bin, and removes system images no remaining AVD uses - and the emulator once no
44
+ AVD is left - with the SDK's own `sdkmanager`. An AVD whose settings name no image keeps every image, and a folder
45
+ an interrupted SDK install left is named for you to remove.
46
+ - **`--browser-profile-roots "P1;P2"` (config `browserProfileRoots`) for section 7.** Folders holding test or
47
+ automation browser profiles: section 7 clears the cache folders of each Chromium profile found in them, and skips
48
+ a profile a running browser holds. Only those cache folders are opened up; the profiles stay protected.
49
+ - **`--temp-roots "P1;P2"` (config `tempRoots`) for section 10.** Folders you use as scratch space: each entry
50
+ nothing wrote for `--temp-days` goes whole, unless a running program's command line names it.
51
+ - **Section 24 shows when each program last ran.** In an elevated run it reads Windows Prefetch and adds a RAN
52
+ column; "none" means no run is on record. File names many programs ship (`uninstall.exe`, `update.exe`,
53
+ `setup.exe`, crash handlers) never count, because Prefetch records a run by file name only.
54
+ - **Section 19 is now a data scanner: large or old personal files.** It lists files in Downloads, and in folders
55
+ you add with `--personal-roots "P1;P2"` (config `personalRoots`), that are large (`--large-file-mb` or more, at
56
+ any age) or old (untouched for `--days`, at any size) - each file once, with its reason, age and the timestamps
57
+ that age came from. A folder is refused as a root when it is a drive root, your profile folder, inside Windows,
58
+ Program Files, ProgramData or AppData, a link, or protected. Removal stays yours: exact files only, never by
59
+ `--yes`, always the Recycle Bin - and a file that changed after the list was made, or is now reached through a
60
+ link, is refused. File names and paths stay on your machine. `--json` candidates for section 19 add `reason`
61
+ (`large`/`old`/`both`), `age_basis` (`write` or `write+access`), `modified`, `root` and `selectable` (with
62
+ `skip_reason` and `index` 0 for a file that cannot be picked); the summary adds `personal_roots`.
63
+ - **Section 28 - superseded tool releases and old downloaded updates.** Tools that update themselves often keep
64
+ every old release. This removes the superseded ones and keeps the release in use, any newer one and the newest
65
+ older one; a release a running program uses is skipped. It covers Codex standalone releases, Electron updaters
66
+ named without "@" (installers and pending updates idle 7+ days), Ollama's downloaded update and - in developer
67
+ mode, with `--scan-roots` - Node versions no project asks for, removed with nvm itself. It joins `--all` and the
68
+ `dev` and `deep` profiles.
69
+ - **Section 29 - Chrome's on-device AI model.** Chrome downloads a model of several GB and fetches it again if the
70
+ folder is deleted. This sets the `GenAILocalFoundationalModelSettings` policy that stops the download; Chrome
71
+ then removes the model on its next start, and the folder goes at once when Chrome is closed. Chrome shows
72
+ "Managed by your organization" while the policy is set; the section prints the one-line undo. It is a deep,
73
+ administrator section that no batch or profile runs.
74
+
75
+ ### Changed
76
+
77
+ - **Idle age uses write time where last-access is live.** When nearly every file written a week or more ago
78
+ was also "read" in the last day - an indexer, a backup, an antivirus or a disk scanner reading everything -
79
+ last-access says nothing, and the idle gate used to keep every file. Each root is now sampled once; where
80
+ last-access is live, idle age uses write and creation time, the log says so, and `--json` lists those volumes
81
+ in `access_live_volumes`. Everywhere else the rule is unchanged. The sample walks on until it holds enough old
82
+ files, so a folder of mostly new files - a busy temp folder - is judged on its own and the answer no longer
83
+ depends on which section ran first.
84
+ - **More folders are protected roots.** Both Common Files folders and `ProgramData\Microsoft` can never be
85
+ removed as a whole, whatever an installer registered as its own folder.
86
+
87
+ ### Fixed
88
+
89
+ - **`--exclude-path` now also holds inside the tool's own exceptions.** An exception (the Android SDK temp
90
+ folders, and from this release the superseded Codex releases) used to let a path through even when you had
91
+ excluded it.
92
+ - **Section 23 no longer offers folders that still belong to something.** It offered the desktop app's own
93
+ data folder, a Store app's data, an installed program known by its initials, and a tool running from its
94
+ own folder. A reverse-DNS folder name (`com.vendor.app`) is now matched segment by segment, a shared vendor
95
+ stem counts as a claim, a program of three or more words also claims its initials, and the folders in a
96
+ running program's command-line paths count as claimed. The desktop app's install and data folders are
97
+ protected outright.
98
+ - **`--json` is one line again on every run.** Section 12's Delivery Optimization step printed two lines to
99
+ stdout ahead of the JSON document. Its words now go to the log, and the runner discards anything a section
100
+ leaves on its output stream.
101
+
12
102
  ## [1.3.2] - 2026-09-28
13
103
 
14
104
  No change to what is cleaned, how it is decided, or what is refused: the engine is 1.3.1's, file for file.
package/README.md CHANGED
@@ -4,12 +4,11 @@
4
4
 
5
5
  <h1>windowsweep</h1>
6
6
 
7
- <p><strong>Developer-aware Windows cleanup CLI: dry-run first, personal folders refused, zero install via npx.</strong></p>
7
+ <p><strong>Windows cleanup CLI: dry-run first, personal files chosen row by row, zero install via npx.</strong></p>
8
8
 
9
9
  [![npm version](https://img.shields.io/npm/v/windowsweep.svg)](https://www.npmjs.com/package/windowsweep)
10
10
  [![downloads](https://img.shields.io/npm/dm/windowsweep.svg)](https://www.npmjs.com/package/windowsweep)
11
11
  [![license](https://img.shields.io/npm/l/windowsweep.svg)](https://github.com/aoneahsan/windowsweep/blob/main/LICENSE)
12
- [![ci](https://github.com/aoneahsan/windowsweep/actions/workflows/ci.yml/badge.svg)](https://github.com/aoneahsan/windowsweep/actions/workflows/ci.yml)
13
12
  [![node](https://img.shields.io/node/v/windowsweep.svg)](https://nodejs.org)
14
13
  [![platform](https://img.shields.io/badge/platform-Windows%2010%20%7C%2011-0078d4?logo=windows&logoColor=white)](https://github.com/aoneahsan/windowsweep#platform-support)
15
14
 
@@ -19,10 +18,11 @@
19
18
 
20
19
  > [!IMPORTANT]
21
20
  > **This tool deletes files.** Most of what it removes are caches that rebuild themselves; personal files it
22
- > lists go to the Recycle Bin; and two sections - emptying the Recycle Bin, clearing event logs - are
23
- > permanent, with no undo of any kind. Those two sit behind `--i-understand-deep`, along with the hibernation
21
+ > lists go to the Recycle Bin; emptying the Recycle Bin and clearing event logs have no undo. Those two sit
22
+ > behind `--i-understand-deep`, along with the hibernation
24
23
  > file and disk-image compaction. Start with `npx windowsweep --scan`, which deletes nothing, then
25
24
  > `npx windowsweep --dry-run --all --yes`, which shows exactly what a real run would remove.
25
+ > Uninstalling a program you select in section 26 is permanent too.
26
26
  > **Windows only** - npm refuses to install it elsewhere.
27
27
 
28
28
  What it reclaims is the disk space that quietly disappears on a Windows machine: package-manager and build caches,
@@ -36,14 +36,14 @@ It is the Windows member of a family with [linux-cleanup](https://github.com/aon
36
36
 
37
37
  | | |
38
38
  |---|---|
39
- | **Version** | `1.3.2` |
39
+ | **Version** | `1.4.1` |
40
40
  | **License** | MIT |
41
41
  | **Node** | `>=14` (launcher only) |
42
42
  | **Runtime** | Windows PowerShell 5.1 (built in) or PowerShell 7 |
43
43
  | **Platforms** | Windows 10 (1809+) and Windows 11 |
44
- | **Install size** | ~120 kB packed · ~401 kB unpacked · 46 files · no dependencies |
44
+ | **Install size** | ~167 kB packed · ~560 kB unpacked · 53 files · no dependencies |
45
45
  | **Undo** | Recycle Bin for personal files; none for caches (they regenerate) |
46
- | **Status** | Stable · 1.3.2, released 2026-09-28 |
46
+ | **Status** | Stable · 1.4.1, released 2026-11-03 |
47
47
 
48
48
  <a id="table-of-contents"></a>
49
49
  ## 🧭 Table of Contents&nbsp;[#](#table-of-contents)
@@ -88,7 +88,7 @@ the lot again, and your afternoon is gone. `windowsweep` takes the narrower path
88
88
  |---|---|---|---|
89
89
  | **Knows developer caches** | yarn, npm, pnpm, Gradle, Cypress, Playwright, AVDs, Docker, editors | no | some |
90
90
  | **Default action** | prune files idle 100+ days; keep the newest version of every tool | fixed categories | wipe the whole cache |
91
- | **Personal folders** | hard refusal, no flag bypasses it | out of scope | usually configurable |
91
+ | **Personal folders** | Downloads and folders you add are scanned for large or old files; only chosen files go to the Recycle Bin | out of scope | usually configurable |
92
92
  | **Junctions and symlinks** | never followed | n/a | varies |
93
93
  | **Dry-run** | every section, exact estimate | no | sometimes |
94
94
  | **Unattended use** | `--all --yes`, Scheduled Task | Storage Sense | GUI-first |
@@ -117,7 +117,7 @@ reclaims disk space, nothing else.
117
117
  - check [6] walks every directory and file target and fails if one resolves inside a protected path.
118
118
  - **A dry-run that writes nothing** - `--dry-run` short-circuits every deletion and every destructive command
119
119
  and reports an exact estimate. `--scan` and `--list-targets` are read-only.
120
- - **Personal files go to the Recycle Bin** - partial downloads and large stale files are listed, you pick, and
120
+ - **Personal files go to the Recycle Bin** - partial downloads and large or old files are listed, you pick, and
121
121
  Windows keeps the undo.
122
122
  - **Batch policy** - `--all` runs the safe batch only; deep sections need `--i-understand-deep`; personal
123
123
  sections never run unattended.
@@ -126,7 +126,7 @@ reclaims disk space, nothing else.
126
126
  - **Running-app guard** - an open browser, editor or app keeps its caches; the tool tells you which to close.
127
127
  - **Session reports** - schema-versioned JSON, exportable to Markdown or a self-contained HTML page, plus
128
128
  `--json` for scripts.
129
- - **Self-test** - 156 checks prove the guards on your machine with a real junction, a 445-character path and
129
+ - **Self-test** - 223 checks prove the guards on your machine with a real junction, a path longer than 260 characters and
130
130
  a dry-run fixture before you trust it.
131
131
  - **Offline by design** - the command-line tool makes zero network calls: no telemetry, no update check.
132
132
  Self-test check [9] fails the build on an HTTP or socket call in the source. Crash bundles stay on disk.
@@ -138,7 +138,7 @@ reclaims disk space, nothing else.
138
138
  |---|---|---|
139
139
  | Windows 11 | ✅ | Same engine and PowerShell hosts; a real run on Windows 11 is on the verification list ([project status](https://github.com/aoneahsan/windowsweep/blob/main/docs/features/windowsweep-completion/00-tracker.json)) |
140
140
  | Windows 10 (1809 and later) | ✅ | The primary development target; every real run so far |
141
- | Windows Server 2019+ | ⚠️ | Uses nothing newer than 1809; CI runs the self-test and a dry-run on Windows Server (`windows-latest`) on every push to `main` and every pull request, but no real cleanup has been run on Server |
141
+ | Windows Server 2019+ | ⚠️ | Uses nothing newer than 1809; no real cleanup has been verified on Server |
142
142
  | Linux | ❌ | `os: ["win32"]` makes npm refuse to install; use [linux-cleanup](https://github.com/aoneahsan/linux-cleanup) |
143
143
  | macOS | ❌ | Use [macleanup](https://github.com/aoneahsan/macleanup) |
144
144
 
@@ -202,6 +202,8 @@ section with `a` run / `s` skip / `q` quit and a running total.
202
202
 
203
203
  ### The sections
204
204
 
205
+ This table describes version 1.4.1.
206
+
205
207
  **Tier** says what happens to the data: *report* deletes nothing, *rebuilds* comes back on its own, *slow*
206
208
  comes back but costs minutes, *Recycle Bin* is recoverable until you empty it (`--list` shows this tier as
207
209
  `recycle`), *permanent* is not, *config* changes a setting.
@@ -227,19 +229,23 @@ comes back but costs minutes, *Recycle Bin* is recoverable until you empty it (`
227
229
  | 16 | Clear Windows Event Logs | **permanent** | yes | deep |
228
230
  | 17 | Stale project build artefacts (`node_modules`, `dist`, `.next`, `target`, ...) | rebuilds | - | interactive, developer-gated |
229
231
  | 18 | Partial / orphan downloads | Recycle Bin | - | interactive |
230
- | 19 | Large stale personal files in Downloads | Recycle Bin | - | interactive |
232
+ | 19 | Large or old personal files in Downloads and folders you add | Recycle Bin | - | interactive |
231
233
  | 20 | Docker Desktop / WSL disk-image compaction | config | yes | deep, developer-gated |
232
234
  | 21 | Disk usage report | report | - | safe |
233
235
  | 22 | Global packages audit (npm, pnpm, yarn, bun, deno) - never uninstalls | report | - | safe · audit only |
234
236
  | 23 | Orphaned application data under AppData | Recycle Bin | - | interactive |
235
237
  | 24 | Installed programs not modified for N+ days - never uninstalls | report | - | safe · audit only |
236
238
  | 25 | Startup items audit - never changes them | report | - | safe · audit only |
239
+ | 26 | Uninstall programs you pick | **permanent** | per program | interactive |
240
+ | 27 | Leftover program folders | Recycle Bin | yes | interactive |
241
+ | 28 | Superseded tool releases | rebuilds | - | safe |
242
+ | 29 | Chrome on-device AI model policy | config | yes | deep |
237
243
 
238
244
  *Safe* sections run in `--all`; *opt-in* ones run when named in `--only` or a profile; *deep* ones also need
239
245
  `--i-understand-deep`; *interactive* ones never run unattended unless you pass a selection. The three
240
246
  *audit only* sections are read-only and safe, but stay out of `--all` so a cleanup run is a cleanup run -
241
247
  `--profile audit` is where they live. Every section is documented in
242
- [Sections 0-25](https://windowsweep-docs.aoneahsan.com/sections).
248
+ [Sections 0-29](https://windowsweep-docs.aoneahsan.com/sections).
243
249
 
244
250
  ### Reclaim interactively
245
251
 
@@ -308,17 +314,20 @@ windowsweep [mode] [options]
308
314
  |---|---|---|
309
315
  | `--dry-run` | off | Delete nothing; show what would go and how much it frees |
310
316
  | `-y`, `--yes` | off | Auto-confirm regenerable caches. Never personal files |
311
- | `--i-understand-deep` | off | Allow sections 11, 15, 16, 20 unattended (with `--yes`) |
317
+ | `--i-understand-deep` | off | Allow sections 11, 15, 16, 20, 29 unattended (with `--yes`) |
312
318
  | `--elevate` | off | Relaunch elevated through a UAC prompt |
313
319
  | `-d N`, `--days N` | `100` | Idle window: a file goes when its newest timestamp is N+ days old |
314
320
  | `--temp-days N` | `3` | Idle window for temp folders |
315
321
  | `--purge-all` | off | 🔥 Clear cache targets completely instead of pruning idle files |
316
322
  | `--developer`, `--not-developer`, `--forget-developer` | saved answer | Override or re-ask the developer question |
317
323
  | `--scan-roots "P1;P2"` | auto | Section 17 project roots |
324
+ | `--personal-roots "P1;P2"` | Downloads only | Extra section 19 folders; explicit empty keeps Downloads only |
325
+ | `--browser-profile-roots "P1;P2"` | none | Cache leaves inside declared automation browser profiles |
326
+ | `--temp-roots "P1;P2"` | none | Idle scratch-folder entries |
318
327
  | `--exclude-path P` | - | A tree to leave alone, in **every** section (repeatable) |
319
328
  | `--hiberfil off\|reduced\|keep` | ask | What section 15 does |
320
- | `--permanent` | off | Sections 18, 19 and 23 delete instead of using the Recycle Bin |
321
- | `--select L`, `--select-file P` | off | Answer an interactive section's selection in advance, by index or by path - the one way sections 17/18/19/23 run unattended |
329
+ | `--permanent` | off | Sections 18 and 23 delete instead of using the Recycle Bin; section 19 always recycles selected personal files |
330
+ | `--select L`, `--select-file P` | off | Answer an interactive section's selection in advance; section 19 requires exact paths in `--select-file` |
322
331
  | `--notify` | off | A Windows notification when the run ends |
323
332
  | `--json`, `--quiet`, `--no-color`, `--ascii`, `--no-report`, `--cleanup-logs` | off | Output and record controls |
324
333
 
@@ -396,9 +405,8 @@ More: [Troubleshooting](https://windowsweep-docs.aoneahsan.com/troubleshooting).
396
405
  Bin instead.
397
406
  - **Windows only.** Linux and macOS are blocked at install and at launch.
398
407
  - **It cannot promise a number.** `--scan` measures your disk; the README will not guess.
399
- - **The idle gate is conservative.** Windows keeps last-access times off on most volumes, so the tool reads the
400
- newest of write, access and creation time - a file can only look fresher than it is, never older. Some old
401
- caches survive the default window; `--days` and `--purge-all` exist for that.
408
+ - **The idle gate checks each volume.** Where last-access is live it uses write and creation time; elsewhere
409
+ it uses the newest of write, access and creation. `--days` and `--purge-all` change how much is offered.
402
410
  - **Admin sections need an elevated console** and a UAC click; a Scheduled Task runs the safe batch only.
403
411
  - **Disk Cleanup (section 13) cannot preview sizes.** Its dry-run names the handlers it would run and nothing more.
404
412
  - **No automated test suite beyond `--self-test`.** Correctness rests on the self-test's fixtures, dry-runs and
@@ -439,7 +447,7 @@ More: [FAQ](https://windowsweep-docs.aoneahsan.com/faq).
439
447
  | [Quick start](https://windowsweep-docs.aoneahsan.com/quick-start) | running your first cleanup |
440
448
  | [Safety model](https://windowsweep-docs.aoneahsan.com/safety-model) | you want every guarantee spelled out before deleting anything |
441
449
  | [Developer mode](https://windowsweep-docs.aoneahsan.com/developer-mode) | you want to know what the first question changes |
442
- | [Sections 0-25](https://windowsweep-docs.aoneahsan.com/sections) | you want to know precisely what one section touches |
450
+ | [Sections 0-29](https://windowsweep-docs.aoneahsan.com/sections) | you want to know precisely what one section touches |
443
451
  | [CLI reference](https://windowsweep-docs.aoneahsan.com/cli-reference) | you need an exact flag, exit code or variable |
444
452
  | [Admin sections and elevation](https://windowsweep-docs.aoneahsan.com/admin-and-elevation) | before running the system profile or touching the hibernation file |
445
453
  | [Reports and logs](https://windowsweep-docs.aoneahsan.com/reports-and-logs) | parsing the JSON or finding a log |
@@ -451,16 +459,9 @@ More: [FAQ](https://windowsweep-docs.aoneahsan.com/faq).
451
459
  <a id="changelog"></a>
452
460
  ## 🔄 Changelog&nbsp;[#](#changelog)
453
461
 
454
- Latest release: **`1.3.2`** - the engine is 1.3.1's, file for file. The version moves so the desktop app and
455
- the engine it bundles keep one number, and the desktop app's 1.3.2 fixes its Google sign-in.
456
-
457
- Before it, **`1.3.1`** - nothing about what is cleaned, how it is decided or what is refused changed. The tool
458
- names the windowsweep team as its maker instead of one person, and the web address it prints is the product's
459
- own site.
460
-
461
- Before that, **`1.3.0`** - the documentation address the tool carries became the documentation site, two files
462
- that had grown past the project's own 500-line ceiling were split (the deletion chokepoint stayed exactly where
463
- it was), and the at-a-glance rows inside the published package were corrected.
462
+ Latest release: **`1.4.1`** - the 1.4 scanner searches Downloads and folders you add for large or old files;
463
+ you choose individual files for the Recycle Bin. The uninstall and leftover-folder sections require explicit
464
+ selection. This patch corrects release documentation and adds the desktop release notice and update gate.
464
465
  Full history: [CHANGELOG.md](https://github.com/aoneahsan/windowsweep/blob/main/CHANGELOG.md).
465
466
 
466
467
  <a id="contributing"></a>
package/VERSION CHANGED
@@ -1 +1 @@
1
- 1.3.2
1
+ 1.4.1
package/lib/actions.ps1 CHANGED
@@ -106,6 +106,19 @@ function Test-KnownCacheLeaf {
106
106
  return ($known -contains [IO.Path]::GetFileName($Path))
107
107
  }
108
108
 
109
+ function Add-CacheLeafExceptions {
110
+ <# .SYNOPSIS D79 (P9): lift the protected lists (lib/safety.ps1) for EXACTLY these folders, each of which must
111
+ carry a declared cache folder's name - never a profile, an app root or a protected root. Returns the count. #>
112
+ param([string[]] $Paths)
113
+ $pr = $Script:WS_PROTECT; $n = 0
114
+ foreach ($x in @($Paths)) {
115
+ $f = Get-FullPath $x
116
+ if (-not $f -or $pr.Exact.Contains($f) -or -not (Test-KnownCacheLeaf $f) -or $pr.Exceptions -contains $f) { continue }
117
+ $pr.Exceptions = @($pr.Exceptions) + $f; $pr.ExceptionPrefixes = @($pr.ExceptionPrefixes) + ($f + '\'); $n++
118
+ }
119
+ return $n
120
+ }
121
+
109
122
  function Invoke-TargetList {
110
123
  <# .SYNOPSIS Run every target with its mode under the dry-run, developer, purge and running-app policies. Returns bytes freed/estimated. #>
111
124
  param([pscustomobject[]] $Targets)
package/lib/config.ps1 CHANGED
@@ -10,6 +10,9 @@ function Get-DefaultConfig {
10
10
  largeFileMb = 100
11
11
  scanRoots = @()
12
12
  excludePaths = @()
13
+ browserProfileRoots = @()
14
+ tempRoots = @()
15
+ personalRoots = @()
13
16
  welcomed = $false
14
17
  }
15
18
  }
@@ -28,6 +31,7 @@ function Import-Config {
28
31
  }
29
32
  if ($null -eq $cfg.scanRoots) { $cfg.scanRoots = @() }
30
33
  if ($null -eq $cfg.excludePaths) { $cfg.excludePaths = @() }
34
+ foreach ($k in 'browserProfileRoots', 'tempRoots', 'personalRoots') { if ($null -eq $cfg[$k]) { $cfg[$k] = @() } }
31
35
  } catch {
32
36
  Write-Warn "config file unreadable, using defaults: $path ($($_.Exception.Message))"
33
37
  }
package/lib/constants.ps1 CHANGED
@@ -4,10 +4,10 @@
4
4
  # Single source of truth for the version is package.json: the Node launcher exports it as
5
5
  # WINDOWSWEEP_VERSION. A direct checkout falls back to this literal; the version:check script
6
6
  # asserts the two never drift.
7
- $Script:WS_VERSION_FALLBACK = '1.3.2'
7
+ $Script:WS_VERSION_FALLBACK = '1.4.1'
8
8
 
9
9
  $Script:WS_NAME = 'windowsweep'
10
- $Script:WS_TAGLINE = 'Developer-aware Windows cleanup CLI: dry-run first, personal folders refused, zero install via npx.'
10
+ $Script:WS_TAGLINE = 'Windows cleanup CLI: dry-run first, personal files chosen row by row, zero install via npx.'
11
11
  # The maker is the team, never one person. WS_AUTHOR lands mid-line ("by the windowsweep team");
12
12
  # WS_TEAM is the form a label shows standing alone ("Author: The windowsweep team").
13
13
  $Script:WS_AUTHOR = 'the windowsweep team'
@@ -63,31 +63,35 @@ $Script:WS_SECTIONS = @(
63
63
  @{ Id = 16; Key = 'eventlogs'; Title = 'Clear Windows Event Logs - PERMANENT'; Tier = 'permanent'; Admin = $true; Batch = 'deep'; Dev = $false; Fn = 'Invoke-Section16' }
64
64
  @{ Id = 17; Key = 'projects'; Title = 'Stale project build artefacts (node_modules, dist, .next, target, ...)'; Tier = 'rebuilds'; Admin = $false; Batch = 'interactive'; Dev = $true; Fn = 'Invoke-Section17' }
65
65
  @{ Id = 18; Key = 'partials'; Title = 'Partial / orphan downloads -> Recycle Bin'; Tier = 'recycle'; Admin = $false; Batch = 'interactive'; Dev = $false; Fn = 'Invoke-Section18' }
66
- @{ Id = 19; Key = 'large'; Title = 'Large stale personal files (Downloads) -> Recycle Bin'; Tier = 'recycle'; Admin = $false; Batch = 'interactive'; Dev = $false; Fn = 'Invoke-Section19' }
66
+ @{ Id = 19; Key = 'large'; Title = 'Large or old personal files (Downloads and folders you add) -> Recycle Bin'; Tier = 'recycle'; Admin = $false; Batch = 'interactive'; Dev = $false; Fn = 'Invoke-Section19' }
67
67
  @{ Id = 20; Key = 'vhdx'; Title = 'Docker Desktop / WSL disk image compaction (stops Docker + WSL)'; Tier = 'config'; Admin = $true; Batch = 'deep'; Dev = $true; Fn = 'Invoke-Section20' }
68
68
  @{ Id = 21; Key = 'diskusage'; Title = 'Disk usage report (largest entries, drives, disk images)'; Tier = 'report'; Admin = $false; Batch = 'safe'; Dev = $false; Fn = 'Invoke-Section21' }
69
69
  @{ Id = 22; Key = 'globals'; Title = 'Globally installed packages audit (npm, pnpm, yarn, bun, deno) - report only'; Tier = 'report'; Admin = $false; Batch = 'safe'; Dev = $false; Fn = 'Invoke-Section22' }
70
70
  @{ Id = 23; Key = 'orphaned'; Title = 'Orphaned application data under AppData -> Recycle Bin'; Tier = 'recycle'; Admin = $false; Batch = 'interactive'; Dev = $false; Fn = 'Invoke-Section23' }
71
71
  @{ Id = 24; Key = 'programs'; Title = 'Installed programs not modified for N+ days - report only'; Tier = 'report'; Admin = $false; Batch = 'safe'; Dev = $false; Fn = 'Invoke-Section24' }
72
72
  @{ Id = 25; Key = 'startup'; Title = 'Startup items audit (Run keys, Startup folders, logon tasks) - report only'; Tier = 'report'; Admin = $false; Batch = 'safe'; Dev = $false; Fn = 'Invoke-Section25' }
73
+ @{ Id = 26; Key = 'uninstall'; Title = 'Uninstall programs you pick, each with its own uninstaller, then the folders they left -> Recycle Bin'; Tier = 'permanent'; Admin = $false; Batch = 'interactive'; Dev = $false; Fn = 'Invoke-Section26' }
74
+ @{ Id = 27; Key = 'leftovers'; Title = 'Folders uninstalled programs left in Program Files, Common Files and ProgramData -> Recycle Bin'; Tier = 'recycle'; Admin = $true; Batch = 'interactive'; Dev = $false; Fn = 'Invoke-Section27' }
75
+ @{ Id = 28; Key = 'releases'; Title = 'Superseded tool releases and old downloaded updates (Codex, Electron updaters, Ollama, unrequested Node) - current kept'; Tier = 'rebuilds'; Admin = $false; Batch = 'safe'; Dev = $false; Fn = 'Invoke-Section28' }
76
+ @{ Id = 29; Key = 'browserai'; Title = 'Chrome on-device AI model - set the policy that removes it (Chrome shows "Managed by your organization")'; Tier = 'config'; Admin = $true; Batch = 'deep'; Dev = $false; Fn = 'Invoke-Section29' }
73
77
  )
74
78
 
75
79
  # The safe batch run by --all. Admin sections 12 and 13 join it only when already elevated.
76
- $Script:WS_SAFE_BATCH = @(0, 1, 2, 3, 5, 6, 7, 8, 9, 10, 21)
80
+ $Script:WS_SAFE_BATCH = @(0, 1, 2, 3, 5, 6, 7, 8, 9, 10, 21, 28)
77
81
  $Script:WS_SAFE_BATCH_ADMIN = @(12, 13)
78
82
 
79
83
  $Script:WS_PROFILES = @{
80
- 'dev' = @(1, 2, 3, 4, 5, 6, 17)
84
+ 'dev' = @(1, 2, 3, 4, 5, 6, 17, 28)
81
85
  'minimal' = @(7, 8, 9, 10)
82
86
  'cache-only' = @(1, 2, 3, 6, 7, 8, 9)
83
87
  'system' = @(12, 13, 14)
84
- 'deep' = @(0, 1, 2, 3, 5, 6, 7, 8, 9, 10, 12, 13, 14, 21)
88
+ 'deep' = @(0, 1, 2, 3, 5, 6, 7, 8, 9, 10, 12, 13, 14, 21, 28)
85
89
  'audit' = @(0, 21, 22, 24, 25)
86
90
  }
87
91
 
88
92
  # Walkthrough order (interactive default mode). Admin sections are inserted when elevated.
89
- $Script:WS_WALKTHROUGH = @(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 17, 18, 19, 23)
90
- $Script:WS_WALKTHROUGH_ADMIN = @(12, 13, 14)
93
+ $Script:WS_WALKTHROUGH = @(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 28, 11, 17, 18, 19, 23)
94
+ $Script:WS_WALKTHROUGH_ADMIN = @(12, 13, 14, 27)
91
95
 
92
96
  function Get-Section {
93
97
  <# .SYNOPSIS Returns the catalogue entry for a section id, or $null. #>
package/lib/external.ps1 CHANGED
@@ -70,15 +70,28 @@ function Test-CanElevate {
70
70
  function Invoke-Elevated {
71
71
  <# .SYNOPSIS Relaunch this run elevated (UAC prompt) and wait for it. Returns the child's exit code. #>
72
72
  $ws = $Script:WS
73
+ $summaryPath = $null
74
+ if ($ws.JsonMode) {
75
+ $token = [guid]::NewGuid().ToString('N')
76
+ $summaryPath = Join-Path $ws.ReportsDir ("elevated-summary-$token.json")
77
+ }
73
78
  $childArgs = @('-NoProfile', '-NoLogo', '-ExecutionPolicy', 'Bypass', '-File', ('"' + $ws.ScriptPath + '"'))
74
79
  foreach ($a in $ws.RawArgs) {
75
80
  if ($a -eq '--elevate') { continue }
76
81
  if ($a -match '[\s"]') { $childArgs += ('"' + ($a -replace '"', '\"') + '"') } else { $childArgs += $a }
77
82
  }
78
83
  $childArgs += '--elevated-child'
84
+ if ($summaryPath) { $childArgs += @('--elevated-summary-token', $token) }
79
85
  Write-Info 'Requesting elevation (a UAC prompt appears). The elevated run opens in a new window and writes its own log.'
80
86
  try {
81
87
  $proc = Start-Process -FilePath 'powershell.exe' -ArgumentList $childArgs -Verb RunAs -Wait -PassThru
88
+ if ($summaryPath -and (Test-Path -LiteralPath $summaryPath)) {
89
+ try {
90
+ $json = [IO.File]::ReadAllText($summaryPath).Trim()
91
+ $null = $json | ConvertFrom-Json -ErrorAction Stop
92
+ [Console]::Out.WriteLine($json)
93
+ } finally { Remove-Item -LiteralPath $summaryPath -Force -ErrorAction SilentlyContinue }
94
+ }
82
95
  return $proc.ExitCode
83
96
  } catch {
84
97
  Write-Err "elevation refused or failed: $($_.Exception.Message)"