How Helix Toolbox works
What each part of Helix Toolbox does, in detail. GUIDE.md is the shorter walk-through for getting started; CATALOG.md covers the entries themselves and how a run is planned.
The menu
Section titled “The menu”In the interface the sidebar is a menu of screens. Tab or j/k in the
sidebar move between Dashboard, Applications, Favorites, Install Plan, and the other
areas, History and Settings; Enter or l opens the selected screen and
h returns to the sidebar. In an area, j/k or the arrows move in the
list, Enter opens a group or runs an entry, Space adds it to the install
plan, d shows its details, p the script or command, g explains the
flags column and / searches every area. A row shows the entry’s
description where it fits, a group what it holds and how many items, and
a search result the area and group it is listed in; an entry marked [>]
(a play icon with Nerd Font icons) runs on its own and cannot be queued.
The details say where the entry is, its kind (package, script, command,
Nix, built in or profile), whether it asks questions as it runs, where an
installed package came from, what a profile runs in order and what each of
its flags means. On a profile, e puts its entries in the Install Plan one
by one, so the plan can be changed before it runs. The Install Plan shows
what is queued with its risk and requirements, each entry with its status,
flags, area, kind and step; K and J (or Shift with the arrows) move
the selected one earlier or later, and Enter runs it. Each run asks [Y]
first and then runs in a terminal inside the window, with each step beside
it (waiting, running, done, failed with its exit status, or skipped), how
many steps have ended, and the run’s warnings and, at the end, its result
and every check, those done after the next reboot or not checked here marked
so; Ctrl-C stops it and everything it started (if something ignores that,
the window says so and a second Ctrl-C kills it), l saves its output, and
History lists every run.
? shows all keys and q quits. The menu needs a terminal; the commands
below also work without one. helix-toolbox tui --screen <name> opens it
on a screen (updates, doctor, drift, plan, restic and the others,
or an area’s id such as applications); on the first start the setup
wizard opens over it.
As in the window, the sidebar counts pinned Favorites, queued Install Plan
entries and entries with an update, and the header shows the version. The
Dashboard counts the package entries installed, those with an update
waiting, what is queued and what is pinned, above the System Overview, and
its quick actions include Set up this machine (the setup wizard) and
Find anything (the command palette). The footer’s rule says how many
package entries were checked, or that the check is running; Ctrl-R, or
“check again what is installed” in the command palette, checks again.
Ctrl-K opens the command palette from any screen: type part of what you
want and Enter does it. It finds every screen (open updates), actions
(check updates online, run DNS diagnostics, which opens Helix Doctor
at that check, save this machine as a baseline, clear the install plan,
change the theme) and every entry (install ghostty), loose spellings
included. An entry chosen there is planned and confirmed like any other.
The mouse works too. A click on a sidebar item opens that screen; a click
on a row selects it, and a click on the row already selected does what
Enter does, so an entry or a plan still opens its confirmation first and
a word you must type is still typed. A click on a key hint at the bottom
presses that key, and the wheel scrolls the list, a popup or the output of
a run. A click outside a popup does nothing. While the interface has the
mouse, most terminals still select text with Shift held down; Settings
(Mouse) or Ctrl-K “turn the mouse off” leaves the mouse to the
terminal, and the choice is remembered.
Search ranks what it finds: names that match exactly or start with the
text first, then names containing it, ids, loose spellings (rpgrp finds
Ripgrep) and descriptions. Escape clears it and goes back to the row you
were on. i cycles the list between all entries, installed ones (including
those managed by Nix) and ones with an update, flattening the groups of the
area. * pins the selected entry; Favorites lists pinned entries, then
the ones run recently, from History, and is also a quick action on the
Dashboard. Pins are kept in ~/.config/helix-toolbox/favorites.toml. Each area
remembers its group and row when you move to another.
The menu follows the Helix Toolbox dashboard design: cards for the main screens
and quick actions, with Nerd Font icons. t or Settings switches between
four themes: solid, the default, paints the design’s dark panels;
transparent draws over your terminal’s own background, so a wallpaper or
transparency shows through (it was called default before, and that name
still works); compatible keeps to sixteen colors; monochrome uses no
color at all, only bold and reverse video. With NO_COLOR set, Helix Toolbox
starts in monochrome without changing the theme it remembers. Settings also turns the icons
off for terminals without a Nerd Font. Both choices are remembered in
~/.config/helix-toolbox/settings.toml, which the Settings screen names;
--theme and --plain override them for one run. A settings.toml that
does not parse is copied to settings.toml.unreadable beside it before a
setting is next saved, since the new file holds only what was saved.
Status and updates
Section titled “Status and updates”Package entries show how they stand on this machine, beside their flags:
Installed with where from and the version (pacman 15.2.0-1, apt,
dnf, AUR, Flatpak 7.5, GitHub release 0.66.2), Update when the
repository metadata already on the machine has a newer version (pacman 15.2.0-1 → 15.3.0-1; nothing is downloaded to find out), or the catalog
pins a newer release than the one installed (GitHub release 0.65.0 → 0.66.2), Managed when the command comes from Nix (Home Manager 1.4.7, Nix, NixOS), or Not installed. When a package is
installed but a Nix copy of its command comes first on the PATH, the status
says so (; Home Manager's 0.12.5 runs first). The check runs in the
background when the menu opens, after every run and on Ctrl-R; d
repeats it in the details.
u updates the selected entry and U every entry with an update, after
the same confirmation as a run: flatpak update -y for its installation, apt-get install --only-upgrade, dnf upgrade or zypper update for that package,
and on Arch pacman -Syu, the whole system, since updating one package alone
is a partial upgrade, which Arch does not support. Afterward each package’s
version is compared with its version before; one that did not change is not
verified. Entries managed by Nix say to update them there.
After every run, each package step is checked with the package manager, and
each script entry for what its [detect] table says it installs and for its
[[verify]] checks (docs/CATALOG.md): the files and folders it leaves,
words on the kernel command line, the value of a setting and whether it
names something installed, and systemd units enabled or running. They are
read as you and change nothing. The result says verified, or not verified: with what is wrong; what cannot be read here (a file only root
can read, a container without systemd) is reported as not checked, never as
passed. Checks that hold only after a reboot are kept beside the history and
made once the machine has started again: Helix Doctor’s Checks after the
reboot shows them waiting, then what they found. c on an entry, Check
it now in the window and helix-toolbox verify <entry>… (exit status 1
when one fails, --json too) make an entry’s checks at any time.
Updates shows the whole machine, not only catalog entries: for each tool
that keeps it (pacman or apt, dnf, zypper; the AUR helper; Flatpak’s system
and user installations; Home Manager with a flake, NixOS, a Nix profile) what
is waiting, from what that tool already knows. r checks online through
read-only commands (checkupdates, which leaves pacman’s database alone,
paru -Qua or yay -Qua, flatpak remote-ls); nothing else asks the
network. Nix channels show how old their locked nixpkgs is, since Nix counts
nothing before it updates. Enter lists the packages, u updates the
selected channel and U every channel with updates waiting, one after
another and the AUR after the repositories, through the tools themselves
(sudo pacman -Syu, paru -Sua, flatpak update, nix flake update then
home-manager switch), after the usual confirmation. The Home Manager update
changes the flake’s flake.lock, in your dotfiles checkout when the
configuration is a link to one. Below the channels, the package entries with
an update are listed: Enter (or u) on one updates it as u in its area
does, and the last row updates every one of them.
The Helix Toolbox row is Helix Toolbox itself, updated the way it was
installed, which it tells from where it runs. r asks GitHub for the latest
release. A package in /usr/bin is updated by downloading the new release’s
package for this distribution into ~/.cache/helix-toolbox/release, checking it
against the release’s SHA256SUMS (the hidden helix-toolbox fetch-release
command, which takes only a release version and one of the release’s own file
names), then installing it with pacman -U, apt-get install, dnf install
or zypper install; the window’s package (helix-toolbox-gui) is fetched and
installed with it when the package tool says it is installed. On Arch with
the helix-toolbox repository in pacman.conf (INSTALL.md), the row runs
pacman -Syu --needed helix-toolbox (and helix-toolbox-gui) instead, which
updates the system with them. A copy from cargo install runs cargo install --locked helix-toolbox again. A build in a checkout fast-forwards it from
GitHub and builds it, and leaves a checkout with local changes alone. A copy
anywhere else that the user owns (~/.local/bin, say) is replaced by the
release’s program, fetched and checked the same way, with install -m 0755;
one the user does not own is left to whoever put it there. The window run
as an AppImage (the APPIMAGE variable names the file) has the release’s
AppImage fetched, checked and put in its place, whatever updates the command
line. The launcher and start.sh fetch the latest release every time they
start, so there is nothing to run for them.
Update notifications (Settings in the menu and the window, or
helix-toolbox notifications on) write two units of the user’s own,
helix-toolbox-updates.timer and helix-toolbox-updates.service, into
$XDG_CONFIG_HOME/systemd/user, enable the timer with the same link
systemctl --user enable makes, and start it; no password is asked. The
timer starts the service 10 minutes after the user’s systemd starts (at
login) and every 6 hours after that, each time up to 10 minutes later at
random. The service runs helix-toolbox notifications check: the Updates
overview, online, as helix-toolbox updates --online reads it. When
something waits that the last notification did not tell of (the package
names and new versions it told of are kept in
$XDG_STATE_HOME/helix-toolbox/notified.txt), it shows a notification with
notify-send, or with gdbus where libnotify is missing. With libnotify
0.7.10 or later and the window installed, the notification has a Show
updates button and waits up to 30 minutes for it, which opens the window
with --updates, on the Updates screen; the service names the window it
was turned on from (an AppImage by its file), else helix-toolbox-gui on
the PATH. The check never updates anything. helix-toolbox notifications off stops the timer and removes the units and notified.txt. A machine
without systemd gets no files and says so.
The same timer can watch more, each read-only and told only when something
is new: Tell me of new health problems (helix-toolbox notifications health on) runs Helix Doctor’s health checks and tells of a check that has
become a problem since it last told (a failed service, a disk filling up,
checks after a reboot that did not hold); the network and DNS checks, which
come and go, are left out. Tell me when it drifts from a baseline
(helix-toolbox notifications drift <baseline>, or off) compares the
machine with a saved Drift baseline and tells of each new difference once.
Their buttons open the window on Helix Doctor (--doctor) or Drift
(--drift). Nothing is repaired or put back by itself. The choices are kept
under [watch] in settings.toml, what was told in health-told.json and
drift-told.json beside notified.txt; the timer is on while any choice
is, and helix-toolbox notifications says which.
Script entries such as Steam, VS Code or Firefox show the same status when
they say what they install (most application scripts do), and u updates
that package; a script entry without it shows only its flags and is updated
by running it again. When a command is on the PATH but in none of an entry’s
packages, the package that owns the file is looked up (pacman -Qo, dpkg -S, rpm -qf), so /usr/bin/github-desktop shows as pacman: github-desktop 3.4.14-2.
The header banner
Section titled “The header banner”In terminals that show pictures through Kitty’s graphics (Ghostty, Kitty) or Sixel (foot, WezTerm, xterm with Sixel on), the header is the Helix Toolbox banner. Elsewhere, including Konsole, tmux and the console, with icons off or in the compatible theme, it is the text header. Helix Toolbox asks the terminal once at start and waits at most 0.4 seconds for the answer.
Profiles
Section titled “Profiles”Profiles of your own: queue what a workstation needs (applications,
the Myfish shell setup, dotfiles configurations, system tweaks; all are
entries) and press s on the Install Plan to save it under a name. It is a
TOML file in ~/.config/helix-toolbox/profiles/ and appears under Profiles,
Your profiles, where Enter runs it and Space queues it, like the
built-in ones; its entries run in order, after what they depend on.
In the menu’s Profiles area, x on one of your profiles exports it to a
file, Delete deletes it (after you type yes) and o imports a profile
file; the window has the same as buttons. On the command line:
helix-toolbox profile list, export <name> [file], import <file> (which
refuses a profile naming entries this catalog does not have) and delete <name>; helix-toolbox run profile-<name> runs one.
name = "Dev Box"description = "Terminal tools and editor configuration"entries = ["git", "ripgrep", "myfish-fish", "dotfiles-nvim", "ghostty"]Drift shows how this machine differs from a saved baseline or from
a profile, without changing anything. A baseline records what is installed
(each package entry’s source and version), the configuration files and
folders catalog entries write (by SHA-256 checksum, never their contents),
the login shell, display manager, Arch repositories, Flatpak remotes and
desktop, and the entries without a package Helix Toolbox has run successfully.
s on the Drift screen, or helix-toolbox drift save <name>, saves one in
~/.config/helix-toolbox/baselines/; --path adds files of your own.
Comparing lists, most important first: Missing applications and
configuration files, entries that ran there and are Not run here,
Replaced paths (a file that became a Home Manager link), Changed
files and settings, then what was Added since and other Versions.
b compares with another baseline or with a profile instead, which checks
each of its entries: installed, its files present, or run here. An entry
with no recorded run here still counts as set up when what it sets is in
place: the files it writes are all there, or its installer’s own renderer
(configure.py, which only prints) finds the boot or login-screen settings
it would write already in the file, as after a run from before Helix Toolbox
1.1 recorded runs, or a change made by hand. A program Helix Toolbox
installed from a GitHub release is Missing when it is gone and
Changed when it is another file than the one installed, with whichever
baseline or profile. Each difference shows what it
was and what it is now. Enter
explains a difference; Space adds the entry that puts it back to the
Install Plan and a adds all of them, to be reviewed and confirmed there;
R reviews running all of them now instead. What the baseline or profile
names that this catalog lacks is listed as not compared, and the entries
this distribution cannot install as not on this machine.
To set up a new machine like an old one: helix-toolbox drift save "Old laptop" and helix-toolbox drift export "Old laptop" there, then helix-toolbox drift check old-laptop.toml on the new one; it ends with the helix-toolbox run that would restore what is missing (planned and confirmed first), and
names what this distribution cannot install. drift list, import and
delete manage the saved ones; --exit-code makes check exit with 1
when anything differs.
The setup wizard
Section titled “The setup wizard”The first time Helix Toolbox starts, it offers the setup wizard (Settings,
Setup wizard, and Ctrl-K “set up this machine” open it again). It shows
what it found: the distribution and package manager, the other package
tools (paru, yay, Flatpak, Nix, Home Manager, Snap), the desktop and session,
the graphics and whether this is a laptop. Then it offers workstations from
catalog/setup.toml: Developer, Gaming (with the NVIDIA driver entry
for the distribution where there is an NVIDIA card), Privacy (a firewall
baseline and AppArmor, or SELinux on Fedora), Minimal and Custom
(every suggestion, none ticked). Its entries are listed with how they stand,
ticked where they can run here and are not installed; Enter puts the
ticked ones in the Install Plan, where they are planned, previewed and
confirmed like anything else. The wizard runs nothing itself.
helix-toolbox setup lists the workstations; helix-toolbox setup gaming prints
what it would add and its plan, and the helix-toolbox run that would run it.
The desktop
Section titled “The desktop”Desktop shows the desktop environment and its version (KDE Plasma,
GNOME, Xfce, Cinnamon, MATE, Hyprland, Sway), the session, the login screen
with its configuration files and SDDM theme, and the appearance settings
read with the desktop’s own tools (kreadconfig6, gsettings,
xfconf-query): color scheme, style, icons, cursor, global theme, font.
It warns when something else sets them: Home Manager’s Plasma or dconf
steps, or Stylix, which may set them again at the next switch, and refuses
to change them where Home Manager links the settings file itself. s
saves the look in ~/.config/helix-toolbox/looks/; Enter on a saved look
puts back what differs with the desktop’s own commands
(plasma-apply-colorscheme, gsettings set, …), after confirmation. The
entries for this desktop (its login screen theme, terminal configuration,
boot splash) are listed below with what is worth knowing about each here,
to run or queue. helix-toolbox desktop,
desktop save <name>, desktop apply <name>, list and delete.
Offline bundles
Section titled “Offline bundles”For a machine without reliable internet, helix-toolbox bundle create <folder> <entries…> downloads, on a machine of the same distribution and
architecture, the packages those entries need into a new folder, with a copy
of Helix Toolbox (the catalog and installers are inside it), a manifest
(bundle.toml) and SHA256SUMS. By default it takes the dependencies this
machine lacks, which suits a machine set up like it; --complete takes every
dependency. pacman’s packages come with their signatures, which pacman -U
checks against its keyring when it installs them; apt’s are checked against
the checksums in the repository’s signed index as they are downloaded; dnf’s
are signed, and their signatures are checked against the installing
machine’s rpm keyring before they install; so are zypper’s,
which zypper downloads as you, without root, into a scratch root that
shares this machine’s repositories (an empty package database for
--complete, this machine’s own otherwise), checking each against the
repository’s signed metadata. Entries that need the network (AUR builds,
scripts, Nix, Flatpaks not installed here) are listed as such and left
out.
An entry with no package for this distribution whose Flatpak is installed
here goes in as that Flatpak: flatpak create-usb copies it, with the
runtimes and extensions it needs, from this machine’s installation into the
bundle’s flatpak folder, and the bundle keeps its remote’s signing key.
create-usb needs the remote to have a collection ID; Flathub, added from
its .flatpakrepo file, has none until it is given its own:
sudo flatpak remote-modify --collection-id=org.flathub.Stable flathub.
bundle create says so rather than changing your remotes.
On the other machine, ./helix-toolbox bundle verify . checks that the bundle
was made for this distribution and architecture and that every file matches
its checksum, and that its packages folder holds only that family’s
package files (.pkg.tar.* and their .sig for Arch, .deb for Debian,
.rpm for Fedora and openSUSE), since everything there goes to the package
manager. ./helix-toolbox bundle install ., after confirmation, copies the
packages into a new private folder, checks the copies against the checksums
it verified (written into the plan, not read from the bundle again), checks
each signature (pacman-key --verify; for an RPM, rpm -Kv must show a
signature by a key in this machine’s rpm keyring, and nothing failed, both
when the plan is made and on the copy, and dnf checks it too), and installs
them from the files (dnf and zypper without their repositories; zypper asks its own
question only in a terminal, as it reads answers from nowhere else). Debian packages have no
signature of their own: each must be in this machine’s signed repository
index with the same checksum. An RPM without such a signature, or a Debian
package the index does not know, is refused unless --trust-bundle takes
the bundle’s word, for a bundle you made yourself.
A bundle installs as a whole, since its entries share their dependencies.
pacman and apt fetch only a dependency the bundle lacks, and only when the
network is there; a --complete bundle lacks none.
Flatpaks install from the bundle’s copy (flatpak install --sideload-repo),
and flatpak checks each commit’s signature against the remote’s key on this
machine, as it would from the remote itself. verify checks that the copy
holds each application at the commit the manifest records. A remote without
a collection ID is given the bundle’s when it is the one published for the
remote’s address (Flathub’s); any other, and a remote this machine lacks,
which is added with the bundle’s copy of its key, only with
--trust-bundle, since nothing here vouches for them.
Offline bundles in the menu and the window does the same from the Install Plan: it says what a bundle of the queued entries would download, makes one in a folder you name (with every dependency or only what this machine lacks), and checks a bundle’s folder or installs from it, with the bundle’s word taken only when you switch that on.
What a change will do
Section titled “What a change will do”Before a plan runs, e (on the Install Plan, in the confirmation, or on a
backup in Backups) and --effects on plan and the --dry-run commands show
what it is expected to change on this machine, step by step, each change
marked by how it is known:
- ✓ known: worked out here. A package step asks the package manager
without root (
pacman -Sp,apt-get -s) which other packages come with it or go; a configuration file is rendered by the installer’s own code (configure.py, which only prints) from the file as it is now and shown side by side with it; a restore compares the file with the backup. - ~ expected: what the entry declares in its
[effects]table (files, packages, services, when it takes effect) or its script plainly runs. - ? not known in advance: what a script decides as it runs, the answers it asks you for, a boot menu regenerated from the installed kernels, or the dependencies dnf and zypper list only with root.
Enter on a file shows it now and afterward, side by side; on any other
change, the whole line. The boot loader, boot splash, login screen and
AppArmor entries declare their effects; other scripts are previewed by the
paths they write and the services their script names, and say plainly that
the rest cannot be known before they run.
The dotfiles entries (Neovim, Fastfetch, Starship, Konsole and Ghostty) are
compared file by file once their pinned source, the dotfiles commit the
installers read, is on this machine: each file is new, changed (side by
side), the same, or, in a folder the installer replaces whole, left only in
the backup it keeps. The installer’s own configure.py lists them without
writing anything, and refuses what another tool manages as it would when it
runs. Until then the preview names the commit; d on the changes, or
helix-toolbox --effects plan --fetch-sources ID, downloads it into
~/.local/share/helixforge/sources, where the installers look first, and
changes nothing else.
Hardware
Section titled “Hardware”Hardware reads the machine without root: fwupd’s devices and the
firmware updates in the metadata it already has; each disk’s kind, size,
model, firmware and temperature; every temperature sensor, with those near
their limit picked out; each battery’s charge, health (what it holds against
its design capacity) and cycle count; PCI devices with their drivers, and USB
devices. A firmware update (f) asks you to type FIRMWARE, then shows its
plan with its own confirmation, because an interrupted firmware update can
leave a device unusable; a SMART health check (s) reads the disk’s health
record and needs your password. helix-toolbox hardware, --smart <disk> and
--firmware <device> do the same from the command line.
Services and startup
Section titled “Services and startup”Services lists systemd’s units of the machine and of your own session:
every installed service, timer and socket with whether it is enabled
(starts at boot or login) and whether it runs now, and those running or
failed without a unit file of their own (the per-application units desktops
start are left out). i shows the machine’s services, timers and sockets,
your session’s, what starts at login, or what failed; f narrows them to a
name or description. Enter shows a unit’s state, what needs it (systemctl list-dependencies --reverse) and, for a unit the machine or the session
needs, what stopping or disabling it costs: the login screen (your session
ends, or the next boot stops at a text console), networking and name
lookups, the firewall, SSH while you are connected through it, D-Bus,
polkit and systemd’s own units, and in your session sound and the desktop
portals. s starts or stops it, e enables or disables it (not static,
masked or generated units, which something else starts), R restarts it;
each is a plan with that cost as a warning first, high risk for those units,
and the machine’s own ask for your password. Masking is not offered.
At login lists the XDG autostart applications (/etc/xdg/autostart and
~/.config/autostart), whether each starts and whether it applies to this
desktop. d shows what it runs, its comment, whether it is the system’s
or your own and whether your file overrides the system’s. Enter turns one
off for you only, with a file of yours in
~/.config/autostart that says Hidden=true (the system’s stays as it
is), or on again by taking that out. helix-toolbox services (list [filter] [--user] [--failed], show <unit>, start, stop, restart,
enable, disable with --user, --dry-run and --yes) and
helix-toolbox startup (list, on <file>, off <file>) do the same.
Storage
Section titled “Storage”Storage shows the space on / (and the home folder’s file system when
it is apart), then what can be cleaned, each with what it takes and what
cleaning it frees: the package cache (pacman keeps the two newest versions
of each installed package through paccache, whose own dry run says what
it frees; apt, dnf and zypper clean theirs), unused packages (pacman’s
orphans, apt’s and dnf’s autoremove, zypper’s unneeded, by name, never a
kernel), unused Flatpak runtimes (flatpak uninstall --unused), system logs
older than four weeks (journalctl --vacuum-time=4weeks), the trash,
thumbnails and, on Arch, paru’s and yay’s build folders. Enter shows one’s
plan, which asks first. The kernels the machine can boot, snapshots and
Helix Toolbox’s configuration backups are listed and never offered: what
could undo a mistake stays. helix-toolbox storage and storage clean <item> (--dry-run, --yes) do the same.
Performance
Section titled “Performance”Performance reads systemd’s record of this boot (systemctl show of
the manager’s timestamps, as systemd-analyze time counts them): the
firmware, the boot loader, the kernel, the initial RAM disk and the
services, then what the login screen waited for (systemd-analyze critical-chain) and the slowest services since the boot (systemd-analyze blame). Below it, the machine now: the load against its processors,
memory and swap (zram or a disk), the kernel’s pressure figures for the
processor, memory and the disk over the last minute, the frequency
governor and power profile, and the programs holding the most memory.
Each boot is recorded once, the first time Helix Toolbox reads it or the
notifications’ timer runs, in boots.json beside the history (the last
50). This boot is set beside the one before it; b (or the window’s
choice) sets it beside an earlier one. The comparison lists each part and
each unit that moved by half a second or more, a kernel that changed, and
the Helix Toolbox runs between the two boots. Hints say what is worth
knowing: the firmware or the boot menu taking long, a service the login
screen waited two seconds or more for (for NetworkManager-wait-online and
systemd-networkd-wait-online, Enter plans disabling it, which asks
first), memory nearly full, swapping to disk without zram, and programs
waiting. It only reads. helix-toolbox performance (boots, compare <before> [after], a boot by its number in boots or the start of its id)
does the same.
Recovery
Section titled “Recovery”Recovery checks what would bring the machine back, reading only:
- System snapshots: Snapper (with a root configuration) or Timeshift, and Snapper’s count and newest where this user may list them; a notice when the newest is over a month old, or when nothing takes snapshots, with the entry that sets Snapper or Timeshift up.
- Starting from a snapshot, on Btrfs: whether the boot menu lists snapshots (grub-btrfs, limine-snapper-sync, openSUSE’s GRUB entries), so a system that no longer starts can start from one.
- A second kernel: the kernels in
/bootwith their boot images, and on Arch the advice to keeplinux-ltsbeside the kernel. - Configuration backups: how many Helix Toolbox’s entries left, and the newest.
- Your own files: the restic repository Restic backs up to, with its
newest snapshot once Restic has read them (listing them here could ask
for its password), else a backup program for the home folder (Borg,
restic, Kopia, Déjà Dup, Pika Backup, Vorta, Back In Time and others),
since system snapshots leave
/homeout and share the disk. - A record of this machine: the newest Drift baseline, a notice when there is none or it is over 90 days old.
c runs the snapshot check: as root, it lists the snapshots and, for
Snapper, checks the newest is a Btrfs subvolume holding /etc/os-release,
/usr/bin and /usr/lib/modules; for Timeshift, timeshift --list. It
rolls nothing back and takes or removes nothing, and asks first. f runs
the entry a check names. helix-toolbox recovery (--check-snapshots
with --dry-run and --yes, confirmed by typing CHECK) does the same.
Migration
Section titled “Migration”Migration moves what this machine has to another machine or
distribution. e exports it to a file (helix-toolbox-migration-<date>.toml
in your home folder unless you name another), reading only:
- the catalog entries one of whose own packages is installed: the family’s package or, on Arch, its AUR package;
- the Flatpak applications no entry covers, and those of an entry installed only as its Flatpak, so the other machine gets the same;
- the packages you installed yourself that no entry covers, as the package
manager records them (
pacman -Qqe,apt-mark showmanual,dnf repoquery --userinstalled, zypper’s packages less those it installed as dependencies,/etc/apk/world,xbps-query -m). Where they cannot be told apart (on Solus, or when the package manager does not answer), the screen says so and only the entries and Flatpaks go in the file.
o opens a migration file and says what each thing in it means here,
under four headings. To install: an entry through this distribution’s
own package (or the AUR, or its Flatpak), a Flatpak from Flathub (after the
Flatpak entry, when Flatpak is missing), and, when both machines are of the
same family, a package the repositories here have by its name. Here
already: what is installed, an entry’s Flatpak included. Cannot be
installed here: an entry this catalog lacks or that has no package for
this distribution, and Flatpaks where Flatpak is missing and no entry
installs it. Left to you: the packages of another family, with
whether the repositories here have one of the same name (it may not be
the same software), and packages of this family the repositories do not
have, such as ones from the AUR. A package another catalog had no entry
for becomes the entry this one has for it. The repositories are read from
the metadata already on the machine, with no network.
a (or Enter on a row to install) reviews the plan of the first list,
which continues past a failed install; d shows a row’s details, r reads
it again. helix-toolbox migrate export [file], migrate show <file> and
migrate apply <file> (--dry-run, --yes, confirmed by typing MIGRATE)
do the same.
Flatpak asks again before it installs, removes or updates anything, and
takes an answer only from a terminal, so the window and --yes without one
could not install a Flatpak. A Flatpak step in a plan therefore carries
-y: the plan you confirmed is the answer, and the -y is in the command
you review.
Restic
Section titled “Restic”Restic works with a restic repository of your own files. The repository
comes from the [restic] table of settings.toml:
[restic]repository = "/run/media/me/Backup/restic" # or sftp:, rest:, s3: and the otherspassword_file = "~/.config/restic/password" # or password_command = "…"paths = ["~/Documents", "~/Pictures"] # what a backup takes; the home folder when left outexcludes = ["~/.cache"] # restic --exclude patterns; ~/.cache and the trash when left outWithout it, restic’s own RESTIC_REPOSITORY and RESTIC_PASSWORD_FILE,
RESTIC_PASSWORD_COMMAND or RESTIC_PASSWORD are used, or a KWallet entry
that RESTIC_WALLET, RESTIC_WALLET_ENTRY and RESTIC_WALLET_FOLDER name;
then the settings Command Center left, read only. Helix Toolbox never
keeps a password, and refuses a repository address with one in it.
The screen lists the snapshots (the latest 30 of each machine and folder).
Enter browses one, a folder at a time. s looks for a name or path, with
* wildcards, in every snapshot: each version of each file it finds,
whether it changed from the version before (its size or time), and how
many newer snapshots of the same folder no longer have it; i looks
again ignoring upper and lower case. R on a
snapshot, a file or a version restores it into a new folder of your home
folder, which must not be there yet: restic restores with --overwrite never and reads what it wrote back (--verify, restic 0.17 or later).
F restores a snapshot you name (latest unless you type its ID), and
after it, only the path you type. The screen shows what the backup leaves
out.
b backs up the folders named (--exclude-caches too), c checks the
repository’s structure. Each is a plan you review.
Recovery tests prove a restore works before you need one. n records a
file’s SHA-256 (a file of your home folder, up to 100 MB) in
recovery-baselines.json beside the history, the last 50. Back it up, then
v on it restores it from a snapshot (the latest, or one you name) into a
temporary folder, compares, says PASS or FAIL and removes the folder.
w turns a daily backup on and W a weekly one, and either turns it off
when it is on: helix-toolbox-restic.timer and its
service in your systemd user folder, which run helix-toolbox restic backup --yes. It needs the password from a file or a command, since the timer
has none of your environment, and it never replaces or removes a unit it
did not write. helix-toolbox restic (files <snapshot> [folder],
history <pattern>, backup, check, restore <snapshot> <folder> [--include <path>], baseline [file], test <baseline> [snapshot] and
timer on|off [--weekly]; plans with --dry-run and --yes, confirmed by
typing BACKUP, CHECK, RESTORE or TEST) does the same. Settings turns the
timed backup on, every day or every week, and off as well.
Repositories
Section titled “Repositories”Repositories lists the Git repositories under your project folders:
[repositories] in settings.toml names them (roots, absolute or under
~/, and depth, 1 to 6 folders down, 3 by default); without it, the
folders Command Center was set up with, read only; else those of
~/github, ~/projects, ~/src, ~/code and ~/dotfiles that exist. A
folder holding .git is a repository, and is not looked into for more;
node_modules, target, .cache and links are passed over. Each shows its
branch, how many files changed, how it stands against its upstream and its
latest commit; favorites (f) come first.
Reading changes nothing: git runs with optional locks off, without the
repository’s hooks or file system monitor, with every content filter its
settings name emptied (through GIT_CONFIG_COUNT, so any name is given
back exactly), and without submodules’ changes, each probe within 15
seconds. A repository whose settings cannot be listed, or names a filter
that cannot be named back, is not looked into; nor is any where git is
older than 2.31.
Enter opens a repository: its changed files (Enter shows a file’s diff,
staged and not; Space stages it, or unstages it when it is all staged;
A stages every change), its branches (Enter switches; b creates one
and switches to it), its stashes (s stashes the changes, new files too;
Enter applies one with its index, keeping it), its tasks and its recent
commits. c commits what is staged, F fetches every remote, p pulls,
fast-forward only, and P pushes to the upstream, never forcing, or
publishes the branch to origin when it has none. Each is a plan, reviewed
first, that checks again when it runs: a commit that what is staged, HEAD
and the branch are as reviewed and nothing is under way; a branch switch,
a pull and a stash applied that the repository has no changes. A
repository in the middle of a merge, rebase, cherry-pick or revert is left
to git. Network steps ask for no password: a remote that needs one fails.
The repository’s hooks and commit signing run as they do with git.
Tasks are found in the repository’s manifests, which are read, never run:
package.json scripts (build, test, dev, lint, check, start),
Cargo (build, test, check, run), a Makefile’s all, build,
test, check and lint and a justfile’s build, test, check,
lint, run and dev. n keeps a command of your own as a task, in
workspaces.toml beside the settings, with your favorites; x removes it.
Enter runs a task in the repository’s folder after you review it, its
command split into words and run as it is, or with fish or bash when you
say so (--shell; in the terminal interface, begin the command with
fish: or bash:). A stages every change, after review.
helix-toolbox repos (show, diff [file] [--staged], stage [files] | --all, unstage, commit -m, branch [--create], stash [-m] [--untracked], stash-apply, fetch, pull, push, publish [remote],
tasks, task, task-add, task-remove, favorite [--off], group; a
repository by its name, or its path when names repeat; changes with
--dry-run and --yes, confirmed by typing GIT, a task by typing TASK)
does the same.
Configs
Section titled “Configs”Configs edits Ghostty’s and Fastfetch’s configuration. The file edited
is the one [configs] in settings.toml names (ghostty_source,
fastfetch_source, absolute or under ~/), else the one Command Center
was set up with, read only, else the live file (ghostty/config, or
config.ghostty where Ghostty 1.2 reads it, and fastfetch/config.jsonc
in the configuration folder). Where Home Manager links the live file into
the Nix store, it is never edited there: its source in your dotfiles
(configs/ghostty/config or configs/fastfetch/config.jsonc under
~/dotfiles, ~/github/projects/dotfiles or the dotfiles Command Center
named) is, and when that file is part of a Home Manager flake, you are
told to run Home Manager afterward. A file is only edited when it is a
full path without .., not in the Nix store, inside your home or
configuration folder, and 512 KB at most.
The checks: Ghostty’s own ghostty +validate-config of a copy, in Helix
Toolbox’s private folder beside the history (never a shared one, a link or
another user’s), or, without Ghostty, said not to be checked; Fastfetch’s
JSONC read here, comments and trailing commas allowed: one object, and
modules a list of names or objects with a "type".
Enter on a field changes it in a draft: Ghostty’s font (the first
font-family; the others stay as fallbacks), font size, theme, padding,
background opacity and cursor, the last line that sets each; Fastfetch’s
logo, its type and the modules, in order, each kept with its options. The
rest of the file, comments included, is left as it is. Several fields can
change before one save: c checks the draft, s saves it and x
discards it. E opens a private copy of the draft (or the file) in
$VISUAL or $EDITOR, then checks it. Either way the save is a plan you
review, the file side by side: run, it checks with sha256sum that the
file is as it was read, keeps it as a configuration backup beside it
(<file>.helix-toolbox-backup-<time>) and writes the new text, keeping the
file’s permissions. Text that does not check is not saved. Enter on a
backup puts it back, the file there now kept as a backup first, as
Backups and helix-toolbox restore do; d shows where the file is and
its SHA-256, r reads both again. helix-toolbox config <ghostty | fastfetch> (validate [file], set <field> <value>, edit, history;
saving with --dry-run and --yes, confirmed by typing SAVE) does the
same.
Home Manager
Section titled “Home Manager”Home Manager shows the configuration Home Manager builds: the folder
flake names under [home_manager] in settings.toml (~/ for the home
folder; folder#name or profile for the flake’s homeConfigurations
name), else the dotfiles Command Center was set up with (their
home-manager folder when it holds flake.nix) and its profile, read only,
else ~/.config/home-manager, holding flake.nix or home.nix. Below it,
the generations home-manager generations lists, newest first, with the
active one marked; the configuration’s Git repository (the nearest folder
above it holding .git, within your home folder), read as Repositories
reads one; and which of your configuration files (Ghostty’s, Fastfetch’s,
fish’s, Git’s, kitty’s and Neovim’s) Home Manager links into the Nix
store, so are changed in the configuration rather than in place.
b builds the configuration without activating it (home-manager build,
in its folder, which leaves a result link), s switches to it, and
Enter on an earlier generation goes back to it by running that
generation’s own activate script, as Home Manager’s manual says to; a
generation the Nix store has collected cannot be. p pulls the
configuration’s repository, fast-forward only. Each is a plan you review.
helix-toolbox home-manager (generations, build, switch, activate <generation>, pull; plans with --dry-run and --yes, confirmed by
typing BUILD, SWITCH, ACTIVATE or GIT) does the same.
Reliability and trust
Section titled “Reliability and trust”Reliability lists every entry with how far it has been tested, the
critical ones first (marked !: boot loaders, the boot splash, the login
screen, kernel security modules, graphics drivers and whole-system or disk
changes):
| Level | Means |
|---|---|
| Hardware Tested | a tester ran it on a real machine and reported it (helix-toolbox report --worked) |
| VM Tested | the Distributions workflow ran it for real in a virtual machine (Arch, Debian or Fedora, on BIOS or UEFI firmware, or the Arch live ISO), rebooted into the result and checked it |
| Container Tested | the Distributions workflow ran it in distribution containers and Helix Toolbox verified the result there |
| Stand-in Tested | installer tests run its script against stand-in commands and files, on every change and in each container |
| Not Yet Validated | nothing tests it yet beyond the checks every entry gets |
Beside each are the systems it was tested on, the date it was last verified
and when it last ran successfully on this machine. Release builds carry the
record of the Distributions run they were built after; other builds show the
stand-in tests and reports only; what of that record cannot be read is
said above the list. i shows only critical or only untested
entries, Enter the evidence. Before a critical entry with no more than
stand-in tests runs, its confirmation says so. helix-toolbox reliability [--critical] prints the same.
An entry that ran here can be reported as working: w on it, or on its run
in History (Report it worked… in the window), or helix-toolbox report --worked <entry> [--note "what you checked"]. The report gives the entry,
the date and version of its last successful run here, and the
distribution, desktop, model and graphics cards with their drivers (no
serial numbers, host name or user), with the [[hardware]] record it asks
for and a link that opens the issue form filled in. It is refused for a run
that failed and in a virtual machine or a container. Nothing is sent until
you submit the issue. In the terminal interface, c copies the report with
its link, as it does the bug report from Settings: through wl-copy, xclip
or xsel where the desktop has one, otherwise by asking the terminal itself
(OSC 52, which Ghostty, Kitty, WezTerm, foot and tmux understand). Both are
also saved under ~/.local/state/helix-toolbox/.
v on any entry (or helix-toolbox trust <id>) opens the trust inspector:
the installer’s origin (Helix Toolbox’s own installers, Linutil’s, or commands
built from package names), its file and SHA-256 checksum, its license and
the software’s (as the package manager reports it), and three kinds of
assurance kept apart:
- Release provenance: whether this Helix Toolbox, which ships the catalog
and every installer, is a release build with a signed build provenance
attestation, and whether its download was checked against
SHA256SUMS. - Package integrity: what each package source checks: pacman’s
signatures and the
SigLevelin effect, apt’s signed repositories, dnf’sgpgcheck, zypper’s and Flatpak’s signatures; the AUR’s user-submitted build scripts are marked unverified. - Downloads the installer makes itself: sources pinned to a commit, downloads it checks with a checksum or signature, and ones nothing checks, such as a script piped into a shell or a plain HTTP address.
Then the privileges it uses (a password, system files, services, the commands it runs as root) and its validation level.
Helix Doctor, backups and snapshots
Section titled “Helix Doctor, backups and snapshots”Helix Doctor checks the machine, read-only, and shows what it found:
network and DNS (a name lookup of github.com), failed system and user
services with their last journal lines, whether each graphics card has a
driver in use (or nouveau where NVIDIA’s is wanted), a stale pacman lock or
unfinished dpkg configuration, files in your home that belong to root,
kernels without an initramfs, a GRUB configuration without its menu, the EFI
partition’s room and free disk space. Enter shows a check’s evidence and
what to do; where a safe repair exists (restart the resolver or a service,
remove a stale lock, dpkg --configure -a, give files back to you, rebuild
the initramfs or GRUB’s menu, clear package caches) f runs it after its own
confirmation, or runs the entry that addresses it (the graphics drivers).
The counts of problems, notices and checks that are OK head the list, and
a check’s details name the commands its repair runs. The Helix Doctor
reports are listed below the checks, entries like any other: Enter runs
one, Space queues it, d, p, v and * as in the areas.
helix-toolbox doctor prints the checks and helix-toolbox doctor --repair <id> runs one repair.
The Backups screen (and helix-toolbox backups) lists the configuration
backups Helix Toolbox’s entries leave beside a file before changing it
(<file>.commander-backup-<time>, <file>.helix-toolbox-backup-<time>), newest
first: your own in ~/.config, ~/.local/share and ~, and system ones in
/etc, /boot and the SDDM theme and font folders. Enter (or helix-toolbox restore <backup>) puts one back after a confirmation: the file now in its
place is moved aside as its own backup first, so a restore can be undone the
same way; system files ask for your password. Only backups Helix Toolbox finds
can be restored.
On Btrfs with Snapper (a root configuration) or with Timeshift, a snapshot
is taken first before runs that change system files, the kernel or disks
(flags PFM, K, D, SI, or high risk): Snapshot before system changes in
Settings, which the command line follows too; --snapshot takes one there
when Settings turns it off. If the snapshot fails, the steps it was for
are not run even when a run continues after a failed step (the rest of
the run still does), and they stay in the Install Plan to try again.
Where such a run gets no snapshot because neither is set up, its confirmation says so (No snapshot: neither Snapper nor Timeshift is set up here.), and --snapshot on a run that changes
none of those says it takes none. Helix Toolbox does not roll
snapshots or packages back itself; the Backups screen says where to (Btrfs
Assistant, snapper rollback, Timeshift).
The command line
Section titled “The command line”helix-toolbox system # the distribution and package manager it seeshelix-toolbox list # the catalog as tabs, groups and entrieshelix-toolbox search rip grep # entries by name, id or description, closest firsthelix-toolbox info git # one entryhelix-toolbox status # every package entry: installed, update, managed or nothelix-toolbox update --dry-run # what updating every entry with an update would runhelix-toolbox updates --online # what each package tool has waitinghelix-toolbox updates --apply --dry-run # what updating those channels would runhelix-toolbox notifications on # tell me on the desktop when updates wait; off, check, or nothing for what is onhelix-toolbox notifications health on # and of new health problems; drift <baseline> for Drifthelix-toolbox plan git system-report # what running entries would dohelix-toolbox run git --dry-run # the plan, nothing changedhelix-toolbox run git # runs after you type RUN, asked on the terminal even when pipedhelix-toolbox remove ardour # removes a package entry that offers ithelix-toolbox profile list # your profiles; also export, import, deletehelix-toolbox drift save "Old laptop" # record this machine as a baselinehelix-toolbox drift check # how it differs now; --profile <name> for a profilehelix-toolbox setup gaming # what the Gaming workstation would add here, as a planhelix-toolbox bundle create ~/b git htop # packages and Helix Toolbox, for a machine offlinehelix-toolbox desktop # the desktop, its look and who else sets ithelix-toolbox plan sddm --effects # what it would change, files side by sidehelix-toolbox --effects plan --fetch-sources dotfiles-nvim # with the dotfiles source to comparehelix-toolbox hardware # firmware, disks, temperatures, batteries, deviceshelix-toolbox services list --failed # systemd units; show, start, stop, restart, enable, disablehelix-toolbox startup off <file> # what the desktop starts at login, for youhelix-toolbox storage # where the space goes; storage clean <item> frees somehelix-toolbox performance # this boot, the machine now, and the boot before; boots, comparehelix-toolbox recovery # snapshots, kernels, backups; --check-snapshots looks inside, as roothelix-toolbox migrate export [file] # what this machine has, to take to anotherhelix-toolbox migrate show <file> # what a migration means here; migrate apply installs ithelix-toolbox restic # the repository and its snapshots; history, restore, testhelix-toolbox repos # the Git repositories under your project foldershelix-toolbox config ghostty # the file edited, its checks and fields; set, edit, historyhelix-toolbox repos show <repo> # its changes, branches, stashes, commits and tasks; stage, commit, push...helix-toolbox home-manager # its configuration and generations; build, switch, activate, pullhelix-toolbox reliability --critical # how far the boot, login and driver entries are testedhelix-toolbox trust sddm # where an entry comes from and what checks ithelix-toolbox doctor # health checks, read-onlyhelix-toolbox doctor --repair permissions # one repair, after confirmationhelix-toolbox backups # configuration backups, newest firsthelix-toolbox restore <backup> # put one back, keeping the current filehelix-toolbox history # recent runshelix-toolbox docgen docs/walkthrough.md # the catalog as Markdownhelix-toolbox status --json # any reading command, or a --dry-run plan, as JSONhelix-toolbox report # what a bug report needs, to paste into an issuehelix-toolbox report --worked sddm # that an entry worked here, for its Hardware Tested recordhelix-toolbox verify sddm grub-dracula # whether entries left the machine as they should, read-onlyA plan the command line runs (run, remove, update, restore and the
other commands that change the machine) shows the confirmation the menu
and the window show, as text: each step with its command, the notes and
what is not run, then Risk: medium · asks for your password, what the
checks before a run found, Warning: lines (the plan’s own, and how
entries were tested), and After a failed step: stop (Settings changes it) when there is more than one step. It follows the run choices in
Settings, as they do: a snapshot first before system changes, and whether
a failed step stops the run; --snapshot and --keep-going turn those on
for one run. A plan that continues past a failure itself, such as
migrate apply’s, does so whatever Settings says, in every interface. plan and --dry-run show the same without running
anything; a blocked plan lists its steps and what blocks it.
--json prints one JSON document for other programs instead of text; it
works with the commands that read and with --dry-run plans, and refuses
anything that would change the machine. The shapes are in
docs/JSON.md.

