feat(terminal): Kitty only — drop Ghostty (#95)
Some checks failed
Check / eval (push) Has been cancelled

Ghostty's OpenGL 4.3 floor broke the Acer (HD 4000 / 4.2). Dual-terminal
support (default Ghostty + install-time Kitty fallback) was more complexity
than it was worth.

- Remove ghostty.nix / nomarchy.ghostty.enable
- Kitty always installed and themed from theme-state
- Default nomarchy.terminal = kitty; SUPER+Return, doctor, calendar,
  what-changed use kitty --class=com.nomarchy.*
- Drop install-time glxinfo probe and mesa-demos on the installer
- Docs/REQUIREMENTS no longer list OpenGL 4.3 as a terminal floor

Verified: V0 flake check; option-docs; installer-safety; template HM has
kitty, no ghostty; menu/calendar emit classed kitty launches.
This commit is contained in:
2026-07-15 09:51:27 +01:00
parent 1e648b6c49
commit 545e40f4d9
32 changed files with 151 additions and 299 deletions

View File

@@ -10,8 +10,7 @@
./stylix.nix # GTK/Qt/cursor/fonts from the same JSON
./hyprland.nix
./waybar.nix
./ghostty.nix
./kitty.nix # themed fallback when Ghostty cannot run (OpenGL < 4.3)
./kitty.nix # sole terminal (themed); doctor/calendar/--class load-bearing
./btop.nix
./rofi.nix # launcher theming + the nomarchy-menu dispatcher
./swaync.nix # notification daemon, themed from the same JSON

View File

@@ -1,48 +0,0 @@
# Ghostty — Nomarchy's default terminal, themed from theme-state.json.
# Colors, fonts and the full 16-color ANSI palette are baked from the
# JSON at eval time.
{ config, lib, ... }:
let
t = config.nomarchy.theme;
c = t.colors;
in
{
# Ghostty is ALWAYS installed — it's Nomarchy's default terminal and is
# load-bearing (SUPER+E file manager, the calendar launcher's classed
# window, etc.), so the distro enforces it. `nomarchy.ghostty.enable` now
# gates only whether Nomarchy's theming/config is applied — a user can
# keep ghostty but drop our config, they just can't remove ghostty itself.
programs.ghostty = {
enable = true;
enableBashIntegration = true;
settings = lib.mkIf config.nomarchy.ghostty.enable {
# ── Typography (from theme-state.json) ────────────────────────
font-family = t.fonts.mono;
font-size = t.fonts.size;
# ── Colors (from theme-state.json) ────────────────────────────
background = c.base;
foreground = c.text;
cursor-color = c.accent;
selection-background = c.overlay;
selection-foreground = c.text;
split-divider-color = c.surface;
# "N=#rrggbb" entries; Ghostty accepts repeated `palette` keys,
# which the HM module renders from this list.
palette = lib.imap0 (i: color: "${toString i}=${color}") t.ansi;
# ── Chrome ────────────────────────────────────────────────────
# background-opacity is theme-driven (normal priority — use the
# CLI); the rest are mkDefault so a plain home.nix value wins.
background-opacity = t.ui.terminalOpacity;
window-padding-x = lib.mkDefault 12;
window-padding-y = lib.mkDefault 12;
window-decoration = lib.mkDefault false;
gtk-single-instance = lib.mkDefault true;
confirm-close-surface = lib.mkDefault false;
};
};
}

View File

@@ -1026,15 +1026,14 @@ in
"float 1, match:class (?i)^(\\.?blueman-(manager|adapters)(-wrapped)?|\\.?system-config-printer(-wrapped)?)$"
"center 1, match:class (?i)^(\\.?blueman-(manager|adapters)(-wrapped)?|\\.?system-config-printer(-wrapped)?)$"
# Calendar popup (item 42): the Waybar clock's on-click runs
# nomarchy-calendar → calcurse in a ghostty window tagged with a
# distinct --class, so it floats centered instead of tiling.
# Calendar popup (item 42): nomarchy-calendar → calcurse in a
# kitty window tagged with a distinct --class, so it floats centered.
"float 1, match:class ^(com\\.nomarchy\\.calendar)$"
"size 60% 65%, match:class ^(com\\.nomarchy\\.calendar)$"
"center 1, match:class ^(com\\.nomarchy\\.calendar)$"
# Doctor sheet (System Doctor / Waybar custom/doctor click):
# nomarchy-menu doctor → ghostty --class=com.nomarchy.doctor.
# nomarchy-menu doctor → kitty --class=com.nomarchy.doctor.
"float 1, match:class ^(com\\.nomarchy\\.doctor)$"
"size 55% 70%, match:class ^(com\\.nomarchy\\.doctor)$"
"center 1, match:class ^(com\\.nomarchy\\.doctor)$"

View File

@@ -1,26 +1,13 @@
# Kitty — fallback terminal when Ghostty cannot run (OpenGL < 4.3 on
# older GPUs, e.g. Intel HD 4000). Themed from the same theme-state.json
# as Ghostty so a machine that needs the fallback still looks like
# Nomarchy. Enabled when nomarchy.terminal is "kitty" (installer sets
# that after a GL probe) or when nomarchy.kitty.enable is forced on.
# Kitty — Nomarchy's only terminal, themed from theme-state.json.
# Colors, fonts and the full 16-color ANSI palette are baked from the
# JSON at eval time (same contract Ghostty used to have). Always
# installed: SUPER+Return, SUPER+E, doctor, calendar, and $TERMINAL
# all depend on it.
{ config, lib, ... }:
let
t = config.nomarchy.theme;
c = t.colors;
# Default terminal may be a bare name ("kitty") or a path; match the
# basename so settings.terminal = "kitty" and nomarchy.terminal =
# "${pkgs.kitty}/bin/kitty" both light this module.
terminalIsKitty =
let
term = config.nomarchy.terminal;
base = lib.last (lib.splitString "/" term);
in
base == "kitty" || lib.hasPrefix "kitty " term;
enabled = config.nomarchy.kitty.enable || terminalIsKitty;
# Kitty colorN = ANSI 015 from the theme palette.
colorSettings = lib.listToAttrs (
lib.imap0 (i: color: {
name = "color${toString i}";
@@ -29,35 +16,37 @@ let
);
in
{
config = lib.mkIf enabled {
programs.kitty = {
enable = true;
shellIntegration.enableBashIntegration = true;
shellIntegration.enableZshIntegration = true;
# Kitty is ALWAYS installed. `nomarchy.kitty.enable` gates only whether
# Nomarchy's theming/config is applied — a user can keep kitty but drop
# our config; they cannot remove kitty itself without breaking the
# desktop's load-bearing classed windows.
programs.kitty = {
enable = true;
shellIntegration.enableBashIntegration = true;
shellIntegration.enableZshIntegration = true;
font = {
name = t.fonts.mono;
size = t.fonts.size;
};
settings = {
background = c.base;
foreground = c.text;
cursor = c.accent;
cursor_text_color = c.base;
selection_background = c.overlay;
selection_foreground = c.text;
url_color = c.accent;
active_border_color = c.accent;
inactive_border_color = c.surface;
# Match Ghostty's padding / opacity so the two terminals feel
# like the same product when a machine falls back.
background_opacity = t.ui.terminalOpacity;
window_padding_width = lib.mkDefault 12;
confirm_os_window_close = lib.mkDefault 0;
enable_audio_bell = lib.mkDefault false;
wayland_titlebar_color = lib.mkDefault "background";
} // colorSettings;
font = lib.mkIf config.nomarchy.kitty.enable {
name = t.fonts.mono;
size = t.fonts.size;
};
settings = lib.mkIf config.nomarchy.kitty.enable ({
background = c.base;
foreground = c.text;
cursor = c.accent;
cursor_text_color = c.base;
selection_background = c.overlay;
selection_foreground = c.text;
url_color = c.accent;
active_border_color = c.accent;
inactive_border_color = c.surface;
background_opacity = t.ui.terminalOpacity;
window_padding_width = lib.mkDefault 12;
confirm_os_window_close = lib.mkDefault 0;
enable_audio_bell = lib.mkDefault false;
wayland_titlebar_color = lib.mkDefault "background";
# Fresh windows for doctor/calendar --class launches (not one shared instance).
single_instance = lib.mkDefault false;
} // colorSettings);
};
}

View File

@@ -100,17 +100,17 @@ in
# ── Preferences ────────────────────────────────────────────────
terminal = lib.mkOption {
type = lib.types.str;
default = config.nomarchy.settings.terminal or "ghostty";
default = config.nomarchy.settings.terminal or "kitty";
example = "kitty";
description = ''
Terminal emulator command, used by keybinds and `$TERMINAL`.
Default is Ghostty. On GPUs below OpenGL 4.3 the installer writes
`settings.terminal = "kitty"` so SUPER+Return still works (Ghostty
needs 4.3; see docs/REQUIREMENTS.md). Set explicitly to override.
Terminal emulator command for keybinds and `$TERMINAL`. Nomarchy
ships and themes **Kitty only** (sole supported terminal works
on older GPUs that Ghostty's OpenGL 4.3 floor rejected). Override
only if you install another emulator yourself.
'';
};
kitty.enable = lib.mkEnableOption "Kitty with Nomarchy theming (palette/font/opacity from theme-state); also auto-on when nomarchy.terminal is kitty (OpenGL < 4.3 install fallback)";
kitty.enable = lib.mkEnableOption "Nomarchy's Kitty configuration (palette/font/opacity from theme-state)" // { default = true; };
keyboard.layout = lib.mkOption {
type = lib.types.str;
@@ -403,7 +403,6 @@ in
shell.enable = lib.mkEnableOption "the zsh shell experience (starship prompt, bat/eza/zoxide)" // { default = true; };
keys.enable = lib.mkEnableOption "the SSH + GPG agent (gpg-agent fronting SSH, pinentry-qt)" // { default = true; };
fastfetch.enable = lib.mkEnableOption "fastfetch system info fronted by the themed Nomarchy logo" // { default = true; };
ghostty.enable = lib.mkEnableOption "Nomarchy's Ghostty configuration" // { default = true; };
btop.enable = lib.mkEnableOption "btop with the per-theme nomarchy theme" // { default = true; };
stylix.enable = lib.mkEnableOption "Stylix theming for the long tail of apps (GTK, Qt, cursors)" // { default = true; };
displays.enable = lib.mkEnableOption "the nwg-displays interactive monitor arranger (a helper to find nomarchy.monitors values; the declarative config stays the source of truth)" // { default = true; };

View File

@@ -946,11 +946,10 @@ ${themeRows}
exec ${cfg.terminal} -e sudo nomarchy-snapshots ;;
doctor)
# Read-only health sheet in a floating, centered ghostty window
# (class matched by hyprland.nix windowrules). --gtk-single-instance
# =false forces a fresh window same pattern as nomarchy-calendar.
# Exit code doesn't matter; the sheet itself is the product.
exec ghostty --class=com.nomarchy.doctor --gtk-single-instance=false \
# Read-only health sheet in a floating, centered kitty window
# (class matched by hyprland.nix windowrules). Same pattern as
# nomarchy-calendar. Exit code doesn't matter; the sheet is the product.
exec kitty --class=com.nomarchy.doctor \
-e sh -c "nomarchy-doctor
printf '\nEnter to close.'; read -r _" ;;
@@ -1045,14 +1044,14 @@ ${themeRows}
whatchanged)
# Plain-language last rebuild (system + desktop nvd). Toast the
# one-liners; open a floating terminal for the full report when
# the user wants detail (same ghostty class pattern as Doctor).
# the user wants detail (same kitty class pattern as Doctor).
if ! command -v nomarchy-what-changed >/dev/null 2>&1; then
notify-send "What changed" "nomarchy-what-changed not on PATH (lifecycle package?)."
exit 0
fi
summary=$(nomarchy-what-changed --summary 2>/dev/null || true)
[ -n "$summary" ] && notify-send -a Nomarchy "What changed" "$summary"
exec ghostty --class=com.nomarchy.doctor --gtk-single-instance=false \
exec kitty --class=com.nomarchy.doctor \
-e sh -c "nomarchy-what-changed
printf '\nEnter to close.'; read -r _" ;;

View File

@@ -1,11 +1,11 @@
# Shell experience — zsh (the default login shell, set system-side) with
# autosuggestions + syntax highlighting, a themed starship prompt, and
# modern CLI tools wired in: bat (cat), eza (ls), zoxide (cd). bat uses
# the "ansi" theme so it follows the terminal palette (Ghostty is themed
# the "ansi" theme so it follows the terminal palette (Kitty is themed
# from the same JSON); starship is themed from the palette directly.
#
# home.shell.enableZshIntegration = true is the single lever that makes
# every integrating program (starship, eza, zoxide, ghostty, yazi) emit
# every integrating program (starship, eza, zoxide, kitty, yazi) emit
# its zsh hooks — no per-module flags needed.
{ config, lib, pkgs, ... }:
@@ -133,7 +133,7 @@ in
};
# bat: "ansi" follows the terminal's 16-color palette → tracks the
# active Nomarchy theme (Ghostty bakes it) with no per-theme config.
# active Nomarchy theme (Kitty bakes it) with no per-theme config.
programs.bat = {
enable = true;
config = {

View File

@@ -1,7 +1,7 @@
# Stylix — themes the long tail of applications (GTK, Qt, cursors,
# fonts) from the same theme-state.json that drives the live engine.
#
# Division of labour: the hot-reload trio (Hyprland, Waybar, Ghostty)
# Division of labour: the hot-reload trio (Hyprland, Waybar, Kitty)
# is owned by the Nomarchy engine and updates instantly; everything
# Stylix touches updates on the next home-manager switch. That is why
# autoEnable is off and the trio's Stylix targets stay disabled.

View File

@@ -6,7 +6,7 @@
#
# Theme changes are fully Home Manager managed: `nomarchy-theme-sync
# apply <theme>` writes the JSON and runs `home-manager switch`, baking
# everything (Hyprland, Waybar, Ghostty, btop, Stylix) into one
# everything (Hyprland, Waybar, Kitty, btop, Stylix) into one
# read-only generation. No runtime patching, no partial states; theme
# history is generation history.
#

View File

@@ -93,20 +93,15 @@ let
[ -n "$next" ] && powerprofilesctl set "$next"
'';
# Opens calcurse (a lightweight TUI calendar, month view by default) in a
# floating, centered ghostty window — bound to the Waybar clock's on-click.
# A distinct --class gives the window a matchable app-id for the
# float+center+size windowrule (hyprland.nix); --gtk-single-instance=false
# forces a fresh standalone window (ghostty defaults single-instance on).
# calcurse is installed with the bar (home.packages below); the gate is
# only for someone who force-removed it. ghostty is always installed
# (ghostty.nix), so it can be relied on for the --class window.
# Opens calcurse (lightweight TUI calendar) in a floating, centered kitty
# window — Waybar clock on-click. Distinct --class → hyprland.nix float
# rules. Kitty is always installed (kitty.nix).
calendarLauncher = pkgs.writeShellScriptBin "nomarchy-calendar" ''
if ! command -v calcurse >/dev/null 2>&1; then
notify-send "Calendar" "calcurse isn't installed (removed from home.packages?)." 2>/dev/null
exit 0
fi
exec ghostty --class=com.nomarchy.calendar --gtk-single-instance=false -e calcurse
exec kitty --class=com.nomarchy.calendar -e calcurse
'';
# VPN indicator — shows a shield when a NetworkManager VPN/WireGuard
@@ -213,7 +208,7 @@ let
# into clock + clock#date — one click surface for the calendar).
format = "{:%H:%M · %a %d %b}";
# Left-click → the calendar (nomarchy-calendar → calcurse in a floating
# ghostty). Tooltip is plain date/zone only — embedding {calendar}
# kitty). Tooltip is plain date/zone only — embedding {calendar}
# produced an empty popup on hardware (2026-07-10); month view is
# one click away.
on-click = "nomarchy-calendar";

View File

@@ -1,5 +1,5 @@
# yazi — the flagship file manager: a fast, keyboard-driven TUI that
# fits the distro's identity (Ghostty's Kitty-graphics previews, rofi
# fits the distro's identity (Kitty graphics previews, rofi
# menus, everything from one JSON). Themed from theme-state.json and
# shipped with a curated plugin set. The GUI half (Thunar, "open folder"
# handler) is nomarchy.system.fileManager on the system side.
@@ -92,7 +92,7 @@ in
# Theme from the palette. yazi merges this over its built-in theme,
# so only the accent-bearing UI is specified; everything else keeps
# yazi's defaults (which already follow Ghostty's ANSI colors).
# yazi's defaults (which already follow Kitty's ANSI colors).
theme = {
mgr = {
cwd = { fg = c.accent; };

View File

@@ -4,7 +4,7 @@
# nixosModules.nomarchy in flake.nix) and layer your machine specifics
# (bootloader, hostname, users, hardware) on top. Host concerns are
# deliberately NOT set here. Everything user-facing (Hyprland config,
# Waybar, Ghostty, theming) lives in modules/home.
# Waybar, Kitty, theming) lives in modules/home.
{ config, lib, pkgs, ... }:
let