Skip to content

Theming

Marchyo owns every themed surface itself, all derived from the Jylhis Design System: the desktop (GTK, Hyprland, the Quickshell shell, Waybar, Mako, Ghostty, fzf, bat, hyprlock, starship, the console, the Vicinae launcher, the Plymouth boot splash), Qt (through the GTK settings, QT_QPA_PLATFORMTHEME=gtk3), the TUI long tail (lazygit, k9s, ncspot, spotify-player, gdu), and Emacs (the design system’s own jylhis themes). Most surfaces restyle at runtime via marchyo theme set/next — no rebuild. There is no Stylix: marchyo retired it once every surface it covered had a marchyo-owned path.

The launcher is a slightly different case, and split by shell: with marchyo.shell.enable the in-shell launcher themes itself from the design tokens at runtime (the shell’s Color singleton — no registration needed), while the discrete stack’s Vicinae gets two real themes (jylhis-dark for dark, jylhis-light for light) generated from the design tokens and registered both, so the full color surface — text, inputs, buttons, list and grid selection, scrollbars, tooltips — is covered rather than just the background/accent basics. See Launcher.

Option Type Default Description
marchyo.theme.enable bool true Enable the theming system
marchyo.theme.variant "dark" or "light" "dark" Theme variant preference
marchyo.theme.scheme string or null null Override the base16 color scheme (a tinted-schemes catalog name)
marchyo.theme.fontScale number (0.5–4.0) 1.25 Global font-size multiplier applied to every text surface
marchyo.theme.themes list of string or inline base16 theme ["jylhis-dark" "jylhis-light"] Themes available for runtime switching (pre-built into the closure)
marchyo.theme.followWallpaper bool false marchyo bg set / bg next also generate a matugen theme from the new wallpaper (details)
marchyo.theme.wallpaper.enable bool true Enable the generated Marchyo grid wallpaper where supported
marchyo.theme.wallpaper.package package pkgs.marchyo-wallpapers Package providing generated Marchyo wallpaper assets
marchyo.theme = {
enable = true;
variant = "dark";
};

By default the theme is the Jylhis Design System palette, derived from its themes/jylhis.json:

Variant Palette
"dark" Jylhis Dark (the “Negative” mode)
"light" Jylhis Light (the “Print” mode)

Both variants sit on a cool, near-neutral ground with a single bronze interactive accent, a benchmark-vermilion brand mark, and a structural contour blue used for linework only. Code colors are Emacs Modus Operandi (light) / Vivendi (dark), so syntax reads identically in every editor and terminal.

To use a different base16 scheme instead, set marchyo.theme.scheme to the name of a .yaml file in the tinted-theming/schemes catalog (the base16/ directory):

marchyo.theme = {
variant = "dark";
scheme = "gruvbox-dark-medium"; # any tinted-schemes catalog name, e.g. "nord"
};

A base16 theme in runtime switching (a catalog or inline entry, or a matugen result) colours each design token from the slot that best matches its role:

Slot Tokens
base00 bg
base01 bg-subtle, accent-subtle
base02 surface, selection-bg
base03 text-faint, border, syn-comment
base04 text-muted, border-strong
base05 text
base06 text-heading
base07 surface-raised
base08 status-err, destructive, syn-variable
base09 accent, accent-hover, cursor, syn-number
base0A status-warn
base0B syn-string, status-ok
base0C syn-type, syn-builtin
base0D status-info, syn-function
base0E syn-keyword
base0F brand

selection-bg, destructive and the extra syn-* tokens follow the slot the base16 styling guidelines name for that role (Selection Background, Diff Deleted, Variables, Integers, Support, Functions). contour, decorator, scrim and syn-docstring have no base16 role and keep the Jylhis hex. A matugen theme additionally takes border, border-strong and accent-subtle from Material’s outline_variant, outline and primary_container when matugen emits them.

Marchyo carries the design system’s three type roles across the system — the fontconfig role mapping (modules/generic/fontconfig.nix), the GNOME interface fonts Qt and GTK apps resolve (modules/home/jylhis-theme.nix), and every surface that names a family directly. The defaults are:

Role Family Package
Display / headings (serif) Zilla Slab pkgs.zilla-slab
Body (sansSerif) Hanken Grotesk pkgs.hanken-grotesk
Monospace BlexMono Nerd Font (IBM Plex Mono, Nerd Font patched) pkgs.nerd-fonts.blex-mono

The Nerd Font patch of IBM Plex Mono is used for monospace because the desktop chrome — Waybar, Mako, hyprlock, Ghostty — needs the icon glyphs. To change the role mapping, override the fontconfig defaults:

fonts.fontconfig.defaultFonts.monospace = [ "JetBrainsMono Nerd Font" ];

marchyo.theme.fontScale is a single multiplier that resizes every text surface at once — the interface fonts (GTK, Qt, Electron), the terminal, the bar, notifications, the lock screen, the launcher, the TUI apps, and the TTY console. It defaults to 1.25 (noticeably larger than upstream defaults). Set it to 1.0 to restore the historical sizes, or higher for HiDPI-at-distance or accessibility:

marchyo.theme.fontScale = 1.5; # everything ~50% larger

Each surface scales from its own base size and rounds to a whole number, so the proportions between surfaces are preserved.

marchyo.theme.themes lists the themes available for runtime switching — no rebuild needed. Each listed theme’s desktop assets (Waybar CSS, Mako config, Hyprland colors, Ghostty colors, wallpaper, GTK CSS + the dconf color-scheme, bat config, fzf colors, hyprlock colors, console palette, the k9s skin, lazygit, spotify-player and gdu colors, and a palette.json token map) are pre-built into the system closure so a switch is an instant symlink swap. The default list is the Jylhis pair; add any tinted-schemes catalog name to make it switchable:

marchyo.theme.themes = [
"jylhis-dark"
"jylhis-light"
"nord"
"gruvbox-dark-hard"
];

An entry can also be an inline base16 theme — the catalog contract — so you can add an arbitrary palette (an omarchy colors.toml, a matugen result, your own) without it living in any upstream catalog. Provide the sixteen base00..base0F slots and a polarity; every runtime surface is derived from them, and an optional wallpaper overrides the default grid:

marchyo.theme.themes = [
"jylhis-dark"
{
name = "kanagawa";
variant = "dark";
slots = {
base00 = "#1f1f28"; base01 = "#2a2a37"; base02 = "#223249"; base03 = "#727169";
base04 = "#c8c093"; base05 = "#dcd7ba"; base06 = "#938aa9"; base07 = "#363646";
base08 = "#c34043"; base09 = "#ffa066"; base0A = "#dca561"; base0B = "#98bb6c";
base0C = "#7fb4ca"; base0D = "#7e9cd8"; base0E = "#957fb8"; base0F = "#d27e99";
};
# wallpaper = ./kanagawa.png; # optional; defaults to the Jylhis grid
}
];

Runtime switching covers every surface except the Plymouth boot splash (it is not on screen during a session) and ncspot (its theme sits inline in config.toml, which has no include, so it follows the build-time variant/scheme at rebuild). Qt follows the GTK swap: the session runs QT_QPA_PLATFORMTHEME=gtk3, so Qt apps pick up the swapped gtk.css and dconf color-scheme on next launch. The switch is ephemeral: the next activation resets to the declarative default.

The TUI apps read their colours through the ~/.config/marchyo/current-theme pointer. k9s restyles open sessions: marchyo theme relinks ~/.config/k9s/skins/jylhis.yaml at the new theme’s skin, and k9s watches its skins directory. lazygit, spotify-player and gdu pick up the new theme the next time they start. ~/.config/spotify-player/theme.toml and ~/.config/gdu/gdu.yaml link into the pointer, and lazygit loads LG_CONFIG_FILE, which lists its main config.yml followed by the pointer’s lazygit.yml (lazygit merges the files in order, so the theme overlay wins). LG_CONFIG_FILE is a session variable, so it applies from the next login. These TUI colours come from base16 slots: with marchyo.theme.scheme set, the declarative theme’s files carry that scheme’s slots, as the build-time config does. Off the desktop, and on Darwin, the TUI apps keep the build-time colours.

GTK apps follow a runtime switch on next launch (newly started apps read the swapped ~/.config/gtk-{3,4}.0/gtk.css; libadwaita apps additionally restyle live via the dconf color-scheme). Ghostty restyles open windows live too — its runtime include names the Jylhis pair as a ghostty light/dark theme pair (theme = dark:…,light:…), which ghostty resolves from the system color-scheme, so the same dconf write that flips libadwaita apps recolors running terminals. The Quickshell bar (marchyo.shell.enable) recolors live as well — it reads the active theme’s palette through the same pointer — and Super+Shift+L cycles the theme from the compositor.

A generated Marchyo grid wallpaper is enabled by default wherever it is supported. To disable it, or to supply your own wallpaper asset package:

marchyo.theme.wallpaper = {
enable = false; # skip the generated wallpaper
# package = pkgs.my-wallpapers; # or swap in a different asset package
};

marchyo theme generate <image> builds a colour scheme from a wallpaper with matugen and applies it live — no rebuild:

Terminal window
marchyo theme generate ~/Pictures/wall.jpg # let matugen pick the polarity
marchyo theme generate ~/Pictures/wall.jpg --light # force a light scheme
marchyo theme generate ~/Pictures/wall.jpg --dark # force a dark scheme
marchyo theme generate --revert # back to the declarative theme

matugen extracts a base16 palette from the image, which Marchyo maps through the same token slots the catalog schemes use. A generated theme restyles every surface a theme set does: the shell (bar, panels, toasts), the terminal (Ghostty), Hyprland window borders, Mako, Waybar, GTK (plus the dconf color-scheme), bat, fzf, the hyprlock fallback lock screen, the console palette (best-effort, as for every switch), k9s, lazygit, spotify-player, gdu, and the wallpaper itself.

The colours come from two files the build ships in the declarative variant’s theme dir: palette.json (every design token’s hex, syn-* included, and the token-to-base16-slot table) and templates/ (the Mako, Waybar and GTK configs with each colour as a token placeholder). theme generate fills each placeholder with the matugen slot for that token, and a token with no base16 slot keeps the build variant’s hex. For bat it writes a marchyo-generated.tmTheme into bat’s themes directory and runs bat cache --build.

Qt follows the runtime GTK swap on next launch (QT_QPA_PLATFORMTHEME=gtk3), and starship styles through ANSI slot names, so it already recolors with the terminal’s live palette. Only the Plymouth boot splash (not on screen during a session) and ncspot keep the declarative theme until the next rebuild (Runtime theme switching). Like marchyo bg, the generated theme is runtime-only: a rebuild (or --revert) resets to marchyo.theme.variant/scheme. Requires the desktop feature (matugen ships with it).

An opt-in Material You mode makes the theme track the wallpaper. It is off by default; the Jylhis palette stays the declarative theme either way.

marchyo.theme.followWallpaper = true;

With it set, every marchyo bg set <image> and marchyo bg next runs the theme generate path on the new image after setting it, with matugen picking the polarity as a bare theme generate <image> does. If generation fails (matugen missing, an unreadable image), the wallpaper still changes, the CLI prints a warning, and the command exits 0.

Both changes are recorded as runtime overrides, so marchyo runtime restore at login replays the wallpaper and the generated theme together. A failed generation leaves the theme override as it was, so restore replays the new wallpaper and whichever theme was live before. marchyo bg set --revert shows the active theme’s wallpaper, which under a generated theme is the image it came from; marchyo theme generate --revert and marchyo theme set return to a declarative theme as usual, and a rebuild resets everything.

To use the light theme:

marchyo.theme = {
variant = "light";
};

With the Quickshell shell (marchyo.shell.enable = true), a set of palette-independent axes adjust the shell’s geometry, corners, animation speed, contrast, and overall shape without touching the colour palette. The scale axes default neutral; the style axes (floatingBar, surfaceAlpha) are Caelestia-inspired and default on.

marchyo.theme.appearance = {
# floatingBar = false; # full-width strip bar instead of the floating pill
# surfaceAlpha = 1.0; # opaque surfaces, no blur (default 0.85 glass)
# cornerRadiusScale = 0.0; # square every corner (default 1.0)
# uiScale = 1.2; # larger chrome without changing font size
# animationSpeed = 2.0; # faster transitions (default 1.0)
# highContrast = true; # thicker panel/notification borders
};
Option Type Default Description
floatingBar bool true Detached rounded pill bar with gaps to the screen edges; false restores the full-width strip
surfaceAlpha float 0.85 Surface opacity; below 1 enables the Hyprland blur effect for the shell’s layer surfaces (glass look)
cornerRadiusScale float 1.0 Multiplier on corner radii (0.0 squares corners)
uiScale float 1.0 Geometry multiplier on top of fontScale, fonts unchanged
animationSpeed float 1.0 Animation speed (higher is faster)
highContrast bool false Thicker separators for higher-contrast chrome

With the shell on, Hyprland also turns on short compositor animations driven by a snappy popin bezier: windows pop in, the shell’s panels, launcher, and OSD pop in, the bar slides from its edge, and toasts and tooltips keep their own QML transitions. Workspace switches and border colour changes stay instant. With the shell off, compositor animations stay disabled.

The greetd login greeter is built in the host’s marchyo.theme.variant, so a light host shows a light login screen. It also follows the session theme: every marchyo theme set, next, or generate writes the active theme’s colours to /var/lib/marchyo/greeter/theme.json, and the greeter picks them up at start and whenever the file changes. The directory is owned by root:users with mode 1775, so session users can write their own marker but cannot replace another user’s. The greeter accepts only #rrggbb values for colour keys it already knows; a missing or invalid file falls back to the built-in variant palette. A declarative rebuild does not touch the marker, so the greeter keeps the last theme the CLI activated.