randpaper - A high-performance wallpaper & theme daemon for Wayland
randpaper is a lightweight Rust utility designed for efficiency. It manages
per-monitor wallpaper rotation and optional system-wide theme
synchronization—replacing complex script chains with a single, optimized binary.
🚀 Features
-
⚡ Performance: Written in Rust using
tokio. Scans your image directory once into memory (caching paths) to prevent disk I/O spikes, even with massive wallpaper collections. -
🎨 Dynamic Theming: Automatically extracts dominant colors from the current wallpaper and generates config files for Ghostty, Kitty, and Foot, keeping your terminal in sync with your desktop.
- Waybar Theming: Generates CSS variables based on the image palette. and reloads Waybar when it changes wallpapers applying the theming automatically.
-
🖥️ Multi-Monitor: Assigns a unique random image to every active output simultaneously.
-
🔄 Dual Operating Modes: Run as a background daemon with automatic cycling, or use one-shot mode for manual wallpaper changes.
-
🛠️ Modular Backends: Works seamlessly with Sway and Hyprland (via Sway IPC or
hyprctl) and supports bothswaybgandswwwrenderers. -
Support for both
swwwand its replacementawww.
🛠 Installation
Prerequisites
You need swaybg or (swww / awww) installed as the renderer.
# From source
# crates.io
Add as a flake input:
inputs = {
randpaper.url = "github:saylesss88/randpaper";
};
Install in environment.systemPackages or home.packages:
environment.systemPackages = {
inputs.randpaper.packages.${pkgs.stdenv.hostPlatform.system}.default
};
- Pass
inputsthroughspecialArgsin yourflake.nix
And add an exec for either hyprland or sway, only for randpaper:
Hyprland Example:
wayland.windowManager.hyprland = {
settings = {
exec-once = [
# Standard Usage
"randpaper --time 15m /home/your-user/Pictures/wallpapers --backend hyprland --renderer swww"
# UWSM Usage w/ swaybg
"uwsm app -- randpaper --time 15m /home/your-user/Pictures/wallpapers --backend hyprland --renderer swaybg"
];
};
}
Sway Example:
wayland.windowManager.sway = {
extraConfig = ''
# Default backend is Sway
exec randpaper --time 30m /home/your-user/wallpapers
'';
};
Note:
randpapermanages the renderer process for you. You do not need separateexec-once = swaybg ...orexec-once = swww ...lines in your config.
🧾 Usage
Daemon Mode (Background Process)
With swww or awww installed you can test which mode you want from the
command line before adding an exec-once for randpaper to your configuration:
When you provide the --time flag, randpaper runs as a daemon and
automatically cycles wallpapers at the specified interval:
# Change every 5 minutes using Hyprland + swww transitions
# Change every hour with custom transitions
- These commands work without
swww-daemonrunning becauserandpaperautomatically launches aswww-daemonprocess if one isn't already running.
One-Shot Mode (Pick Once & Exit)
Without the --time flag, randpaper picks a random wallpaper, updates themes,
and exits immediately.
It's recommended to run one-shot via a compositor keybind so it inherits the
correct session/IPC environment.(i.e., running
randpaper ~/Pictures/wallpapersfrom the command line doesn't work as expected)
# Sway: cycle wallpaper + themes now (one-shot)
bindsym $mod+Shift+n exec randpaper ~/Pictures/wallpapers
# Hyprland: cycle wallpaper + themes (one-shot)
"$mod SHIFT,N,exec, randpaper --backend hyprland /home/jr/Pictures/wallpapers2"
swaybgcan't be one-shot from the command line because it's not a set-and-exit command; it's a long-running wallpaper service.
Use cases for one-shot mode:
-
Manual wallpaper changes via keybinds
-
Scripted theme updates
-
Testing without running a daemon
swww/awww Transitions:
# Use fade transitions
# Use wipe transitions for hyprland
-
Again, the above commands only work if there isn't already a
swww-daemoninstance running. Adding anexec randpaperto your config automatically adds anexec swww-daemon
Advanced Options
| Flag | Description | Default |
|---|---|---|
[DIR] |
Directory containing images | . |
-t, --time |
Time between changes(e.g., 15m, 1h) | 30m |
-b, --backend |
Detection backend: sway or hyprland |
sway |
-o, --outputs |
Specific outputs to target (Sway only) | Auto-discover |
-r, --renderer |
Renderer tool: swaybg or swww |
swaybg |
--transition-type |
swww transition: fade, wipe, outer |
simple |
-s, --transition-step |
swww transition step (0-100) | 90 |
-f, --transition-fps |
swww target frame rate for transitions | 30 |
--transition-type: Choose between (simple,fade,wipe,outer,inner,random)
NOTE: All transition options are ignored when using
--renderer swaybg.
🎨 Automatic Terminal Theming
randpaper automatically extracts a 16-color palette from your wallpaper and
generates theme files in ~/.config/randpaper/themes/.
To use them, add the include line to your terminal config:
Ghostty
File: ~/.config/ghostty/config
config-file = ~/.config/randpaper/themes/ghostty.config
Foot
File: ~/.config/foot/foot.ini (Place near end of file)
[main]
include=~/.config/randpaper/themes/foot.ini
Kitty
File: ~/.config/kitty/kitty.conf
include ~/.config/randpaper/themes/kitty.conf
Live-Reload of Terminal Themes
-
Ghostty: live reload works with either "cycle" keybind (i.e., theme updates immediately with either
pkill -USR1 randpaperfrom either a keybind or the command line or a keybind set toexec randpaper ~/Pictures/wallpapers)(Tested on Fedora with Sway, expect different behavior on NixOS) -
Foot / Kitty: the theme file is updated, but existing windows may not live-reload reliably; close and reopen the terminal to pick up the new theme. (Work in Progress)
# home.nix or ghostty.nix
programs.ghostty = {
enable = true;
settings = {
# The '?' makes the include optional/non-blocking
"config-file" = "?~/.config/randpaper/themes/ghostty.config";
};
};
-
On boot up, the generated theme will be applied.
-
Run the cycle command then type
pkill -USR2 ghosttyto apply the theme instantly.
Waybar Dynamic Theming (Optional)
To use randpaper with a waybar setup, ensure you call the daemon via
exec waybar in your Sway or Hyprland config.
(Sway Example ~/.config/sway/config):
exec randpaper --time 10m ~/Pictures/wallpapers
bar {
swaybar_command waybar
}
# ---snip---
randpaper automatically generates a Waybar CSS color file from the current
wallpaper palette and writes it to:
~/.config/randpaper/themes/waybar.css
This file only defines color variables (it doesn't change your bar by itself).
To use it, you import it from your Waybar style.css and then reference the
variables in your existing rules.
Example of the generated waybar.css file:
/* auto-generated by randpaper */
@@@@@@@
- Import the generated file
At the very top of your Waybar style.css (Change YOUR_USER to your
username):
- Use the variables in your CSS
Replace hard-coded colors with variables like @rp_bg, @rp_fg, @rp_accent,
etc.
Example:
}
}
randpaperautomatically reloads Waybar when it changes wallpapers, keeping your bar perfectly themed without manual intervention. (SIGUSR2zero-flicker reload)
Obviously, the more hard-coded colors you replace with the dynamically generated CSS variables the more noticeable it will be.
NOTE: Just adding the
@importat the top makes the variables available, you need to reference them for the changes to be applied.
-
On NixOS, after cycling with one-shot run
pkill -USR2 waybarto apply the new theme.
⏭️ Cycling Wallpapers & Themes
Manual Wallpaper Change (Recommended)
The simplest way to instantly change wallpapers is to run one-shot mode while the randpaper daemon is running:
Hyprland Config:
bind = $mainMod SHIFT, N, exec, randpaper ~/Pictures/wallpapers --backend hyprland
Sway Config:
bindsym $mod+Shift+n exec randpaper ~/Pictures/wallpapers
This picks a new wallpaper, updates all themes (terminal + Waybar), and exits. Your background daemon continues running for automatic cycles.
Signal Running Daemon (Alternative for Standare Filesystem Hierarchy layouts)
You can also force the daemon to cycle immediately without spawning a separate process:
Sway Config:
bindsym $mod+n exec pkill -USR1 randpaper
Hyprland Config:
bind = $mainMod SHIFT, N, exec, pkill -USR1 randpaper
Shell:
Now when you run the above keybind, you will get a new wallpaper, terminal theme, and waybar theme.
NOTE: Expect different behavior on NixOS.
⚙️ How it Works
- Startup: Caches all valid image paths (
jpg,png,bmp,webp) from the target directory into memory.
2 Loop(daemon mode): Every interval (e.g., 30m):
-
Queries active monitors via IPC.
-
Picks a random image for the primary monitor and extracts its color palette.
-
Generates theme files and triggers terminal reloads.
-
Spawns a non-blocking background process (
swaybgdaemon orswwwclient) to update the display. -
Sleeps efficiently until the next cycle.
- One-Shot (no
--time): Picks wallpaper, updates themes, exits immediately.
- Works reliably as a keybind, may have to close out terminal and relaunch for the new theme to be applied.