Keystone SystemsKS Systems

Desktop environment

The Keystone desktop module provides a complete Wayland desktop built on the Hyprland tiling compositor. It includes session management via UWSM, audio through PipeWire, login with greetd, a comprehensive keybinding system, screen recording with GPU-accelerated encoding, night light filtering, and monitor management. The desktop module automatically enables the terminal module, so all terminal tools are available within the graphical environment.

Enabling the module

The desktop environment is enabled per-user through the keystone.os.users option. The system-level NixOS desktop module must also be imported in the flake configuration.

{
  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.05";
    keystone.url = "github:ncrmro/keystone";
    home-manager.url = "github:nix-community/home-manager/release-25.05";
  };

  outputs = { nixpkgs, keystone, home-manager, ... }: {
    nixosConfigurations.workstation = nixpkgs.lib.nixosSystem {
      system = "x86_64-linux";
      modules = [
        home-manager.nixosModules.home-manager
        keystone.nixosModules.operating-system
        keystone.nixosModules.desktop
        {
          keystone.os = {
            enable = true;
            storage = {
              type = "zfs";
              devices = [ "/dev/disk/by-id/nvme-WD_BLACK_SN850X_2TB" ];
            };
            users.alice = {
              fullName = "Alice Smith";
              email = "alice@example.com";
              extraGroups = [ "wheel" "networkmanager" ];
              initialPassword = "changeme";
              terminal.enable = true;
              desktop = {
                enable = true;
                hyprland.modifierKey = "SUPER";
              };
            };
          };
        }
      ];
    };
  };
}

Hyprland compositor

Hyprland is a dynamic tiling Wayland compositor. Keystone uses the official Hyprland flake for the latest features and integrates it with UWSM (Universal Wayland Session Manager) for proper session lifecycle management.

Session management

Sessions are managed through UWSM, which handles:

  • Proper systemd user session setup for the Wayland compositor.
  • D-Bus activation and XDG portal initialization.
  • Clean session teardown on logout.

The greetd login manager starts the Hyprland session via uwsm start -F Hyprland. Applications that require the Wayland session should be launched through uwsm app -- to ensure they inherit the correct environment.

Default applications

The following default applications are configured:

| Application | Default | Launch binding | | :------------------- | :------- | :------------- | | Terminal | Ghostty | Mod+Return | | Application launcher | Walker | Mod+Space | | Browser | Chromium | Mod+B | | File manager | Nautilus | Mod+E |

Keybinding system

The keybinding system is designed for a fully keyboard-driven workflow with consistent patterns across all tools.

Modifier key strategy

Keystone uses a layered modifier approach to avoid conflicts between the compositor, terminal multiplexer, and applications:

| Modifier | Scope | Examples | | :------------ | :------------------------------ | :--------------------------------------- | | Super (Mod) | Window manager operations | Focus, workspaces, launch apps | | Ctrl | Application-level operations | Zellij tabs, editor commands | | Alt | Pane navigation, window cycling | Zellij panes, Alt+Tab | | Shift | Modified operations | Reverse direction, move instead of focus |

By default, altwin:swap_alt_win is enabled in the keyboard options. This swaps the physical Alt and Super keys so that the physical Alt key (in the ergonomic thumb position) sends Super keycodes. The result is that frequent window management operations are accessible from the natural thumb resting position. The physical Super key then sends Alt keycodes, which provides browser back/forward navigation via Alt+Left/Right (sent by pressing physical Super+Arrow).

Caps Lock is remapped to Control by default (ctrl:nocaps). This places Ctrl in a more ergonomic position for terminal and editor usage. The remapping can be disabled by setting capslockAsControl = false, which instead maps Caps Lock to the Compose key.

Window management

| Key | Action | | :------------ | :------------------------------------- | | Mod+Return | Open a new terminal | | Mod+Space | Open the application launcher (Walker) | | Mod+W | Close the active window | | Mod+F | Toggle fullscreen | | Shift+F11 | Fullscreen (exclusive) | | Mod+Shift+V | Toggle floating mode | | Mod+T | Toggle split direction | | Mod+S | Toggle scratchpad workspace | | Mod+Shift+S | Move window to scratchpad |

Focus navigation

| Key | Action | | :----------------------- | :----------------------- | | Mod+Left/Right/Up/Down | Move focus directionally | | Mod+H | Move focus left | | Mod+L | Move focus right | | Alt+Tab | Cycle through windows | | Alt+Shift+Tab | Cycle windows in reverse |

Window movement

| Key | Action | | :----------------------------- | :----------------------------------- | | Mod+Shift+Left/Right/Up/Down | Swap the active window directionally | | Mod+Minus/Equal | Resize window width | | Mod+Shift+Minus/Equal | Resize window height | | Mod+Left Mouse | Drag to move a window | | Mod+Right Mouse | Drag to resize a window |

Workspace navigation

| Key | Action | | :---------------------------------- | :------------------------------------- | | Mod+1 through Mod+0 | Switch to workspaces 1 through 10 | | Mod+Shift+1 through Mod+Shift+0 | Move window to workspaces 1 through 10 | | Mod+Tab | Next workspace | | Mod+Shift+Tab | Previous workspace | | Mod+Ctrl+Tab | Last visited workspace | | Mod+Comma/Period | Adjacent workspace navigation | | Mod+Shift+Comma/Period | Move window to adjacent workspace |

Utilities and menus

| Key | Action | | :---------------- | :---------------------------------------------------- | | Mod+Escape | Open the Keystone menu system | | Mod+K | Display searchable keybindings help | | Mod+B | Open browser | | Mod+E | Open file manager | | Mod+C/V/X | Universal copy, paste, cut (via Insert key remapping) | | Mod+Ctrl+V | Open clipboard manager (clipse) | | Mod+Ctrl+E | Open emoji/symbol picker | | Print | Take a screenshot | | Shift+Print | Screenshot to clipboard | | Mod+Ctrl+I | Toggle idle inhibition | | Mod+Ctrl+N | Toggle night light | | Mod+Shift+Space | Toggle Waybar visibility |

Hardware keys

| Key | Action | | :---------------------- | :------------------------ | | XF86AudioRaiseVolume | Increase volume by 5% | | XF86AudioLowerVolume | Decrease volume by 5% | | XF86AudioMute | Toggle mute | | XF86AudioMicMute | Toggle microphone mute | | XF86MonBrightnessUp | Increase brightness by 5% | | XF86MonBrightnessDown | Decrease brightness by 5% | | XF86AudioPlay/Pause | Toggle media playback | | XF86AudioNext/Prev | Next/previous track | | Power button | Open system menu |

Hardware portability

The keybinding system is designed to work consistently across different keyboard hardware without requiring per-device Nix configuration. The OS-level key swap (altwin:swap_alt_win) ensures that any keyboard -- whether a Framework laptop keyboard, a UHK split keyboard with custom layers, or a standard desktop keyboard -- sends consistent keycodes to Hyprland.

Ghostty integration

The Ghostty terminal emulator is configured to delegate all multiplexing to Zellij. Ghostty's built-in tab and split management keybindings are unbound to prevent conflicts:

  • Ctrl+PageUp/Down and Ctrl+Tab are unbound (Zellij handles tab navigation).
  • Ctrl+Shift+O and directional splits are unbound (Zellij handles pane management).
  • Ghostty retains its own tab shortcuts on Ctrl+Shift+W/E/R/C for the rare case where Ghostty-level tabs are needed outside of Zellij.

PipeWire audio

PipeWire provides the audio stack with compatibility layers for ALSA, PulseAudio, and JACK. It is enabled by default when the desktop module is active.

The configuration includes:

  • rtkit: Real-time scheduling for low-latency audio.
  • PulseAudio: Disabled in favor of PipeWire's PulseAudio compatibility layer.
  • ALSA, Pulse, and JACK: All PipeWire compatibility backends enabled.

Audio devices can be managed through pavucontrol (PulseAudio Volume Control), which is included in the desktop system packages.

greetd login manager

greetd is a minimal, daemon-based login manager. Keystone configures it with auto-login to the Hyprland session via UWSM. The PAM session is registered as a Wayland session with class user, which ensures that loginctl lock-session functions correctly for the lock screen.

Menu system

The Keystone menu system is accessible via Mod+Escape or the power button. It provides a hierarchical launcher with the following categories:

  • Apps: Application launcher.
  • Capture: Screenshot and screen recording controls.
  • Toggle: Night light, idle inhibition, and system feature toggles.
  • Style: Theme switching.
  • Setup: Monitor configuration and system settings.
  • System: Lock, suspend, restart, and shutdown.
  • Learn: Keybindings reference and documentation.

The menu can be invoked with a category argument to navigate directly to a specific submenu (for example, keystone-menu system).

Screen recording

Keystone provides built-in screen recording through gpu-screen-recorder, using GPU-accelerated encoding for minimal performance impact.

Starting and stopping

There are three ways to control screen recording:

  1. Menu: Press Mod+Escape, navigate to "Capture", and select "Screenrecord".
  2. Waybar indicator: A red indicator appears in the center of the status bar while recording. Clicking it stops the recording.
  3. Command line: Use the keystone-screenrecord command.
# Start recording (video only)
keystone-screenrecord

# Record with desktop audio
keystone-screenrecord --with-desktop-audio

# Record with microphone
keystone-screenrecord --with-microphone-audio

# Record with both audio sources
keystone-screenrecord --with-desktop-audio --with-microphone-audio

# Stop an active recording
keystone-screenrecord --stop

Running keystone-screenrecord while a recording is already active will stop the current recording (toggle behavior).

Audio configuration

Audio capture is opt-in. Without any flags, recordings contain video only.

| Flag | Captures | Use case | | :------------------------ | :---------------------------------- | :--------------------------------- | | (none) | Video only | Bug reproduction, silent demos | | --with-desktop-audio | All system audio output | App demos with sound, gameplay | | --with-microphone-audio | Microphone input | Tutorial voiceovers, presentations | | Both flags combined | Desktop and microphone audio, mixed | Full presentations with narration |

Desktop audio uses the PipeWire default_output device, and microphone audio uses the PipeWire default_input device. When both sources are active, they are mixed into a single synchronized AAC audio track at 128 kbps.

Output files

Recordings are saved as MP4 files with GPU-accelerated H.264 encoding at 60 FPS and native monitor resolution. The output location is determined in the following order:

  1. $KEYSTONE_SCREENRECORD_DIR (if set).
  2. $XDG_VIDEOS_DIR (typically ~/Videos).
  3. ~/Videos as a fallback.

Files are named screenrecording-YYYY-MM-DD_HH-MM-SS.mp4 and sort chronologically in file browsers.

To save recordings to a project-specific directory:

export KEYSTONE_SCREENRECORD_DIR=~/Projects/my-project/recordings
mkdir -p "$KEYSTONE_SCREENRECORD_DIR"
keystone-screenrecord

Technical details

| Property | Value | | :------------- | :---------------------------------- | | Container | MP4 | | Video codec | H.264 (hardware-accelerated) | | Frame rate | 60 FPS | | Resolution | Native monitor resolution | | Audio codec | AAC, 128 kbps | | CPU overhead | Less than 5% (encoding runs on GPU) | | Capture method | Wayland portal protocol |

The recording engine (gpu-screen-recorder) supports NVIDIA NVENC, Intel Quick Sync, and AMD VCE hardware encoders.

Night light

Blue light filtering is provided by Hyprsunset. The filter can be toggled via Mod+Ctrl+N or through the "Toggle" category in the Keystone menu. The menu also allows configuration of the schedule (start and end times) and intensity (color temperature).

Monitor management

The desktop module includes monitor management capabilities for dynamic display configuration. The menu system provides a "Monitors" section under "Setup" that lists connected displays and offers options for mirroring, resolution presets, and multi-monitor arrangement. An autoMirror configuration option, when enabled, automatically mirrors the primary display to any newly connected external monitor.

Screen locking

Screen locking is handled by Hyprlock, which integrates with the system PAM stack. The lock screen supports:

  • Fingerprint authentication.
  • Time display and themed background.
  • Visual feedback for authentication failures.
  • Automatic activation via Hypridle after a configurable idle period.

Idle inhibition can be toggled with Mod+Ctrl+I to prevent automatic locking during presentations or long-running tasks. D-Bus inhibition requests from applications (such as browsers playing media) are ignored by default to ensure the screen locks when the user is genuinely idle.

Bluetooth and networking

The desktop module enables Bluetooth support with Blueman for device management, and NetworkManager with systemd-resolved for network configuration. These services are appropriate for laptops, portable machines, and thin client setups.

The resolv.conf is configured as a direct symlink to support Tailscale MagicDNS with systemd-resolved.

Fonts and theming

The following font families are installed:

  • Noto Sans and Noto Color Emoji.
  • JetBrains Mono Nerd Font.
  • Caskaydia Mono Nerd Font.

The theming system supports runtime switching between multiple themes (such as Tokyo Night, Catppuccin, and Nord). A theme switch updates the window manager, status bar, terminal emulator, text editor, application launcher, notification daemon, wallpaper, and GTK settings consistently. The selected theme persists across reboots.

System packages

The desktop module installs the following system-level packages:

| Package | Purpose | | :------------------------ | :----------------------------------- | | gpu-screen-recorder | Screen recording engine | | mpv | Video player | | nautilus, file-roller | File management and archive handling | | pavucontrol | Audio volume control | | networkmanagerapplet | Network configuration tray applet | | blueberry | Bluetooth device manager | | hyprsunset | Blue light filter | | hyprlock | Screen locker | | hypridle | Idle management daemon | | hyprpaper | Wallpaper manager | | hyprpolkitagent | Polkit authentication agent |

NixOS module options

The NixOS-level desktop module (keystone.desktop) exposes the following options:

| Option | Type | Default | Description | | :------------------ | :------ | :------- | :------------------------------------------ | | enable | boolean | false | Enable the desktop environment | | user | string | required | User for auto-login to the Hyprland session | | hyprland.enable | boolean | true | Enable Hyprland compositor | | greetd.enable | boolean | true | Enable greetd login manager | | audio.enable | boolean | true | Enable PipeWire audio stack | | bluetooth.enable | boolean | true | Enable Bluetooth support | | networking.enable | boolean | true | Enable NetworkManager and systemd-resolved |

Per-user Hyprland options are configured through keystone.os.users.<name>.desktop:

| Option | Type | Default | Description | | :--------------------------- | :------------------- | :-------- | :------------------------------- | | enable | boolean | false | Enable the desktop for this user | | hyprland.modifierKey | "SUPER" or "ALT" | "SUPER" | Primary modifier key | | hyprland.capslockAsControl | boolean | true | Remap Caps Lock to Control |

See also