bootstrap v2026.09.28-2
·
2 commits
to main
since this release
Windows 1.47.0
Added
- A release archive is a whole install now. It used to hold the platform
directory alone, without the configs the script deploys from the repo root -
starship.toml, the tool themes, mise/, tools/cli-parity.conf - so an install
from it could not finish its shell and theme phases. Each archive now
unpacks to one bootstrap/ directory laid out as the repo: the platform's own
directory and every top-level entry but the other two platforms. It also
carries a RELEASE file naming the tag and the repo. - An archive install updates itself like a checkout: when a newer release
is out, a run you are sitting at offers it, downloads that release's zip,
checks it against the published .sha256, unpacks it into a temp directory
and copies it over the install - the same directory, so the daily task still
finds the script. A download that fails or does not match leaves the install
as it was. An archive from before this release has no RELEASE file; unpack
this one once by hand and it updates from then on. - Update from a run: when preflight finds a newer release, a run you are
sitting at asksUpdate to vX and rerun? [y/N]. Yes fetches, moves the
checkout to the tag - a branch fast-forwards, a detached checkout of a tag
moves to the new one - and reruns the new script with the same arguments and
-SkipUpdateCheck. Local changes, or a branch with commits the release
lacks, and it refuses and says why rather than guessing. The daily task,
-WhatIfand-Doctoronly print the line, as before. -Select: choose which packages this machine has. A menu of every
winget package and uv tool in the manifest, drawn by the script itself: a
section per group with its packages beneath, each with a[x]or[ ]box,
the installed version and the current pick pre-ticked. Space on a package
ticks it; on a section it ticks all of it - or clears it, when all of it was
ticked - and the section shows[x],[-]or[ ]for all, some or none.
Not fzf: fzf marks only ticked lines, with no empty box for the rest, and a
whole-section toggle from inside it takes a shell command per keypress. It
needs no fzf, so it works on a first run too. Ticked is installed; unticked
and installed is uninstalled, after one confirmation listing all of it.
Declining abandons the whole pick rather than saving it without the
removals, which would leave those packages installed but unwanted, and
never offered for removal again.- The pick is saved to
%LOCALAPPDATA%\windows-bootstrap\selection.json,
besidelast-run, and every later run follows it, the daily task included.
It keeps two lists:Selected, what was ticked, andKnown, everything the
menu offered - so an unticked package can be told from one the manifest
gained since. With no file every package is wanted, exactly as before. Requiredinpackages.psd1: ids that are always installed and show
locked in the menu - pwsh, git, uv and mise, which other phases stand on.
Optional, so an older manifest still loads; an id no group lists fails the
run up front.- New packages are asked about, not assumed. A manual run asks once per
package the manifest gained since the last pick and remembers the answer
either way. An unattended run installs none of them and reports each as
deselected, so nothing arrives on the machine that nobody chose. A
section with nothing ticked counts as switched off: its newcomers are left
out without asking. - User-scope packages uninstall from an elevated run. winget refuses
(0x8A15007D) to remove a package installed per user - most portable CLIs -
from an administrator process. That one call is rerun un-elevated as the
same user, through a throwaway scheduled task withRunLevel Limitedthat is
removed when it finishes. - What the menu offers to remove follows the machine: anything unticked
and still installed that a menu has offered before. A removal that failed
is offered again on the next-Selectinstead of being stranded as
unticked-but-installed. - Result actions
removed,would-removeanddeselected, and the run
history now records a removal as-id.
Removed
- ILSpy, added in 1.46.0: dropped before anyone depended on it. Taking it
out of the manifest stops installs and upgrades; a copy already installed
stays untilwinget uninstall icsharpcode.ILSpy. - Sysinternals Suite, added in 1.46.0: winget's manifest pins the hash of
SysinternalsSuite.zip, which Microsoft replaces in place at the same URL
without a new version, so the install fails the hash check - and an
elevated winget rightly refuses to skip it - every time the zip moves until
the manifest catches up.
Linux 1.40.0
Added
- A release archive is a whole install now. It used to hold the platform
directory alone, without the configs the script deploys from the repo root -
starship.toml, the tool themes, mise/, tools/cli-parity.conf - so an install
from it could not finish its shell and theme phases. Each archive now
unpacks to one bootstrap/ directory laid out as the repo: the platform's own
directory and every top-level entry but the other two platforms. It also
carries a RELEASE file naming the tag and the repo. - An archive install updates itself like a checkout: when a newer release
is out, a run you are sitting at offers it, downloads that release's
tarball, checks it against the published .sha256, unpacks it into a temp
directory and copies it over the install - the same directory, so the
systemd timer still finds the script. A download that fails or does not
match leaves the install as it was. An archive from before this release has
no RELEASE file; unpack this one once by hand and it updates from then on. - Update from a run: when preflight finds a newer release, a run you are
sitting at asksUpdate to vX and rerun? [y/N]. Yes fetches, moves the
checkout to the tag - a branch fast-forwards, a detached checkout of a tag
moves to the new one - and reruns the new script with the same arguments and
--skip-update-check. Local changes, or a branch with commits the release
lacks, and it refuses and says why rather than guessing. The systemd timer,
--dry-run,--doctorand a run as root only print the line: git writing
into your checkout as root would leave files you could not change. The rerun
is anexec: bash reads a script as it runs, so the old process must not go
on over a file that just changed under it.
macOS 1.43.0
Added
- A release archive is a whole install now. It used to hold the platform
directory alone, without the configs the script deploys from the repo root -
starship.toml, the tool themes, mise/, tools/cli-parity.conf - so an install
from it could not finish its shell and theme phases. Each archive now
unpacks to one bootstrap/ directory laid out as the repo: the platform's own
directory and every top-level entry but the other two platforms. It also
carries a RELEASE file naming the tag and the repo. - An archive install updates itself like a checkout: when a newer release
is out, a run you are sitting at offers it, downloads that release's
tarball, checks it against the published .sha256, unpacks it into a temp
directory and copies it over the install - the same directory, so the
launchd agent still finds the script. A download that fails or does not
match leaves the install as it was. An archive from before this release has
no RELEASE file; unpack this one once by hand and it updates from then on. - Update from a run: when preflight finds a newer release, a run you are
sitting at asksUpdate to vX and rerun? [y/N]. Yes fetches, moves the
checkout to the tag - a branch fast-forwards, a detached checkout of a tag
moves to the new one - and reruns the new script with the same arguments and
--skip-update-check. Local changes, or a branch with commits the release
lacks, and it refuses and says why rather than guessing. The launchd agent,
--dry-runand--doctoronly print the line. The rerun is anexec: bash
reads a script as it runs, so the old process must not go on over a file
that just changed under it. --select: choose which packages this Mac has, the same design as
Windows 1.47.0. A menu of every formula and cask in the manifest, drawn by
the script: a section per group with its packages beneath, each with a
[x]or[ ]box and its installed version, the current pick pre-ticked.
Space on a section ticks all of it, or clears it when all of it was ticked,
and the section shows[x],[-]or[ ]. Keys are read from/dev/tty
a byte at a time; everything else - the rows, a toggle, a frame - is plain
functions over indexed arrays, since bash 3.2 has no associative ones.- Unticked and installed is uninstalled with
brew uninstall, after one
confirmation listing all of it; declining keeps everything and saves
nothing. What is offered follows the machine - unticked, installed, offered
before - so a formula brew refused to remove because another depends on it
is offered again next time. - The pick is saved to
~/.local/state/bootstrap-macos/selectionas plain
yes/nolines, and every later run follows it, the launchd agent
included. A line that is neither makes the file untrusted, and every package
is wanted - a garbled file never unticks everything. No file, no change. REQUIREDinpackages.conf- git, mise and uv - always installed and
locked in the menu. Optional, so an older manifest still loads; an id no
group lists fails the run up front.- New packages are asked about once on a manual run and the answer kept;
the agent installs none of them and reports each asdeselected. A section
with nothing ticked counts as switched off, and its newcomers are left out
without asking. - The run history records a removal as
-pkg, and the menu restores the
terminal on Ctrl-C as well as on exit.
Removed
- ILSpy, added in 1.42.0: dropped before anyone depended on it. Taking it
out of the manifest stops installs and upgrades; a copy already installed
stays untilbrew uninstall --cask ilspy.