Skip to content

Releases: aoneahsan/windowsweep

windowsweep 1.2.0

Choose a tag to compare

@aoneahsan aoneahsan released this 08 Sep 12:28

Added

  • targets[].newest_write_utc in --scan --json. ISO 8601 UTC, the newest of write, access and creation
    time found anywhere under the target - the same rule the idle gate uses - or null when the target is
    absent or holds no files. It costs no extra walk: under --json the size pass already enumerates every
    file, so the timestamp comes out of that same enumeration. A human --scan keeps the faster path.
  • protected in --list --json. subtrees (every protected folder, resolved for this machine) and
    categories (the same four sentences --list-targets prints). Both readers now take the category list
    from one constant, so the machine-readable copy cannot quietly promise less than the console does.
  • excluded[] in the --json summary, naming every path an exclusion actually kept, once each.

Changed

  • --exclude-path is honoured in every section, not only section 17. It was parsed globally and read by
    exactly one consumer, so someone who excluded a folder was protected in one section and silently not in the
    other twenty-five. It is now enforced at the deletion chokepoint itself - the one place every section
    already passes through - and an excluded path is refused, logged as excluded: <path> and reported in
    excluded[]. The same reach applies to excludePaths in the config file. No deletion behaviour widens:
    --exclude-path only ever refuses more.
    A path that is both protected and excluded still reports the
    protected reason, because that is the promise no flag can lift.

Fixed

  • 🔴 --exclude-path only ever refused the path you named, never anything inside it. The normalised
    prefix was built with a PowerShell literal '\', which is two characters, so the prefix ended in a
    doubled backslash and no child path could ever match it. Excluding a folder protected the folder and
    nothing in it - which is the opposite of what anyone excluding a folder means. The self-test check that
    was supposed to cover this asserted only on the excluded path itself, so it passed throughout; it now
    asserts on a child, and the fix was watched failing on the original bug reintroduced.
  • 🔴 A dry-run counted files a real run would skip. Remove-StaleFiles applied the protection guard
    only in its real-run loop, so the rehearsal's estimate included protected and excluded files that the run
    then refused - for exactly the files a person most wants the two numbers to agree about. One filter now
    decides both, and a check proves a dry-run and a real prune report the same count and the same bytes.
  • --help said --permanent covers "Sections 18/19". It reaches 18, 19 and 23: Send-ToRecycleBin
    is called from modules/personal.ps1 (18, 19) and from modules/orphaned_appdata.ps1 (23). Someone who
    passed --permanent believing it applied to two sections would have had section 23's orphaned
    application data deleted outright instead of recycled. The reference docs already said 18, 19 and 23;
    only the engine's own help text - the one place a person actually reads it from - was wrong.
  • Section 22 declared Dev = $true with no behavioural branch, so --list --json advertised a developer
    flag that changed nothing. It now reads false, and the Dev column in docs/sections.md agrees.
  • 🔴 --scan parsed --developer and --not-developer and then never read them.
    Resolve-DeveloperMode ran only for the walkthrough, the menu, --all and --only, so in scan mode the
    flag reached DeveloperFlag and nothing looked at it: section 0 printed Developer mode: not decided yet
    whatever you passed, and --json returned developer: null. The desktop window sends those flags to
    --scan and could not read back the setting it had just sent. A scan now resolves it from the flag or the
    saved answer and stops there - it may not ask the question, may not write config.json, and may not invent
    a decision you never made, so with neither a flag nor a saved answer it still reports "not decided yet",
    which is the truth. No scan result changes: the scan reports what is on disk, not what a run would
    remove, and Show-ScanTable never read the developer answer in the first place.
  • The hibernation target's one-line note contradicted the section's own explanation two lines below. It
    said reduced keeps Fast Startup "at roughly 40% of RAM", which is the size of the whole file; the
    section intro says reduced is about half of that. The note now states the figure once, on the thing it
    belongs to: the full file is about 40% of RAM and reduced keeps roughly half that.

windowsweep desktop desktop-v1.1.0

Choose a tag to compare

@github-actions github-actions released this 07 Sep 17:55

windowsweep desktop 1.1.0 is a window over the same engine the command-line tool runs. It reimplements no
cleanup logic: it starts the bundled windowsweep.ps1 with --json --no-color and reads its catalogue from
--list --json, so a new section appears in the app without an app update, and a bug reproduced here
reproduces on the command line with the same file.

The app version is the bundled engine's version. This one carries engine 1.1.0: sections 0 to 25, the
scripted-selection flags, and a self-test of 151 checks that passes from the bundled copy as well as from the
repository.

What it adds over the command line

Eleven screens, three colour treatments in light and dark, and a ten-axis appearance control applied before
first paint. Every path is still named before anything is touched. Personal folders are still refused
outright, and no flag changes that.

The home screen draws what a scan found as a treemap, so the biggest thing on the disk is the biggest thing
on the screen. Beside it: the safe run laid out step by step with a figure against each rung, the sections
that need a person to choose, the ones Windows has to ask about, and your last eight runs. A run shows the
engine's own log as it arrives, next to a per-section table that fills in as each section finishes. The
catalogue is a table you can filter.

Four things the design specifies are not built yet, and the window says so where each one belongs rather
than leaving a gap you have to notice: the drive rails and the capacity ring, the weekly schedule switch,
shading each tile by how long that cache has sat unused, and clicking a tile to keep it out of the next run.
Each says why in a sentence.

What it sends

Nothing, in this release.

Sign-in and sync are compiled and dormant: the account screen reports the feature as unconfigured rather than
failing when pressed. Analytics and error reporting are likewise absent from this build, because it carries no
keys for them.

When they are configured, windowsweep collects usage data to improve the product for everyone. The first run
says so in one line, and there is no switch to find. What is never sent is specific and does not change: a file
path, a folder name, a drive label, your user name, your machine name, or the contents of anything. A run
summary is a count and a number of bytes.

The command-line tool continues to make no network calls at all, and its own test suite asserts that.

Installing it, and the warning you will see

Download the .exe for a per-user install, or the .msi if you deploy with one.

Windows SmartScreen will warn you the first time. The installer is not signed with a code-signing
certificate, so Windows has no publisher to check it against. Choose More info and then Run anyway.

You can verify what you downloaded before you run it. Every release publishes a SHA-256 checksum for each
installer, and a minisign signature the app's own updater checks. Neither is a code-signing certificate: they
prove the file is the one that was built, not who built it. The source is public.

To check the checksum yourself:

Get-FileHash -Algorithm SHA256 .\windowsweep_1.1.0_x64-setup.exe

and compare it with the matching line in SHA256SUMS.txt below.

Requirements

Windows 10 or Windows 11, with Windows PowerShell 5.1 - which both ship with. The WebView2 runtime, which
recent Windows builds already have and which the installer fetches if yours does not. No Node, and no
separate install of the command-line tool: the engine ships inside the app.

The installer is per-user and needs no administrator rights. Elevated cleanup sections still ask for consent
at the Windows prompt, through the engine's own elevation; the app never elevates itself.

Artefacts

File What it is
windowsweep_1.1.0_x64-setup.exe the installer, per-user, no administrator rights needed
windowsweep_1.1.0_x64_en-US.msi the same app as an MSI
*.sig the minisign signature of each installer, which the updater verifies
latest.json the update manifest the app reads
SHA256SUMS.txt a SHA-256 for each installer

Known limits, stated rather than discovered

The installer is unsigned, as above. The window has a minimum width of 760 pixels, so it does not go narrower
than that. Sign-in, sync, analytics and error reporting are dormant in this build - the account screen reports
the feature as unconfigured rather than failing when pressed.

The elevated path runs three of its six sections and says so about the rest. The other three - the
hibernation file, the event logs and disk-image compaction - are what the engine calls deep: irreversible or
system-changing, and refused in an unattended batch unless you pass --i-understand-deep yourself on the
command line. The window does not pass it for you, and it should not: that is a decision, not a default. The
run report lists each refusal by name, so nothing is skipped silently, but you will see fewer sections run
than the screen offered. Passing that flag on the command line does what you would expect.

The elevated window also does not stream its log back into the main window yet. It writes its own report to
the same run folder, and the main window waits.

windowsweep 1.1.0

Choose a tag to compare

@aoneahsan aoneahsan released this 04 Sep 09:13

Four new sections, two flags that let a script or a GUI drive the interactive ones, and a machine-readable
catalogue.

npx windowsweep@1.1.0 --profile audit      # the four read-only audits, deletes nothing
npx windowsweep@1.1.0 --list --json        # the section catalogue as one JSON line

Added

  • Section 22 - global packages audit. What npm, pnpm, yarn, bun and deno installed globally, with size and
    idle days, the ones no recent project references flagged, and the exact uninstall command printed. It never
    uninstalls anything and declares no deletable target: several of those roots are protected paths.
  • Section 23 - orphaned application data. Top-level folders under %APPDATA% and %LOCALAPPDATA% that no
    installed program, Store package or running process claims and that nothing has touched for --days+ days.
    Interactive, Recycle Bin, and it fails closed - an unreadable uninstall registry produces zero
    candidates rather than treating everything as orphaned. Every vendor folder another section already cleans
    is excluded automatically, derived from the declared target list so the exclusions cannot drift.
  • Section 24 - installed programs not modified for N+ days. Report only, largest first, with
    winget uninstall --id when one winget list call resolves it. It never runs an uninstaller.
  • Section 25 - startup items audit. Run and RunOnce keys, both Startup folders, logon-triggered scheduled
    tasks and Win32_StartupCommand, each with its enabled state. It changes nothing.
  • --select L and --select-file P. Supply an interactive section's selection in advance, by index or by
    full path. Either lets sections 17, 18, 19 and 23 run unattended - a person did choose - and the selection
    answers that section's final confirmation. --yes alone still selects nothing.
  • --notify. A toast on Windows PowerShell 5.1, a tray balloon on PowerShell 7. It never changes the exit
    code and never writes to stdout. --install-task adds it to the weekly run.
  • --json gained candidates[] and targets[], always present so a caller can rely on the shape, plus
    per-section progress lines on stderr. --list --json prints the catalogue.
  • Section 1 gained the Hugging Face model cache; section 9 offers wsreset.exe as a next step rather than
    running it (it has no silent mode and always opens the Store). Section 17 recognises .nx, .mypy_cache,
    .ruff_cache, .tox, .eggs, .output, .serverless, and .cache beside a Gatsby or Parcel config.

Fixed

  • The section-23 exclusion set was returned as an unrolled array, whose .Contains is case-sensitive, so a
    folder named slack would have slipped past the Slack entry. Caught by a new check before it shipped.
  • Section 24's idle measurement used the newest of write, access and creation time. Last-access is live on
    many systems, so every install folder read as touched today and the section could never report anything.

Changed

  • The target table is collected from the section catalogue rather than a literal 0..21 range, so a new
    section is reachable by --scan, --list-targets and the safety checks the moment it is declared.
  • Profile audit is now 0, 21, 22, 24, 25. The three new report sections stay out of --all so a cleanup
    run remains a cleanup run.
  • Self-test: 124 -> 151 checks. Every new one was planted against and watched go red before it was kept.

Full changelog: https://github.com/aoneahsan/windowsweep/blob/main/CHANGELOG.md

windowsweep 1.0.1

Choose a tag to compare

@aoneahsan aoneahsan released this 03 Sep 17:00

Fixed

  • Sections 17, 18 and 19 no longer pre-select every item under --yes. In the walkthrough and the menu
    with auto-yes on, section 17 could remove every listed build artefact without a person choosing one, and
    18/19 pre-selected everything before their final question. The selection prompt now appears even with
    --yes, defaults to none, and section 17's final confirmation is never auto-answered. Batch mode already
    refused these sections and is unchanged. (RW-002)
  • Section 19's title no longer names Desktop; only Downloads is scanned. (RW-003)
  • Sections 18 and 19 report the tier recycle instead of permanent in --list. (RW-004)
  • --purge-all from a console asks you to type purge once per run, as documented; --yes remains the
    confirmation in batch runs. (RW-005)
  • A running editor's VSIX download cache is cleared as documented: it is its own target without the
    running-editor guard. (RW-006)
  • --install-task and --install-alias refuse to run under npx (exit 3) and print the global-install
    steps; the npx cache is evicted and the task or alias would break later. (RW-007)
  • The engine exits 130 when a run is interrupted before it finished; previously only the Node launcher
    did. (RW-008)
  • --uninstall-data always asks; --yes no longer removes your history unattended. (RW-010)

Changed

  • Internal rename Write-Log -> Write-LogLine (18 call sites) so PSScriptAnalyzer's
    PSAvoidOverwritingBuiltInCmdlets passes under PowerShell 7 in CI. No behaviour change.
  • Self-test: four new checks prove the --yes asymmetry at the helper and at the section 17/18/19 call sites,
    and that every picker call in modules/ carries -NoAutoYes (114 checks).
  • Keywords trimmed to twelve (temp-files dropped). (RW-011)

windowsweep 1.0.0

Choose a tag to compare

@aoneahsan aoneahsan released this 03 Sep 17:00

First release. The Windows member of the cleanup family beside
linux-cleanup and
macleanup.

Added

  • 22 numbered sections (0-21): package-manager caches, build-tool caches, test-runner browsers, Android
    emulators, Docker, editor caches, browser caches, desktop-app caches, Windows user caches, user temp, Recycle
    Bin, Windows Update cache, the Disk Cleanup engine, DISM component-store cleanup, the hibernation file, event
    logs, stale project build artefacts, partial downloads, large stale personal files, disk-image compaction and
    a disk-usage report. Section numbers are a public contract from this release on.
  • Developer mode. The first interactive run asks whether you are a developer. Yes means package, build and
    test-runner caches are pruned only when idle 100+ days and the newest version of every versioned tool cache
    is kept; no means those caches are cleared completely. The answer is saved and can be re-asked with
    --forget-developer.
  • A dry-run that writes nothing (--dry-run), a read-only scan (--scan) and --list-targets.
  • One deletion chokepoint that refuses drive roots, Windows, Program Files, the profile root, personal
    folders, credentials, toolchains and browser/editor state, asserts every deletion lies inside its declared
    target root, never follows junctions or symlinks, handles paths longer than 260 characters and skips files
    another program has open.
  • Batch policy. --all runs the safe batch only; deep sections (11, 15, 16, 20) need
    --i-understand-deep; personal sections (17, 18, 19) never run unattended and use the Recycle Bin.
  • Admin awareness. Admin sections skip with the exact command when not elevated; --elevate relaunches
    through a UAC prompt.
  • Session reports as schema-versioned JSON with Markdown and HTML export, a reports manager, run history
    (--stats), history pruning and --json for scripting.
  • Weekly Scheduled Task (--install-task) and a PowerShell profile alias (--install-alias).
  • Self-test (--self-test): script syntax, ASCII-only source, the protection lists, a real junction
    fixture, the dry-run guarantee, keep-newest, long paths and the extension-leftover rule.
  • Crash bundles written locally on unexpected exit; --debug-bundle and --report-issue for bug reports.
    Nothing is ever transmitted.
  • Node launcher for npx windowsweep, a .cmd launcher for machines without Node, and a ci workflow that
    runs the self-test and a dry-run on both Windows PowerShell 5.1 and PowerShell 7.