archinstall 4.3 maps the deprecated top-level 'bootloader': 'Limine'
to BootloaderConfiguration(bootloader=Limine, removable=True) (per
lib/args.py:185-190 and lib/models/bootloader.py:56-69). Our new
_install_limine_omarchy mirrors archinstall's removable handling: it
would copy BOOTX64.EFI to EFI/BOOT (fallback path) and SKIP
efibootmgr, neither of which is what we want.
Switch to the explicit bootloader_config form with removable=false
so we take the EFI/limine path + register the 'Limine' NVRAM entry
as intended.
archinstall's add_bootloader creates EFI/arch-limine/{BOOTX64.EFI, BOOTIA32.EFI}, writes a limine.conf with an Arch Linux entry, and registers an efibootmgr label "Arch Linux Limine Bootloader" — only for limine-snapper.sh to delete it all and rebuild with Omarchy branding via limine-mkinitcpio-hook.
Replace the add_bootloader call with _install_limine_omarchy, which does the same work archinstall's _add_limine_bootloader does (UEFI EFI binary copy + efibootmgr register, or BIOS limine-bios.sys + limine bios-install) but with Omarchy-owned paths and labels from the start:
- EFI subdir: EFI/limine (not EFI/arch-limine)
- efibootmgr: label "Limine" (not "Arch Linux Limine Bootloader")
- loader path: \EFI\limine\BOOTX64.EFI
Compute the kernel cmdline directly from disk_config instead of harvesting it from a file archinstall wrote (whose path keeps drifting across versions). Then write /etc/default/limine and /etc/kernel/cmdline, and stage /boot/limine.conf from our styling template — limine-mkinitcpio-hook will add the actual boot entries when it deploys.
Adds limine + efibootmgr to EARLY_PACKAGES (archinstall used to pacstrap these as a side effect of add_bootloader).
Does not modify limine-snapper.sh — its cleanup code will simply no-op because there are no arch-limine paths or "Arch Linux Limine Bootloader" entries to find. That code can be pruned in a follow-up.
archinstall 4.3 writes limine.conf to <target>/<esp_mount>/EFI/arch-limine/
limine.conf for UEFI non-removable installs (lib/installer.py:1487), not
to /mnt/boot/limine.conf as our code assumed. Older archinstall versions
used different paths.
Probe the 4.3 paths (arch-limine, BOOT, limine subdir) and the legacy
/boot/limine.conf in order; pick whichever exists. Error message now
lists everywhere it looked so future drift is easy to diagnose.
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.