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.
- package/AI-INTEGRATION-GUIDE.md +8 -8
- package/CHANGELOG.md +90 -0
- package/README.md +31 -30
- package/VERSION +1 -1
- package/lib/actions.ps1 +13 -0
- package/lib/config.ps1 +4 -0
- package/lib/constants.ps1 +12 -8
- package/lib/external.ps1 +13 -0
- package/lib/fs.ps1 +116 -14
- package/lib/safety.ps1 +48 -23
- package/lib/ui.ps1 +20 -2
- package/modules/android_avd.ps1 +187 -36
- package/modules/browser_ai.ps1 +68 -0
- package/modules/browsers.ps1 +101 -33
- package/modules/data_scanner.ps1 +158 -0
- package/modules/globals_audit.ps1 +5 -3
- package/modules/installed_programs.ps1 +69 -2
- package/modules/leftovers.ps1 +388 -0
- package/modules/orphaned_appdata.ps1 +47 -3
- package/modules/personal.ps1 +7 -37
- package/modules/projects.ps1 +2 -1
- package/modules/runner.ps1 +29 -5
- package/modules/self_test_1_4.ps1 +215 -0
- package/modules/self_test_1_4b.ps1 +418 -0
- package/modules/self_test_extra.ps1 +9 -0
- package/modules/system_admin.ps1 +17 -3
- package/modules/tool_releases.ps1 +197 -0
- package/modules/uninstall.ps1 +232 -0
- package/modules/windows_user.ps1 +46 -2
- package/package.json +2 -2
- package/windowsweep.ps1 +19 -1
package/AI-INTEGRATION-GUIDE.md
CHANGED
|
@@ -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-
|
|
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
|
|
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-
|
|
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
|
|
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
|
|
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>
|
|
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
|
[](https://www.npmjs.com/package/windowsweep)
|
|
10
10
|
[](https://www.npmjs.com/package/windowsweep)
|
|
11
11
|
[](https://github.com/aoneahsan/windowsweep/blob/main/LICENSE)
|
|
12
|
-
[](https://github.com/aoneahsan/windowsweep/actions/workflows/ci.yml)
|
|
13
12
|
[](https://nodejs.org)
|
|
14
13
|
[](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;
|
|
23
|
-
>
|
|
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.
|
|
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** | ~
|
|
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.
|
|
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 [#](#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** |
|
|
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
|
|
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** -
|
|
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;
|
|
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
|
|
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-
|
|
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
|
|
321
|
-
| `--select L`, `--select-file P` | off | Answer an interactive section's selection in advance
|
|
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
|
|
400
|
-
newest of write, access and creation
|
|
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-
|
|
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 [#](#changelog)
|
|
453
461
|
|
|
454
|
-
Latest release: **`1.
|
|
455
|
-
|
|
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.
|
|
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.
|
|
7
|
+
$Script:WS_VERSION_FALLBACK = '1.4.1'
|
|
8
8
|
|
|
9
9
|
$Script:WS_NAME = 'windowsweep'
|
|
10
|
-
$Script:WS_TAGLINE = '
|
|
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
|
|
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)"
|