# Flameshot Screenshot Swap Implementation Plan > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. **Goal:** Replace the bespoke `scripts/screenshot.sh` pipeline with Flameshot, bound to `Mod+Print`. **Architecture:** Pure tool swap. Install Flameshot from `extra`, generate a small `~/.config/flameshot/flameshot.ini` from `install.sh` (mirrors the existing `mako/config` generator pattern), point `Mod+Print` at `flameshot gui`, then delete the old script + symlink + install.sh entry. Tasks ordered so `Mod+Print` keeps working at every commit boundary. **Tech Stack:** flameshot (Qt6, official Arch `extra`), niri, bash for `install.sh`. **Spec:** `docs/superpowers/specs/2026-05-02-flameshot-screenshot-design.md` **Verification model:** Bash + system commands. Each task ends with shell verification commands and a one-line user check (e.g. "press `Mod+Print`, confirm Flameshot toolbar appears"). The controller has a display; subagents do not — defer visual checks to the controller. --- ## File Structure | File | Change | |---|---| | `packages.txt` | add `flameshot` | | `install.sh` | remove the `ln -sf ".../screenshot.sh" ...` line; add a flameshot.ini generator block (idempotent: only writes if file doesn't exist) | | `niri/config.kdl` | change `Mod+Print { spawn "screenshot"; }` to `Mod+Print { spawn "flameshot" "gui"; }` | | `scripts/screenshot.sh` | deleted | | `~/.local/bin/screenshot` | symlink removed (filesystem only, not git-tracked) | | `~/.config/flameshot/flameshot.ini` | created on disk by the install.sh block (filesystem only, not git-tracked) | --- ## Task 1: Install Flameshot and add to packages.txt After this task, the `flameshot` binary is on PATH and `packages.txt` declares it as a dependency. The old screenshot script and keybind are still wired up — nothing functional has changed yet. **Files:** - Modify: `packages.txt` (add one line) - [ ] **Step 1: Install flameshot via the AUR helper** ```bash yay -S --needed --noconfirm flameshot ``` Expected: package installs (or "is up to date" if already present). If `yay` is unavailable, substitute `paru` or `sudo pacman -S --needed --noconfirm flameshot`. - [ ] **Step 2: Verify the binary is on PATH** ```bash flameshot --version ``` Expected: a version string like `Flameshot v13.3.0 (compiled with Qt 6.x)`. If "command not found", the install failed — escalate. - [ ] **Step 3: Add `flameshot` to `packages.txt`** Open `packages.txt` and insert `flameshot` in alphabetical-ish order. The existing list is roughly grouped by topic, not strictly sorted. Insert after `fw-fanctrl` (line 39) so it sits with the small one-off utilities cluster: ``` fw-fanctrl satty starship flameshot ``` (Final order doesn't matter as long as `flameshot` appears once and on its own line. Don't reorder unrelated lines.) - [ ] **Step 4: Verify packages.txt is well-formed** ```bash grep -c "^flameshot$" packages.txt ``` Expected: `1` (exactly one occurrence). - [ ] **Step 5: Commit** ```bash git add packages.txt git commit -m "packages: add flameshot" ``` --- ## Task 2: Add flameshot config generator to install.sh and run it After this task, `~/.config/flameshot/flameshot.ini` exists with the spec's defaults. Re-running `install.sh` will not clobber the file (the generator has an `[ ! -f ]` guard so user-saved preferences like `savePath` are preserved on subsequent runs). The screenshot keybind still points at the old script. **Files:** - Modify: `install.sh` (insert generator block after the existing mako python block, around line 42) - [ ] **Step 1: Insert the flameshot config generator into `install.sh`** Find the existing mako block in `install.sh`. It looks like: ```bash python3 - <<'PYEOF' import json, os c = json.load(open("theme/colors.json")) config = f"""background-color={c['background']} text-color={c['foreground']} border-size=2 border-color={c['blue']} default-timeout=4000 """ open(os.path.expanduser("~/.config/mako/config"), "w").write(config) PYEOF ``` Immediately *after* the `PYEOF` line that closes the mako block, insert: ```bash mkdir -p ~/.config/flameshot if [ ! -f ~/.config/flameshot/flameshot.ini ]; then cat > ~/.config/flameshot/flameshot.ini <<'INI' [General] disabledTrayIcon=true showStartupLaunchMessage=false showHelp=false copyAndCloseAfterUpload=true uiColor=#81a2be contrastUiColor=#1d1f21 contrastOpacity=190 INI fi ``` The `[ ! -f ]` guard is required: Flameshot writes runtime state (savePath, last folder) back to this file, so re-running `install.sh` must not overwrite user preferences. - [ ] **Step 2: Sanity-check `install.sh` parses as bash** ```bash bash -n install.sh ``` Expected: no output, exit 0. (`-n` is dry-run syntax check.) - [ ] **Step 3: Run the new block manually to create the live config** You can either run install.sh in full, or extract just the new block. Cleanest is to run the block standalone: ```bash mkdir -p ~/.config/flameshot if [ ! -f ~/.config/flameshot/flameshot.ini ]; then cat > ~/.config/flameshot/flameshot.ini <<'INI' [General] disabledTrayIcon=true showStartupLaunchMessage=false showHelp=false copyAndCloseAfterUpload=true uiColor=#81a2be contrastUiColor=#1d1f21 contrastOpacity=190 INI fi ``` - [ ] **Step 4: Verify the file was written with the right contents** ```bash cat ~/.config/flameshot/flameshot.ini ``` Expected output: ``` [General] disabledTrayIcon=true showStartupLaunchMessage=false showHelp=false copyAndCloseAfterUpload=true uiColor=#81a2be contrastUiColor=#1d1f21 contrastOpacity=190 ``` - [ ] **Step 5: Verify the guard works (re-run is a no-op)** ```bash # Mutate the file slightly echo "savePath=/home/alex/Pictures" >> ~/.config/flameshot/flameshot.ini # Re-run the generator block (paste from Step 3) mkdir -p ~/.config/flameshot if [ ! -f ~/.config/flameshot/flameshot.ini ]; then cat > ~/.config/flameshot/flameshot.ini <<'INI' [General] disabledTrayIcon=true showStartupLaunchMessage=false showHelp=false copyAndCloseAfterUpload=true uiColor=#81a2be contrastUiColor=#1d1f21 contrastOpacity=190 INI fi # Confirm the savePath line is still present (file was not regenerated) grep "^savePath=" ~/.config/flameshot/flameshot.ini ``` Expected: `savePath=/home/alex/Pictures` (proves the `[ ! -f ]` guard prevented overwrite). Clean up the test mutation (so the file matches the spec's defaults again): ```bash sed -i '/^savePath=/d' ~/.config/flameshot/flameshot.ini ``` - [ ] **Step 6: Commit** ```bash git add install.sh git commit -m "install: generate flameshot.ini with idempotent guard" ``` --- ## Task 3: Repoint `Mod+Print` to Flameshot After this task, pressing `Mod+Print` opens Flameshot's GUI (region selector + on-canvas annotation toolbar). The old `scripts/screenshot.sh` is no longer reachable via keybind, but the script and its symlink still exist on disk — Task 4 deletes them. **Files:** - Modify: `niri/config.kdl` (line 87) - [ ] **Step 1: Replace the keybind** In `niri/config.kdl`, find line 87: ```kdl Mod+Print { spawn "screenshot"; } ``` Replace with: ```kdl Mod+Print { spawn "flameshot" "gui"; } ``` Note the two-string form for `spawn` — niri's `spawn` action takes the program and each argument as separate quoted strings. `spawn "flameshot gui"` (single string) would not work; niri would try to exec a binary literally named `flameshot gui`. - [ ] **Step 2: Validate the niri config** ```bash niri validate ``` Expected: exit 0 and a final line `INFO niri: config is valid`. Any "ERROR" or non-zero exit means a syntax issue — fix before continuing. - [ ] **Step 3: User-side visual verification (controller only — subagent skip)** Niri picks up `config.kdl` changes live; no reload needed. Press `Mod+Print`. Expected: Flameshot's region-selector overlay appears, with a floating toolbar showing drawing tools and Save/Copy/Discard buttons. Cancel out (Esc) without taking a real screenshot. If a portal permission prompt appears the first time, allow it — Flameshot uses `xdg-desktop-portal-wlr` to capture under Wayland. If `Mod+Print` does nothing or you see "command not found" in `journalctl --user`, the binary isn't on PATH for niri — re-run Task 1, Step 1. - [ ] **Step 4: Commit** ```bash git add niri/config.kdl git commit -m "niri: bind Mod+Print to flameshot gui" ``` --- ## Task 4: Delete the old screenshot script, symlink, and install.sh entry After this task, all traces of `scripts/screenshot.sh` are gone — script file deleted, `~/.local/bin/screenshot` symlink removed, and the corresponding line in `install.sh` removed so re-running it doesn't recreate the dead symlink. `Mod+Print` continues to work via Flameshot. **Files:** - Delete: `scripts/screenshot.sh` - Modify: `install.sh` (remove one line) - Filesystem: `~/.local/bin/screenshot` (remove symlink) - [ ] **Step 1: Remove the symlink line from `install.sh`** In `install.sh`, find this line (it's inside the `==> Installing scripts` section, around line 61): ```bash ln -sf "$(pwd)/scripts/screenshot.sh" ~/.local/bin/screenshot ``` Delete the entire line. The surrounding lines (other `ln -sf` calls for the remaining scripts) stay intact. - [ ] **Step 2: Sanity-check install.sh still parses** ```bash bash -n install.sh ``` Expected: no output, exit 0. - [ ] **Step 3: Delete the live symlink** ```bash rm ~/.local/bin/screenshot ``` Expected: silent success. Verify it's gone: ```bash ls -la ~/.local/bin/screenshot 2>&1 ``` Expected: `cannot access ... No such file or directory`. - [ ] **Step 4: Delete the script file from the repo** ```bash git rm scripts/screenshot.sh ``` Expected: `rm 'scripts/screenshot.sh'`. - [ ] **Step 5: Verify nothing else in the repo references the deleted script** ```bash grep -rn "screenshot" --include="*.kdl" --include="*.sh" --include="*.jsonc" --include="*.toml" --include="*.fish" --exclude-dir=docs /home/alex/Documents/dotfiles ``` Expected: zero hits, or only matches inside markdown/spec files (which the include-glob excludes anyway). If the keybind from Task 3 still says `spawn "screenshot"`, Task 3 didn't land — go back and check. - [ ] **Step 6: Confirm `Mod+Print` still works (controller only — subagent skip)** Press `Mod+Print`. Flameshot's GUI should still appear (this isn't a regression test — it's just a sanity check that nothing in the cleanup broke the live keybind). - [ ] **Step 7: Commit** ```bash git add install.sh scripts/screenshot.sh git commit -m "screenshot: remove old grim/slurp/wofi pipeline (replaced by flameshot)" ``` (`git rm` from Step 4 already staged the deletion; this commit picks up both the staged deletion and the install.sh edit.) --- ## Final verification - [ ] **Pressing `Mod+Print` opens Flameshot.** Region selector + on-canvas toolbar with drawing tools and Save/Copy/Discard buttons. - [ ] **`flameshot gui` produces a usable capture.** Pick a region, click Copy → confirm clipboard has the image (`wl-paste --list-types | grep image/png` should show `image/png`). Click Save → file lands wherever Flameshot prompts (first-time prompt expected; pick `~/Pictures`). - [ ] **No leftover references.** `grep -rn "screenshot\.sh\|/local/bin/screenshot" /home/alex/Documents/dotfiles --exclude-dir=.git --exclude-dir=docs` → no hits. - [ ] **install.sh is re-runnable without breakage.** Optional: rerun `bash install.sh` and confirm flameshot.ini is preserved (the `[ ! -f ]` guard) and no `~/.local/bin/screenshot` symlink reappears (because the line was removed). - [ ] **Toolbar colors match the theme.** The Flameshot floating toolbar should show the Tomorrow Night blue accent (`#81a2be`) on the dark background (`#1d1f21`).