aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CLAUDE.md82
-rw-r--r--README.md195
2 files changed, 277 insertions, 0 deletions
diff --git a/CLAUDE.md b/CLAUDE.md
new file mode 100644
index 0000000..2aa4393
--- /dev/null
+++ b/CLAUDE.md
@@ -0,0 +1,82 @@
+# CLAUDE.md
+
+Guidance for AI agents working in this repo.
+
+## What this is
+
+`wallp` — a single bash script that sets and restores wallpapers on a fixed
+two-screen wayland (sway/hyprland) setup. It merges two older scripts
+(`multiwal.sh` interactive setter, `qar-lastwall.sh` restorer). Uses `swaybg` to
+paint wallpapers, `qarma` for GUI selection, `wal` (pywal) for the color theme.
+
+Logical screens are `H` (horizontal) and `V` (vertical), mapped to physical
+outputs via config (`OUTPUT_H`/`OUTPUT_V`).
+
+## Layout
+
+- `wallp` — the whole program (one bash file, ~320 lines).
+- `tests/wallp.bats` — bats test suite (the only tests).
+- `wallp.conf.example` — sample config.
+- `docs/superpowers/specs/` — design spec.
+- `docs/superpowers/plans/` — implementation plan.
+
+## Build / test
+
+No build step. Run the suite:
+
+```bash
+bats tests/wallp.bats
+```
+
+Requires `bats` (1.5.0 known good). Tests run hermetically: `setup()` creates a
+temp `$HOME`, stubs `swaybg`/`wal`/`qarma`/`notify-send`/`pkill`/`kill` on `PATH`
+(each logs its call to `$HOME/calls.log` and exits 0), then `source`s `wallp`.
+The sourcing guard at EOF (`[ "${BASH_SOURCE[0]}" = "$0" ]`) keeps `main` from
+running on source — **do not remove it.**
+
+Syntax check: `bash -n wallp`.
+
+## Development rules
+
+- **TDD.** Every change: write the failing bats test first, confirm it fails,
+ implement, confirm green, commit. Functions go ABOVE `main()`.
+- **Test conventions:** use `run fn` when asserting on `$status`/`$output`; call
+ the function directly when asserting on globals (`CONF_*`, `SET_*`) or
+ filesystem side effects, since `run` executes in a subshell.
+- **Pure logic is unit-testable** (conf parse, arg parse, tilde expansion, output
+ mapping, theme resolution). Side-effecting bits (`swaybg`, `wal`, `qarma`) are
+ isolated in thin functions and exercised via the PATH stubs.
+- `set -u` is on. Empty-array expansion `"${set_args[@]}"` is safe on bash ≥ 4.4
+ (this host is fine). Guard env vars with `${VAR:-}`.
+- Quote all paths (wallpaper filenames may contain spaces).
+
+## Critical gotchas
+
+- **Install is a COPY, not a symlink.** The live binary is `~/bin/wallp`, copied
+ from this repo. After editing repo `wallp`, re-copy:
+ `cp /home/danix/Programming/GIT/wallp/wallp ~/bin/wallp`
+ Otherwise hypr autostart/keybind run the stale version.
+- **qarma `--list` needs `--radiolist --print-column=2`.** A plain `--list`
+ prints nothing on selection (bug that shipped once). `qarma_select` depends on
+ these flags; a regression test guards it.
+- **Selective kill.** `apply_output` kills only the changed output's swaybg PID
+ (tracked in `~/.cache/wallp/{H,V}.pid`). Updating one screen must never blank
+ the other — there's a test for this; keep it green.
+- **`load_conf` return codes:** 0 ok, 1 invalid (missing required key), 10
+ bootstrapped (template just written → caller exits 0, no wallpaper change).
+- **Persistence is wallp-owned**, under `~/.config/wallp/` (`wall_h`, `wall_v`,
+ `theme`). `~/.cache/wal/wpaper` symlink is still maintained (rofi reads it).
+ `~/bin/wal.sh` was trimmed to dunst+kitty glue only; it no longer touches
+ wallpaper pointers.
+
+## External integration (outside this repo)
+
+- `~/bin/wal.sh` — wal's `-o` hook; dunst + kitty theming only now.
+- `~/.config/hypr/sections/autostart.lua` → `wallp --restore`.
+- `~/.config/hypr/sections/keybindings.lua` → `wallp --set` (mainMod+Return).
+- Old `~/bin/multiwal.sh` + `qar-lastwall.sh` kept as fallback, unreferenced.
+
+## Commits
+
+Pre-commit gitleaks hook prints ASCII art — normal; the commit succeeds when it
+reports "no leaks found".
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..d66216f
--- /dev/null
+++ b/README.md
@@ -0,0 +1,195 @@
+# wallp
+
+A single-script wallpaper manager for a two-screen Wayland (sway / Hyprland)
+setup. Sets and restores wallpapers per screen, drives a [pywal](https://github.com/dylanaraps/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 `swaybg` process is tracked by PID and only the changed one is
+ restarted (no full-screen blank flash).
+- **GUI or CLI** — pick wallpapers through a [qarma](https://github.com/luebking/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; `--restore`
+ brings 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`:
+
+```bash
+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 `~/bin` for 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.
+
+```ini
+# ~/.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_V` are required. A missing or
+ empty one is a hard error (named in the message). `THEME` is 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
+
+```bash
+# 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:
+
+1. `--theme <name>` on the command line,
+2. the last persisted theme (`~/.config/wallp/theme`),
+3. `THEME` from the config,
+4. 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:
+
+```ini
+# 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](https://github.com/bats-core/bats-core):
+
+```bash
+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.