wallp
A single-script wallpaper manager for a two-screen Wayland (sway / Hyprland) setup. Sets and restores wallpapers per screen, refreshes the desktop accent colour to match, and remembers what you had across reboots.
It replaces two older scripts — an interactive setter and a session restorer — with one flag-driven program.
Features
- Two independent screens — a horizontal (
H) and a vertical (V) output, mapped to physical connectors in config. - Partial updates — change one screen without disturbing the other. Each
screen's
swaybgprocess is tracked by PID and only the changed one is restarted (no full-screen blank flash). - GUI or CLI — pick wallpapers through a qarma dialog, or pass file paths as arguments for scripted/headless use.
- Session restore — re-applies the last wallpapers at login, falling back to configured defaults on first run.
- Unified desktop theme — after every change
wallphands the new wallpaper toudt-accent, which owns the whole palette (rofi, Hyprland, Firefox, quickshell, Sublime).wallpitself no longer runs pywal or stores a theme. - Self-bootstrapping config — first run writes a template config and tells you to fill it in, without touching your wallpapers.
Requirements
| Tool | Required | Purpose |
|---|---|---|
bash |
yes (≥ 4.4) | the script itself |
swaybg |
yes | paints the wallpaper on each output |
udt-accent |
optional | refreshes the desktop accent colour |
qarma |
only for GUI --set |
screen-choice menu + file picker |
bats |
dev only | running the test suite |
wallp checks for the required binaries at startup and exits with a clear
message if one is missing. udt-accent is looked up at run time: if it is
absent, or it fails, the wallpaper is still set and only the accent refresh is
skipped.
Install
wallp is a standalone script — put it somewhere on your PATH:
ln -s "$PWD/wallp" ~/bin/wallp
A symlink keeps the installed command in step with the checkout, so edits take
effect at once. A plain cp wallp ~/bin/wallp && chmod +x ~/bin/wallp works too,
but then every repo edit needs a re-copy.
Configuration
Config lives at ~/.config/wallp/wallp.conf. On the very first run, if it
doesn't exist, wallp writes a template there and exits without changing any
wallpaper — edit it, then run again.
# ~/.config/wallp/wallp.conf
# Physical output names. Find yours with:
# swaymsg -t get_outputs (sway)
# hyprctl monitors (Hyprland)
# wlr-randr
OUTPUT_H=DP-1
OUTPUT_V=DP-3
# Used by --restore when there is no saved wallpaper yet.
# A leading ~ is expanded to your home directory.
DEFAULT_H=~/Pictures/wallpapers/SFW/horizontal.png
DEFAULT_V=~/Pictures/wallpapers/SFW/vertical.png
Format notes:
- Plain
key=value, one per line. Blank lines and#comments are ignored. - The file is not sourced as shell — it's parsed manually, so it can't run code.
OUTPUT_H,OUTPUT_V,DEFAULT_H,DEFAULT_Vare all required. A missing or empty one is a hard error (named in the message).
Usage
wallp Show help
wallp --help | -h Show help
wallp --set Interactive selection (qarma): pick H / V / Both
wallp --set H=<file> Set the horizontal screen only
wallp --set V=<file> Set the vertical screen only
wallp --set H=<f> V=<f> Set both screens
wallp --restore Restore last session (defaults if none saved)
Examples
# Interactive: a menu asks which screen, then a file picker opens.
wallp --set
# Change only the vertical monitor; the horizontal one is untouched.
wallp --set V=~/Pictures/wallpapers/portrait.png
# Set both at once.
wallp --set H=~/pics/wide.jpg V=~/pics/tall.jpg
# Restore on login (defaults on first ever run).
wallp --restore
GUI vs CLI
qarma is used only to draw windows — the screen-choice menu, the file
picker, dialogs, and the help screen when a display is present. The actual
wallpaper is always set by swaybg, so the H=/V= argument forms work fine
without any display (e.g. from a startup script). --restore never needs a
display.
If you run wallp --set with no arguments and no Wayland display is available,
it errors and asks you to pass H=/V= instead.
How it works
State is owned entirely by wallp:
| Path | Role |
|---|---|
~/.config/wallp/wallp.conf |
configuration |
~/.config/wallp/wall_h |
persisted horizontal wallpaper path |
~/.config/wallp/wall_v |
persisted vertical wallpaper path |
~/.cache/wallp/H.pid |
PID of the horizontal swaybg |
~/.cache/wallp/V.pid |
PID of the vertical swaybg |
~/.cache/udt/wpaper |
symlink to the current horizontal image |
Setting a screen: validate the file, kill only that screen's old swaybg,
launch a new one (swaybg -o <output> -i <file> -m fill), record the new PID,
and save the path. Then update the ~/.cache/udt/wpaper symlink and run
udt-accent ~/.cache/udt/wpaper to re-derive the desktop accent colour.
Restoring: for each screen, use the saved path if present, otherwise the configured default; apply it; then refresh the accent the same way.
The wpaper symlink is the hand-off point to the rest of the theme: other
tools (rofi, udt-accent) read it rather than wallp's own state.
Integration with sway / Hyprland
Bind the interactive setter to a key and run a restore at startup. For Hyprland:
# autostart
exec-once = wallp --restore
# keybind
bind = $mainMod, Return, exec, wallp --set
(For sway, use exec / bindsym equivalents.)
Development
The whole program is the single wallp file; functions are small and isolated
so they can be unit-tested. Tests use bats:
bats tests/wallp.bats
The suite stubs swaybg, udt-accent, qarma, and notify-send on PATH and runs
against a temporary $HOME, so it touches nothing real. Contributions should
follow TDD — add a failing test first.
Design notes and the implementation plan live under docs/superpowers/.
License
Personal tooling; use as you like.
