Restore the env + redirect setup that the previously-working ISO
installer used (matching /home/ryan/Downloads/ISO scripts/.automated_script.sh):
export COLUMNS=$(tput cols)
export LINES=$(tput lines)
exec > >(tee >(sed CSI-strip >> log) 2>/dev/null) 2>/dev/tty
export CLICOLOR_FORCE=1
export FORCE_COLOR=1
The cutover commit (064b5e2) silently dropped these. Subsequent
attempts to fix the TTY/gum rendering by reshaping the redirect were
all symptom-chasing — the proven shape was correct. The key insight:
- gum draws its TUI on stderr, not stdout. 2>/dev/tty keeps that
rendering on the real terminal.
- stdout-as-pipe (via tee) is *desired*: it lets gum detect a
non-TTY stdout and skip cursor-position probes (CSI 6n). Without
that detection, the DSR replies leak as visible ^[[13;1R bytes.
- CLICOLOR_FORCE/FORCE_COLOR force gum to still emit colour despite
stdout being a pipe.
Also drops the configurator's _drain_tty workaround — unnecessary
once gum stops sending DSR queries in the first place.
bash's `read -t 0` only TESTS whether input is available; it does not
consume the bytes. So the drain loop `while read -t 0 ...; do :; done`
spun forever the moment any bytes were pending (e.g., the DSR reply
sitting in the tty input buffer after gum style sent CSI 6n).
That hung the configurator at the first step() title screen — blank
prompt, blinking cursor, no keyboard form.
Use `read -t 0.05 -N 9999` once, which consumes up to 9999 bytes with
a 50ms timeout. Always returns after 50ms whether there's data or not.
Single call replaces the while loop.
configure_protected_boot used to arch-chroot pacman -S limine
efibootmgr, but at that phase the live ISO's offline mirror is not
bind-mounted into the target yet (run_chroot_finalizer does that
later) and the target's pacman.conf points at network mirrors that
aren't reachable during an offline install.
Pacstrap these packages alongside the runtime package list in
arch_install_base, where archinstall is still pacstrapping against
the live ISO's offline mirror. Drop the now-redundant arch-chroot
pacman call from configure_protected_boot.
gum's TUI startup queries the terminal (e.g., cursor position via
CSI 6n) and doesn't always read the reply. The reply bytes
("^[[13;1R") then surface visibly next to the next step title.
A one-time drain at script start (in .automated_script.sh) catches
the boot-time replies but not the gum-per-call ones, since the
artifact came back at every new step().
Add a small _drain_tty helper and call it from step() after the
title gum-style invocation so any pending DSR replies are consumed
before the next prompt runs.
archinstall 4.3's Installer.__init__ types target as Path and uses it
directly (self.target / 'boot', etc.). Passing str(mountpoint) makes
self.target a str, so every internal path operation raises
'unsupported operand type(s) for /: str and str' — most visibly during
set_mirrors, which constructs target / MIRRORLIST.relative_to_root().
Drop the str() cast; pass the Path through as-is.
ArchConfigHandler reads --config and --creds from sys.argv via argparse at
construction time; it ignores ARCHINSTALL_CONFIG/ARCHINSTALL_CREDS env
vars (confirmed in archinstall 4.3 lib/args.py:_parse_args). Setting those
env vars was a no-op, so handler.config.disk_config was always None when
the wrapper stripped our args off the real argv.
Fix: build a synthetic argv [prog, --config <path>, --creds <path>] and
swap it into sys.argv just for the ArchConfigHandler() call, then
restore. Drops the unused 'import os' now that the env var lines are
gone.
Fix the ^[[13;1R cursor-position-report artifacts visible next to the
first configurator step. archiso's boot init leaves DSR responses in the
kernel tty input buffer; the first gum invocation reads them as stray
input and echoes them as visible escape sequences.
- Drain stdin (with a short timeout) from /dev/tty before configurator
runs so any pending replies are consumed.
- Drop the explicit </dev/tty stdin redirect — the parent script's
stdin is already tty1 (inherited from archiso autostart), and the
explicit redirect opened a new fd with subtly different termios.
All install-phase logic now lives in the Python orchestrator and the
omarchy-iso-* bash helpers. .automated_script.sh becomes a thin shim that:
- sources install helpers (env for configurator)
- sets the Tokyo Night palette on the live VT
- tees stripped stdout/stderr to /var/log/omarchy-install.log
- runs the configurator wizard
- exec's omarchy-iso-install with absolute config paths
Absolute paths are required because the wrapper cd's into
/usr/share/omarchy-iso before invoking the orchestrator.
Removed install_base_system, install_omarchy, install_arch, install_disk,
cleanup_install_disk, configure_login_for_unencrypted_install, and
chroot_run_as_user — all replaced by Python phases or bash helpers.
Bind mounts set up in run_chroot_finalizer used to be torn down in finish,
but finish doesn't run when a phase between the two raises. Move the unmount
loop into a dedicated cleanup_bind_mounts function and call it from main()'s
finally so it runs on success, failure, and KeyboardInterrupt.
The orchestrator drives an offline install on the live ISO using
archinstall as a library subsystem. Lands under configs/airootfs/ so
mkarchiso bakes it into the live squashfs directly:
/usr/share/omarchy-iso/orchestrator/ (the Python package)
/usr/local/bin/omarchy-iso-install (thin shell wrapper that
execs python -m orchestrator.main)
Two corrections vs the previous omarchy-installer location:
1. omarchy-installer dropped from EARLY_PACKAGES \u2014 it's live-ISO-only
install tooling, must never land on the target. /etc/skel is still
populated pre-useradd via omarchy-settings.
2. run_chroot_finalizer now copies /usr/share/omarchy from the live
ISO into /mnt/tmp/omarchy-install/ before arch-chroot. finalize.sh
+ install/ scripts run from /tmp inside the chroot; /tmp is wiped
on first reboot, so the target boots with zero install detritus.
The live ISO runs as root with XDG_RUNTIME_DIR=/run/user/0; arch-chroot
-u ryan switches the UID but doesn't reset the env, so tools running as
ryan tried to write to root's runtime dir (dconf failed to commit,
omarchy-theme-set's flock target hit Permission denied). Drop the var
so tools fall back to no-runtime-dir behaviour, which works inside the
chroot.
Two motivations:
1. Plymouth: the omarchy plymouth theme + /etc/plymouth/plymouthd.conf
ship from omarchy-settings (theme at /usr/share/plymouth/themes/omarchy,
plymouthd.conf via the package's post_install etc-overrides hook).
Without omarchy-settings on the live ISO, mkarchiso builds the initrd
with plymouth pointing at the default theme instead of Omarchy's. Now
it picks up the Omarchy theme on boot like the installed system does.
2. Drops the .pkg.tar.zst extraction hack in .automated_script.sh:
OMARCHY_PATH=/usr/share/omarchy is the real package install path, so
use_omarchy_helpers no longer needs to bsdtar pieces out of the
offline mirror into /tmp/omarchy-iso.
archinstall creates the user from user_credentials.json BEFORE installing
the 'additional packages' list, so when omarchy-settings populates
/etc/skel/.config/... later in the pacstrap, the user's home has already
been created from an empty skel and missed the seed (user boots into a
terminal with no Hyprland configs).
Copy /etc/skel into /home/$OMARCHY_USER after archinstall finishes (by
which point omarchy-settings has populated skel) and chown to the user.
cp -rT keeps it idempotent: existing files get overwritten, dirs merge.
omarchy's hard depends are now just the bricking set, not the full default
install. After archinstall pacstraps the meta packages (which populates
/etc/skel before user creation), install the rest of omarchy-base.packages
in the chroot before running omarchy-install.
With the cleaner dep graph, omarchy-installer no longer transitively
pulls omarchy + omarchy-settings + omarchy-limine. Pacstrap both
explicitly so /etc/skel (via omarchy -> omarchy-settings) is populated
before archinstall creates the user.
archinstall creates the user AFTER pacstrap. If omarchy-settings (which
ships /etc/skel/.config/**) isn't pacstrap'd, the user is created with
an empty skel and never gets the Omarchy default configs in their HOME.
Add omarchy-installer to the configurator's archinstall package list
(its depends pull omarchy + omarchy-settings + omarchy-limine), so all
the package files are in place before the user is created.
install_omarchy no longer needs the explicit 'pacman -S omarchy-installer'
step; it just runs 'omarchy-install' which is already at /usr/bin/.
presentation.sh reads $OMARCHY_PATH/logo.txt to compute LOGO_WIDTH and
LOGO_HEIGHT, which then drive max_line_width in logging.sh / errors.sh.
We were only extracting omarchy-installer into /tmp/, so logo.txt was
missing, LOGO_WIDTH=0, max_line_width=-4, and bash's substring expression
errored with 'substring expression < 0'.
Extract from omarchy-settings into the same /tmp tree so all the
presentation/logging helpers find what they expect. Renamed the dir
from omarchy-installer-iso to plain omarchy-iso since it now blends
content from two packages.
The ISO no longer carries a cp -r'd copy of the omarchy git checkout
into /root/omarchy and the target /home/$user/.local/share/omarchy.
Instead it builds omarchy-installer + omarchy-settings + omarchy +
omarchy-limine from mounted source trees (${OMARCHY_INSTALLER_PATH:-
../omarchy-installer} and ${OMARCHY_PKGS_PATH:-../omarchy-pkgs}),
drops them in the offline mirror, and pacstraps omarchy-installer
during the target install — which deps-in the other three.
- builder/build-omarchy-packages.sh: new. Builds the four packages
inside the ISO build container using each PKGBUILD's OMARCHY_SRC
override (introduced in Chunk 2). Creates a 'builder' user because
makepkg refuses to run as root. Drops the resulting .pkg.tar.zst
files into the offline-mirror directory.
- builder/build-iso.sh: drop the git clone / -v omarchy mount path;
call build-omarchy-packages.sh first; filter out the locally-built
package names from the rest-of-mirror download so we don't try to
fetch them from the network mirror.
- configs/airootfs/root/.automated_script.sh: replace the install_omarchy
cp-and-source dance with 'arch-chroot pacman -S omarchy-installer'
followed by 'OMARCHY_INSTALL_MODE=offline omarchy-install'. Drop the
big chown/chmod block that was setting up the cloned tree.
use_omarchy_helpers extracts the installer's helpers/ tree directly
from the offline-mirror's omarchy-installer-*.pkg.tar.zst so the live
ISO has access to gum-styled logging before pacstrap.
- bin/omarchy-iso-make: always mount omarchy-installer and omarchy-pkgs
(paths configurable via OMARCHY_INSTALLER_PATH / OMARCHY_PKGS_PATH;
default to ../omarchy-installer and ../omarchy-pkgs). --local-source
is now a back-compat no-op.
* Configurator tester
* Make it a dry run
* Offer a no-encryption install mode
* Fix SDDM login
* Simplify the flow by using ctrl-c to toggle into unencrypted mode