Match the disk-overwrite screen, where the unencrypted-install hint sits on
the line right below its message.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Restore the pre-OEM behavior: a disk with no unallocated free space has just
one viable mode, so the wizard skips the mode picker and goes straight to the
overwrite confirmation. The picker appears only when a free-space install is
also on offer.
Also give the harness's first-boot SSH bootstrap more headroom (360s): an
encrypted OEM first boot re-keys LUKS and rebuilds the UKI before sshd
settles, which can exceed 180s under parallel VM load.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The normal install flow returns to its original order: keyboard, then the
user step, then disk selection and mode. The Ctrl+C shortcut on the first
screen and its confirmation now speak only of preparing the machine for
another owner — no 'OEM' in any user-facing string (the omarchy_install.oem
data contract is unchanged).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Restore the original screen order (keyboard first, then disk) and make Ctrl+C
on the keyboard screen the entry into OEM mode — the same hidden-Ctrl+C idiom
the disk-overwrite screen already uses for unencrypted installs. A confirm
guards against an accidental Ctrl+C; once confirmed, OEM jumps straight to
disk selection and the overwrite confirmation (no keyboard, no user), since
OEM is always a full-disk install. The 'OEM install' entry leaves the mode
picker. The harness drives the new path.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Remove oem_supported() and its branches: the configurator always offers OEM
install now, rather than scanning the offline mirror's runtime package to
decide. Building an ISO against a runtime that ships OEM support is the
build's responsibility; the orchestrator still fails an OEM install with a
clear error if the staged target somehow lacks omarchy-oem-setup.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The wizard now opens on disk selection; keyboard moves to after the install
mode is chosen and stays before the user step (so the LUKS passphrase is
still typed under the chosen layout). OEM installs skip keyboard and user
entirely — the machine's owner picks both at first boot — so the emitted
config just carries a default 'us' keymap as a placeholder.
The QEMU harness drives the new order and the OEM first-boot keyboard step.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Review findings from codex and Copilot:
- A rig-supplied credentials file in OEM mode now contributes only its LUKS
passphrase: preserved users/root_enc_password fields would have created a
hidden provisioning account despite OEM promising no user until first boot.
- The factory snapshot is taken writable, scrubbed of deployment credentials
(staged authorized_keys, tailscale auth key and join unit, the dead OEM
LUKS key and its initramfs drop-ins), then set read-only — a reset years
later must not authorize the original deployment key or rejoin its tailnet.
- The missing-Node-tarball case is a hard install error on every install,
not just OEM: the stash is what lets a factory reset finalize offline.
- The configurator's OEM gate checks the runtime package for the service
unit as well as the setup binary.
- The test harness handles the deliberately skipped mode picker on blank
disks when the bundled runtime lacks OEM support.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The configurator now peeks into the offline mirror's runtime package for
omarchy-oem-setup before offering the OEM install mode, so an ISO built
against a pre-OEM runtime can't start an install doomed to fail at the
staging phase (which still hard-checks as the backstop). Blank disks with no
OEM choice to offer skip the mode picker entirely, like the pre-OEM flow.
Also keep the test harness QMP socket in /tmp — unix socket paths cap at
~108 bytes, which nested test-run directories can exceed.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
OEM mode installs the entire system but defers user creation to first boot,
where the runtime's omarchy-oem-setup asks for the owner and lands them in the
already-installed system — and the same machinery arms omarchy-reset-computer.
The configurator's install-mode step gains an OEM choice, which required
moving the user step after mode selection (OEM skips it entirely). Autoinstall
rigs select OEM with an `oem` marker file on the cidata drive, which also
replaces the user_credentials.json requirement.
In the orchestrator, OEM swaps the user phases for a stage_oem_state phase:
it stashes the bundled Node tarball (every install, for offline factory
resets), arms omarchy-oem-setup.service in the target, and on encrypted
installs stages the throwaway LUKS passphrase — generated by InstallContext
when the input carries none — with a keyfile embedded in the UKI so boot
auto-unlocks until first-boot setup re-keys to the owner's password. The
install fails with a clear error if the bundled runtime lacks OEM support.
Every install now also ends with a read-only @factory snapshot of @ at the
btrfs top level — outside snapper's reach — which is what makes
omarchy-reset-computer a true factory reset.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The username regex accepted names that already exist on the target, so
useradd failed inside arch_install_system — after the disk had been
partitioned and formatted, which is the worst point to discover it.
From #59 by @wolfgangw, applied to quattro; it was opened against main.
Co-Authored-By: Wolfgang Woehl <tito@online.de>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Remeasure the terminal at every screen redraw instead of once at boot:
the framebuffer can settle after the configurator starts (VM windows
especially), which left stale padding for the whole flow. Pad the
confirm-screen warnings with say so every line shares the same left
edge. Boot the test VM with SDL instead of GTK, whose GL display path
crops the guest framebuffer on HiDPI Wayland desktops.
Verified in a live VM by driving the whole flow over QMP and reading
each screen back from /dev/vcs1: all screens center on the real console
width.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Three echo-through-awk substitutions to split one line into three
variables is what read was made for.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The free-space and full-disk paths each carried verbatim copies of the
T2 Mac kernel detection, the credentials JSON heredoc, the identity/
encryption answer files, the dry-run print-and-cleanup block, and the
udev settle loops. Pull those into detect_kernel, write_user_files,
print_dry_run_files, and wait_for_device, which also removes a subtle
rm vs rm -f drift between the two dry-run cleanups.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
We decided Omarchy always creates its own dedicated ESP and never adopts
a Windows one, so shared_esp was declared empty and never assigned —
every conditional on it was guaranteed to take the dedicated-ESP branch.
Collapse the whole dual-path structure into straight-line code and keep
detect_windows_esp only for the "leaving it untouched" message.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
build-iso.sh bakes tzupdate into the live environment, so the runtime
pacman fallback was dead there — and in a dry run on a dev machine it
would install a package as a side effect. tzupdate -p already fails
gracefully into the manual timezone filter when the tool is missing.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Drop the dead LOGO_PATH override, the redundant package-targets sourcing,
the unused TERM_HEIGHT and OMARCHY_NVIM_PACKAGE, the non-gum exports, and
the logo fallback branches. Trust that logo.txt is where OMARCHY_PATH says.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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.
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.
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.
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/.
* 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