Skip to content

Releases

1.7.1: App Store updates, a squircle icon, and fixes from real use

Choose a tag to compare

@github-actions github-actions released this 25 Oct 23:22

Fixes from the first day of using the Mac app, and an icon that matches the rest of macOS.

If you are on 1.7.0, the app offers this update itself: press Download in the strip under the title bar, then Close and install.

Fixed

  • App Store updates work. They failed with "a terminal is required to read the password". The current mas needs administrator rights to update apps; the app now asks for your password in the standard macOS dialog, the same way it does for macOS updates.
  • App Store apps show where they are installed, even when the app's name differs from its store name (Kindle installs as Amazon Kindle).
  • A Python that uv has already upgraded stops being offered. uv keeps the previous version beside the new one, and the old copy kept the update listed. Two copies of the same Python are now labelled with their full version.
  • npm no longer logs a stray { as an error when it finds updates. This affected Windows too.
  • Paths are shortened, not cut off, in the Location column.
  • The manager filter shows the manager's name ("App Store") instead of its internal id.
  • Settings opens without a focus ring on its close button.

Changed

  • A new Mac icon, in Apple's rounded icon shape with a gold rim, so it sits evenly beside other apps in the Dock and Finder.
  • The README is rewritten for both platforms, including the System Settings steps that macOS 15 and later need to open an app that is not notarized.

Install

Download DontLeaveUpdatesToFate-1.7.1-arm64.dmg for a Mac (Apple Silicon), or the setup or portable exe for Windows. A new Mac install needs the one-time Open Anyway step in System Settings › Privacy & Security; see the README.

Verify your download

Each file's SHA-256 is in SHA256SUMS-1.7.1.txt, attached below. The built-in updater checks it for you.

Full Changelog: v1.7.0...v1.7.1

1.7.0: The Mac app, and a refreshed interface

Choose a tag to compare

@github-actions github-actions released this 25 Oct 22:47

Don't Leave Updates To Fate now runs on Apple Silicon Macs, and the interface has been rebuilt on both platforms so it moves with what the app is doing.

New: the Mac app

One scan reads every package manager on the Mac:

  • Homebrew, as two rows: command-line tools and apps. Apps that keep themselves current (Chrome, Discord) are hidden by default, as Homebrew hides them; Settings can include them. Updating an app closes it first, and the log says which open apps will close before the run starts.
  • The Mac App Store, through the free mas tool. If mas is missing, select the App Store tile and the app installs it with Homebrew.
  • macOS updates, including Safari and security responses. Installing one asks for your administrator password in the standard macOS dialog; the app never sees it. Updates that need a restart are labelled and run last, and a new major version of macOS is listed but never included in "Update all".
  • uv: tools from uv tool install, and the Pythons uv manages.
  • npm, pnpm, pip, cargo and rustup, as on Windows. pip finds every Python on the Mac, and leaves the ones Homebrew, uv or macOS own to those tools.

The app finds your tools when opened from the Dock, checks that every app in Applications still launches after a run, shows locations in Finder, and updates itself from the release page.

Install: download DontLeaveUpdatesToFate-1.7.0-arm64.dmg, open it, and drag the app to Applications. It runs on Apple Silicon Macs. The app is not notarized, so macOS blocks the first launch:

  1. Open the app. When macOS says it could not verify it, choose Done, not Move to Trash.
  2. Open System Settings › Privacy & Security, scroll to Security, and choose Open Anyway next to the app's name. Confirm with your password or Touch ID, then choose Open.

After that it opens normally. (Right-click › Open no longer works for this on macOS 15 and later.)

New on both platforms: a refreshed interface

  • Buttons that show their progress. "Update all" becomes a progress bar with a running count while it works, and Cancel sits beside it. Scan shows how many managers have reported.
  • The Ledger. The package being updated fills with gold. Each one that finishes gets a gold seal and moves under Done, so the whole run stays on screen to review. A failure stays above the line, next to Retry.
  • A table that keeps its shape while scanning, with rows easing in as each manager reports and counts that roll to their new values.
  • Settings, toasts and the update bar now arrive and leave smoothly. Error messages stay until you dismiss them, and pointing at a message pauses it.
  • Everything respects the system's reduce motion setting, and the in-app one.

Known limits

  • Installing macOS updates through softwareupdate has not yet been tested on an Apple Silicon Mac with an update pending. If an install fails, use System Settings, Software Update for that one.
  • The Mac build is not notarized, which is why the first launch needs the extra step above.

Verify your download

Each file's SHA-256 is in SHA256SUMS-1.7.0.txt, attached below. The built-in updater checks it for you.

Full Changelog: v1.6.1...v1.7.0

1.6.1: Five quieter bugs, fixed

Choose a tag to compare

@github-actions github-actions released this 09 Oct 16:17

Five quieter bugs, each found in review after 1.6.0, confirmed and fixed.

Fixed

  • Switching a package manager off in Settings now means off. Its packages used to stay in the table and the counts, and "Update all" would still update them. They now disappear while it is off, and come back without a rescan when you switch it on again.
  • pip updates a package only in the Python it was found in. If that Python had been uninstalled since the scan, the update used to go into a different one. It now stops and asks you to scan again.
  • Scoop packages read correctly. The available version could pick up the text from the columns after it, such as "Held package" or a missing dependency. Held packages are now shown but left out of "Update all", since Scoop would refuse them anyway.
  • Program names that are not plain English survive. A name like "Café" or a Japanese title came through mangled, which could cost a package its install location.
  • The terminal no longer drops or repeats lines logged while the app is starting up.

Verify your download

Each file's SHA-256 is in SHA256SUMS-1.6.1.txt, attached below. The built-in updater checks it for you.

Full Changelog: v1.6.0...v1.6.1

1.6.0: The terminal shows its text again

Choose a tag to compare

@github-actions github-actions released this 09 Oct 15:37
2a7c71e

The terminal readout works again, a handful of updates that were being silently missed now show up, and the table, the rail and the bottom of the window have had a refinement pass.

Fixed

  • The terminal showed no text. Opening the drawer showed a narrow strip with one digit of each timestamp. Every line is readable again.
  • Some winget updates were missing. Rows were checked against the installed-version column instead of the available one, so a package whose installed version winget could not read was dropped.
  • Some updates were judged "not newer". 1.2 was treated as equal to 1.2.0.5, so that update never appeared, and a release candidate such as 2.0.0rc1 counted as newer than 2.0.0, so its final release was never offered.
  • Install locations for some programs went missing, for names that carry a dash before their version.
  • A skipped package came back after the next run. Skipping now holds.
  • The timeout fields in Settings could not be typed into. Typing 120 saved 1520.
  • Checking for updates after downloading one threw the download away. A finished download now stays ready to install.
  • Clearing the log no longer leaves the pane empty with Export disabled.

Refined

  • At the smallest window size the Settings button had fallen off the bottom of the rail. It is reachable again, and the administrator warning and "Restart as admin" are a single button.
  • Notifications no longer cover the Export button or the version in the footer.
  • The table: no more numpy printed twice in one row, a cooler highlight for ticked rows, checkboxes you can actually see, easier-to-read notices, a quiet Status column until there is something to report, and a fade that says there are more rows below.
  • "Everything is current" gets a proper green check.
  • Terminal timestamps no longer run into the status mark.

Verify your download

Each file's SHA-256 is in SHA256SUMS-1.6.0.txt, attached below. The built-in updater checks it for you.

Full Changelog: v1.5.1...v1.6.0

1.5.1

Choose a tag to compare

@github-actions github-actions released this 19 Sep 03:05

Full Changelog: v1.5.0...v1.5.1

1.5.0

Choose a tag to compare

@github-actions github-actions released this 19 Sep 02:04

Full Changelog: v1.4.0...v1.5.0

1.2.1: Make the handover actually happen

Choose a tag to compare

@VagueDustin VagueDustin released this 23 Aug 09:47

1.2.0 shipped a self-update that did not work. This fixes it. If you are on 1.2.0, you will need to download this one by hand: that is precisely the bug.

Download What it is
DontLeaveUpdatesToFate-1.2.1-portable.exe Single file. Run it from anywhere, installs nothing.
DontLeaveUpdatesToFate-1.2.1-setup.exe Normal installer: Start Menu entry, Add/Remove entry, installs to C:\Program Files\VagueDustin Enterprises.

x64, Windows 10 1809 or newer. Both unsigned: SmartScreen will warn on first run; More info → Run anyway. SHA256SUMS-1.2.1.txt is attached.


What was broken

Both self-update and "Restart as admin" closed the window and did nothing. Neither reported an error, because by the time they fail the app is already gone. Both were found by running them, not by reading the code.

Three separate faults, stacked on each other.

1. The helper never started on the portable build

Both features work by leaving behind a small PowerShell helper that waits for the app to exit and then does something to the files the app was using. A detached spawn is enough from the installed build and is silently not enough from the portable one, which is a stub that extracts the app to a temp directory and tears it down afterwards. detached: true governs the console and the process group; it does not confer independence.

"Restart as admin" has been broken on the portable build since 1.0.0. It was only ever tested on an installed copy.

The fix is not "use the right mechanism": it is to stop trusting them. handover.ts now tries Start-Process, then WMI, then the detached spawn, and accepts none of their return values: the helper's first statement writes a marker file, and a mechanism only counts once that file exists.

That distinction is the entire bug. Win32_Process.Create returns 0 and a process id for a process that executes nothing at all.

2. The portable swap waited for the wrong thing

It waited for the app to exit, then retried the copy four times a second apart. But the stub outlives the app, and while it is deleting its extraction its own image is still mapped and the exe cannot be written. It now waits for the condition a copy actually needs (an exclusive write handle on the target) for up to ninety seconds, polling twice a second.

3. The installer could not be launched from where it was downloaded

%APPDATA% is where a great deal of real malware stages itself, so a hardened Windows refuses to execute anything from there. The installer downloaded and verified perfectly, then failed to start with "the system cannot find the path specified", for a file that Test-Path confirmed existed. The same file ran fine from two other directories.

Downloads now go to your Downloads folder, which is where an installer would have been if you had fetched it yourself, and the least likely place to be treated as suspicious.


And when it goes wrong anyway

Every handover attempt is now recorded in %APPDATA%\dont-leave-updates-to-fate\updates\handover.log: which mechanism was tried, what it claimed, and whether the helper actually ran. An installer that will not start opens Explorer with the file selected rather than leaving you looking at a closed window.

Housekeeping

  • A successful install removes the downloaded installer, and being up to date clears any stale one.
  • That cleanup runs in your Downloads folder, so it only ever deletes files matching this app's own artifact names (DontLeaveUpdatesToFate-<version>-setup.exe and -portable.exe). A cleanup routine loose in someone's Downloads folder is a catastrophe rather than a bug, and there is a test whose only job is to keep that pattern honest.
  • 17 new tests covering the two handover scripts and the deletion pattern. 243 in total.

Licence

Free software under the GNU AGPL v3 or later, with absolutely no warranty. Copyright © 2026 VagueDustin Enterprises.

1.2.0: It updates itself now

Choose a tag to compare

@VagueDustin VagueDustin released this 23 Aug 06:06

It updates itself now. A tool whose whole job is "the things on this machine have fallen behind" should not be the thing on this machine that has fallen behind.

Download What it is
DontLeaveUpdatesToFate-1.2.0-portable.exe Single file. Run it from anywhere, installs nothing.
DontLeaveUpdatesToFate-1.2.0-setup.exe Normal installer: Start Menu entry, Add/Remove entry, installs to C:\Program Files\VagueDustin Enterprises.

x64, Windows 10 1809 or newer. Both are unsigned: SmartScreen will show "Windows protected your PC" on first run; More info → Run anyway. SHA256SUMS-1.2.0.txt is attached if you would rather verify the download than trust it.

This is the last release you have to download by hand. From 1.2.0 onward the app offers the next one itself.


Self-update

On launch it asks the GitHub Releases API for the latest tag and compares it with the running version using the same comparator the package table uses. If there is something newer, a strip appears under the title bar: what version, what you are on, a link to the notes, and a Download button. Nothing is fetched until you press it.

The download is hashed as it streams and checked against the SHA256SUMS published with the release: a mismatch deletes the file rather than leaving a half-verified installer on disk. Be clear about what that proves: the checksums come from the same release as the binary, so they catch a truncated or corrupted download and nothing more. Whether the release itself is honest is what code signing answers, and these builds are not signed.

Each build gets the right artifact. Handing an installed user a portable exe leaves them with a second unmanaged copy; handing a portable user an installer silently converts their "installs nothing" choice into an install.

Build What "install" does
Installed Closes the app, then runs the installer's normal wizard. Not /S: silently replacing an application is not a thing software should do to someone, even at their own request.
Portable Closes the app, overwrites the exe you double-clicked with the new one, and starts it again.
Unpackaged Checks, but is never offered an artifact.

Both paths hand off to a detached helper that calls Wait-Process on the app's process id before touching anything: you cannot replace a running executable on Windows, and racing the exit is how you get a half-written binary. The portable swap retries for a few seconds, because the portable build is a stub that extracts to a temp directory and our own exit does not mean the stub's image is unmapped yet.

Why not electron-updater

It is the obvious choice and it was the wrong one here. It cannot update a portable build at all, which would have left half of what ships here with no update path. Its integrity story is code signing, which these unsigned builds cannot use, so the one check it adds is the one that cannot apply. And it wants a latest.yml published alongside the artifacts, which a release can silently forget, and a release that forgets it is a release nobody can update to, with no error anywhere.

Privacy

The update check is the only network request this app makes on its own: one call to api.github.com per launch, switchable off in Settings, with a manual Check now button either way. Everything else on the network is a package manager you asked to run.

The renderer still cannot reach the network at all: the CSP is default-src 'none' with connect-src 'self', and the check runs in the main process. Adding api.github.com to the renderer's connect-src would have been the easy way to build this and would have widened the renderer's reach for no reason. A release asset is only ever fetched from a https://github.com/ URL; any other host in the API response is dropped before it becomes something the app could download and then execute.


Also in this release

  • The README no longer links to the private brand repository: that was a dead link for everyone but the author.
  • A full release history back to 1.0.0 is now on the repo's main page. Version control here starts at 1.1.0, so the 1.0.x entries are reconstructed from the build artifacts and the development record and are grouped by what was being fixed rather than split per point release.
  • 26 new tests. One of them caught a real bug before it shipped: a dev build was being offered the installer, producing a Download button that led somewhere install() would refuse to go.

Licence

Free software under the GNU AGPL v3 or later, with absolutely no warranty. Copyright © 2026 VagueDustin Enterprises. The product name, the VagueDustin Enterprises name, and the crest and gold-navy identity are not covered by the code licence.

1.1.0, Where it is, on disk

Choose a tag to compare

@VagueDustin VagueDustin released this 23 Aug 05:40

Every package manager on this machine, read in one pass.

Download What it is
DontLeaveUpdatesToFate-1.1.0-portable.exe Single file. Run it from anywhere, installs nothing.
DontLeaveUpdatesToFate-1.1.0-setup.exe Normal installer: Start Menu entry, Add/Remove entry, installs to C:\Program Files\VagueDustin Enterprises.

x64, Windows 10 1809 or newer. Both are unsigned: SmartScreen will show "Windows protected your PC" on first run; More info → Run anyway. SHA256SUMS-1.1.0.txt is attached if you would rather verify the download than trust it.


New in 1.1.0

Every row now shows where the package lives

The question the table could never answer was "which one is this, and where is it?". Now it does. Clicking a path opens Explorer with the folder selected; the row menu (⋯) adds Show in Explorer and Copy path. The location is searchable (type site-packages or Program Files to narrow the list) and it goes into every log export as a package inventory alongside the transcript.

No manager has a --where-is-it flag, so each is asked in the way it can answer: winget through the Add/Remove Programs registry read concurrently with the upgrade query, pip through one importlib.metadata pass per interpreter, Chocolatey and Scoop through their package roots, npm from the field it already reports, rustup and cargo from their homes.

Three rules keep it honest. Nothing is shown that is not actually on disk. MsiExec.exe /X{GUID} is not an install location, so uninstall strings pointing at a shared uninstaller are rejected outright. And a name that two different applications both claim (three .NET runtimes differing only by version) produces no answer rather than a confident wrong one.

Fixes

Four places disagreed about how many updates were waiting. A scan finding 78 packages, two of which had an unreadable installed version, showed "78 updates waiting" in the title bar, 76 in the tile below it, 78 across the sidebar counts, and 76 rows in the table. There is now one definition of "offered", used by all four, and the scan summary says how many were hidden and why.

Retrying a failure erased the run. "Retry 1 failed" started a fresh run, which blanked the 73 rows that had just succeeded. A retry now continues the run it belongs to. Related: the run counters are derived from the jobs rather than tracked alongside them, so they cannot drift again.

A cancelled run showed "Selected: 73". The tile's label and its number were decided by two different conditions.

Exported logs were timestamped in UTC while their filename was local time: the same instant, two clocks, one file. Everything is local now, with the offset named in the header.

Failures dropped their exit code when the cause was recognised from the text. An OBS upgrade that failed with 0x8A150111 reported only "Something is using this package": true, unsearchable, and indistinguishable from the same message raised by a different manager for a different reason.

The shortcut census ran before every run, unannounced. Enumerating four Start Menu trees and resolving every .lnk through COM takes seconds at both ends of a run, and forty pip upgrades cannot break a shortcut. It now runs only when the update includes a desktop installer, says so in the transcript, and can be switched off in Settings.

"Last scan" froze mid-scan: it was computed at render time with nothing to trigger a render, so it ticked four times in nineteen seconds and stopped. Also: Ctrl+R no longer fires while Settings is open, and Escape now clears the search box once the filter and the run are dealt with.


Licence

Free software under the GNU AGPL v3 or later, with absolutely no warranty. Copyright © 2026 VagueDustin Enterprises. The product name, the VagueDustin Enterprises name, and the crest and gold-navy identity are not covered by the code licence.