wallp
A single-script wallpaper manager for a two-screen Wayland (sway / Hyprland) setup. Sets and restores wallpapers per screen, drives a pywal color theme, 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 (and last theme) at login, falling back to configured defaults on first run.
- Theme persistence — the last theme sticks until you change it;
--restorebrings it back, not the config default. - 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 |
wal (pywal) |
yes | generates/applies the color theme |
qarma |
only for GUI --set |
screen-choice menu + file picker |
notify-send |
optional | desktop notification on theme change |
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.
Install
wallp is a standalone script — put it somewhere on your PATH:
cp wallp ~/bin/wallp
chmod +x ~/bin/wallp
Note: this is a plain copy. If you later edit the script in the repo, re-copy it to
~/binfor the change to take effect.
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
# Optional. Defaults to sexy-splurge if omitted.
THEME=sexy-splurge
# 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 required. A missing or empty one is a hard error (named in the message).THEMEis optional.
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)
wallp --theme <name> Override the theme (combine with --set or --restore)
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
# Set a wallpaper and switch theme in one go; the theme persists afterwards.
wallp --set H=~/pics/wide.jpg --theme gruvbox
Theme precedence
When resolving which theme to apply, wallp uses, in order:
--theme <name>on the command line,- the last persisted theme (
~/.config/wallp/theme), THEMEfrom the config,- the built-in default
sexy-splurge.
The resolved theme is always saved, so it carries across --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 |
~/.config/wallp/theme |
persisted theme name |
~/.cache/wallp/H.pid |
PID of the horizontal swaybg |
~/.cache/wallp/V.pid |
PID of the vertical swaybg |
~/.cache/wal/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 wpaper symlink and apply the theme via
wal --backend colorz -nq --theme <name> -o ~/bin/wal.sh.
Restoring: for each screen, use the saved path if present, otherwise the configured default; apply it; then re-apply the resolved (persisted) theme.
The ~/.cache/wal/wpaper symlink is kept because other tools (e.g. rofi themes)
read it.
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, wal, 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.
