feat(terminal): themed Kitty when OpenGL < 4.3 (#95)
All checks were successful
Check / eval (push) Successful in 3m41s

Ghostty needs OpenGL 4.3; older GPUs (Intel HD 4000) top out at 4.2.
Installer probes glxinfo and writes settings.terminal=kitty into
theme-state when below the floor. modules/home/kitty.nix enables Kitty
with the same palette, mono font, and opacity as Ghostty so the fallback
still looks like Nomarchy.

Default machines stay Ghostty-only (no kitty in the HM closure). Doctor
and calendar still invoke Ghostty by class — V3 on Acer for SUPER+Return.

Verified: V0 flake check; installer-safety; HM with terminal=kitty builds
themed kitty.conf + TERMINAL=kitty; default template has no kitty bin.
This commit is contained in:
2026-07-15 09:45:32 +01:00
parent a09399702d
commit 1e648b6c49
12 changed files with 179 additions and 71 deletions

View File

@@ -15,6 +15,7 @@
, pciutils # lspci
, usbutils # lsusb (fingerprint-reader VID probe; sysfs is the fallback)
, btrfs-progs # inspect-internal map-swapfile (hibernation offset)
, mesa-demos # glxinfo — OpenGL probe for Ghostty floor (needs 4.3)
, xkeyboard_config # human-readable installed layout/variant catalog
# Baked metadata — what this installer installs and where it came from.
, templateDir # templates/downstream (home.nix, theme-state.json)
@@ -64,6 +65,7 @@ stdenvNoCC.mkDerivation {
--prefix PATH : ${lib.makeBinPath [
bash gum disko whois git python3
util-linux gptfdisk parted cryptsetup lvm2 pciutils usbutils btrfs-progs
mesa-demos
]} \
--set NOMARCHY_INSTALL_SHARE "$share" \
--set NOMARCHY_XKB_RULES ${xkeyboard_config}/share/X11/xkb/rules/base.lst \

View File

@@ -625,6 +625,47 @@ python3 "$SHARE/patch-template.py" "$FLAKE_DIR" <<PYJSON
}
PYJSON
# Ghostty requires OpenGL 4.3 (docs/REQUIREMENTS.md). On older GPUs (Intel
# HD 4000 / Ivy Bridge tops at 4.2) it cannot map a surface. Prefer Kitty
# as the default terminal when we can prove the floor is missing — written
# into theme-state.json so SUPER+Return works after first boot without a
# hand edit. Unknown probe → leave Ghostty (do not guess on headless VMs).
gl_ver=""
if command -v glxinfo >/dev/null 2>&1; then
gl_ver=$(
{ DISPLAY="${DISPLAY:-:0}" WAYLAND_DISPLAY="${WAYLAND_DISPLAY:-}" \
glxinfo -B 2>/dev/null || glxinfo -B 2>/dev/null || true; } \
| sed -n 's/.*OpenGL version string: \([0-9][0-9]*\.[0-9][0-9]*\).*/\1/p' \
| head -1
)
fi
if [[ -n "$gl_ver" ]]; then
gl_major=${gl_ver%%.*}
gl_minor=${gl_ver#*.}
gl_minor=${gl_minor%%.*}
if (( gl_major < 4 || (gl_major == 4 && gl_minor < 3) )); then
info "OpenGL $gl_ver < 4.3 — default terminal → kitty (Ghostty needs 4.3)"
python3 - "$FLAKE_DIR/theme-state.json" <<'PY'
import json, sys
path = sys.argv[1]
with open(path, encoding="utf-8") as f:
state = json.load(f)
settings = state.setdefault("settings", {})
# Do not clobber an explicit user/template choice.
if not settings.get("terminal"):
settings["terminal"] = "kitty"
settings["terminalReason"] = "opengl-below-4.3"
with open(path, "w", encoding="utf-8") as f:
json.dump(state, f, indent=2)
f.write("\n")
PY
else
info "OpenGL $gl_ver ≥ 4.3 — keeping Ghostty as the default terminal"
fi
else
info "OpenGL version not probed (glxinfo unavailable or no display) — Ghostty stays default"
fi
# The flake.lock: composed offline — nomarchy is path-locked to the very
# source the ISO carries (original stays the forge URL, so a later
# `nix flake update` on the installed machine re-resolves normally).