A minimalist, Rofi/yazi-style wallpaper selector for Wayland.
Borderless, dark, keyboard-first β the wallpapers are the content, the UI disappears.
Pick a still image or a looping video, hit Enter, done.
- Keyboard-first β arrow keys /
hjkl/wasdto move,/to filter,Enterto apply. No mouse needed, but it works too (click to select, double-click to apply). - Images and video wallpapers β via
swww, looping video viampvpaper. - Smooth transitions β animated switches for both images and video
- Live previews β selecting a video plays a short looping clip right on its thumbnail.
- Audition mode β
Spaceapplies a wallpaper but keeps the picker open, so you can flip through options on your real desktop. - Lightweight & on-demand β launches when you call it, exits cleanly, and never idles in the background. Rendering is handed to detached daemons.
- Restore on login β remembers your last wallpaper so a video survives a reboot.
- Color-scheme integration β tells noctalia / matugen / wallust / pywal to re-theme your system from the new wallpaper.
- Riced to taste β backdrop opacity, made for a
layerrule = blurcompositor.
Wallfliper draws its picker as a wlr-layer-shell overlay and delegates painting to swww/mpvpaper, so it targets compositors that implement wlr-layer-shell:
Hyprland Β· Sway Β· river Β· Wayfire Β· niri
Out of scope (no layer-shell, or only partial): KDE Plasma, GNOME, X11, Windows.
Honestly? I just wanted to give Claude Code a try, and ended up enjoying it a little too much.
Wallfliper was built mostly "low-code" β most of the codebase was written with the help of AI tooling like Claude Code and Google Stitch, with me steering the design, scope and decisions.
Install from source β works on any supported compositor:
Important
Install PySide6 from your distribution, not pip. layer-shell-qt is a compiled
Qt plugin loaded into the running process β its Qt version must match the Qt that
PySide6 uses. Distro packages are all built against the same system Qt, so they always
match. A pip install PySide6 bundles its own Qt and can mismatch the system
layer-shell plugin, causing cryptic load failures.
1. Install the dependencies
| Dependency | Purpose | Required? |
|---|---|---|
pyside6 |
the Qt6 / QML runtime | β required |
layer-shell-qt |
the overlay (org.kde.layershell QML module) |
β required |
swww or awww |
image wallpapers (auto-detected) | image support |
mpvpaper |
video wallpapers | video support |
ffmpeg |
video thumbnails, previews & color extraction | video extras |
On Arch / CachyOS β copy-paste:
sudo pacman -S pyside6 layer-shell-qt swww ffmpeg
paru -S mpvpaperOn other distros β install them with your package manager (names vary, e.g.
python3-pyside6). swww and mpvpaper are usually not packaged outside Arch β
build them from source (both have simple instructions):
- swww β https://github.com/LGFae/swww (Rust)
- mpvpaper β https://github.com/GhostNaN/mpvpaper
2. Run it
git clone https://github.com/Roberth-Souza/wallfliper
cd wallfliper
python main.py --check # β/β report of every dependency
python main.py # launchπ‘
python main.py --checkprints a per-dependency report with an install hint for whatever's missing β run it first if anything misbehaves.
Bind Wallfliper to a compositor hotkey. Pressing the hotkey again while it's open closes it β it's a toggle.
-- Hyprland (Lua config) β ~/.config/hypr/modules/keybinds.lua
hl.bind("SUPER + W", hl.dsp.exec_cmd("python /path/to/wallfliper/main.py"))# Sway β ~/.config/sway/config
bindsym $mod+w exec python /path/to/wallfliper/main.py# niri β ~/.config/niri/config.kdl
binds { Mod+W { spawn "python" "/path/to/wallfliper/main.py"; } }| Key | Action |
|---|---|
β β β β Β· h j k l Β· w a s d |
Move selection |
/ |
Start searching β then type to filter |
Backspace |
Edit the filter (empty filter β leave search) |
i Β· v |
Toggle the image / video filter (also clickable buttons) |
Enter |
Apply selected wallpaper and close |
Space |
Apply but keep open (audition on your desktop) |
Esc |
Close (or close the settings panel) |
| Double-click | Apply and close |
| Click outside the panel | Close |
| β (gear) | Open settings |
Applying an image stops any running video wallpaper β there's only ever one wallpaper at a time.
Click the gear (or it's keyboard-driven: j/k move Β· β/β change Β· Enter select Β· Esc close):
- background β backdrop darkness / opacity
- folder β choose your wallpaper directory (via your
xdg-desktop-portalfile chooser)
Hyprland blurs windows by default, but not layer-shell surfaces β so Wallfliper
starts out unblurred. To get the frosted-glass panel, add a layer rule for its
wallfliper namespace:
hl.layer_rule({ name = "wallfliper", match = { namespace = "wallfliper" }, blur = true, ignore_alpha = 0.5 })Lower the background opacity in Settings to actually see the blur through it.
Verify the namespace any time with hyprctl layers while Wallfliper is open.
Other wlr-layer-shell compositors expose their own blur mechanism (or none) β consult
their docs; Wallfliper just provides the transparent surface for them to blur.
Wallfliper saves the last-applied wallpaper to ~/.config/wallfliper/state.json.
wallfliper --restore reads that and re-spawns swww/mpvpaper β so a video
wallpaper survives a reboot. (Wallfliper itself doesn't stay running; it just hands
the file back to the renderer and exits β mpvpaper is stateless and dies on reboot,
so something has to re-launch it, and that's all --restore does.)
python /path/to/wallfliper/main.py --restore # re-apply the saved wallpaper nowRun it on login from your compositor's autostart, wrapped in a short sleep so the
compositor finishes bringing up your desktop first. Without the delay a video wallpaper
can come up frozen on a low-res frame: mid-boot the wallpaper surface is briefly reported
as "hidden", which trips mpvpaper's auto-pause (a known mpvpaper quirk). A few seconds'
delay sidesteps it:
-- Hyprland (Lua config) β inside hl.on("hyprland.start", ...) in your autostart.lua
hl.exec_cmd("sh -c 'sleep 5 && python /path/to/wallfliper/main.py --restore'")# Sway β ~/.config/sway/config
exec sh -c 'sleep 5 && python /path/to/wallfliper/main.py --restore'# niri β ~/.config/niri/config.kdl
spawn-at-startup "sh" "-c" "sleep 5 && python /path/to/wallfliper/main.py --restore"# Wayfire β ~/.config/wayfire.ini
[autostart]
wallfliper = sh -c 'sleep 5 && python /path/to/wallfliper/main.py --restore'Uses system
python(the same interpreter that runs the app) β no virtualenv, no activation. Once you install via a package (e.g. AUR), a realwallflipercommand lands on PATH and every line above shortens to justwallfliper --restore.
Alternative: XDG autostart entry
wallfliper --install-autostart writes ~/.config/autostart/wallfliper-restore.desktop
(the freedesktop standard). It works on sessions that honor XDG autostart β GNOME/KDE,
or wlroots compositors launched via UWSM/systemd. A bare Hyprland/Sway/niri session
won't read that folder, so on a plain setup use the compositor exec line above instead.
No background daemon of our own β rendering is handled by swww-daemon / mpvpaper.
After applying a wallpaper, Wallfliper notifies external color tools so your system
color scheme regenerates from it (best-effort, never blocks). It auto-detects
noctalia-shell if running; for everything else set
color_hook in ~/.config/wallfliper/config.json ({path} is substituted):
{
"color_hook": "matugen image {path}"
}Works with matugen / wallust / pywal / any command. For video wallpapers it themes from a
still frame extracted with ffmpeg.
First step, always: wallfliper --check β it tells you exactly what's missing.
| Symptom | Cause & fix |
|---|---|
ImportError / won't start |
PySide6 missing β install your distro's pyside6. |
| "failed to load QML UI" | layer-shell-qt missing β install it (provides org.kde.layershell). |
| Overlay never appears | Not on a wlr-layer-shell Wayland session β check your compositor. |
| β "no wallpaper tool found" on apply | Install swww (or awww) for images. |
| β "mpvpaper is not installed" on apply | Install mpvpaper for video wallpapers. |
Video cards show βΆ instead of a frame |
Install ffmpeg (thumbnails/previews are optional). |
| Settings folder picker doesn't open | Install an xdg-desktop-portal backend (e.g. xdg-desktop-portal-gtk or -termfilechooser). |
the app still runs and tells you in the status bar what to install.
GPL-3.0. PySide6 is used under the LGPL.
