Files
dotfiles/docs/superpowers/plans/2026-05-02-flameshot-screenshot.md
T
funman300 7a5a276efd docs: track implementation plans for fan-profile auto and flameshot
Both plans were generated during their respective implementation
runs but never committed.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-05 23:18:31 -07:00

12 KiB

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

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
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
grep -c "^flameshot$" packages.txt

Expected: 1 (exactly one occurrence).

  • Step 5: Commit
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:

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:

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 -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:

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
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)
# 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):

sed -i '/^savePath=/d' ~/.config/flameshot/flameshot.ini
  • Step 6: Commit
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:

    Mod+Print { spawn "screenshot"; }

Replace with:

    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
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
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):

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 -n install.sh

Expected: no output, exit 0.

  • Step 3: Delete the live symlink
rm ~/.local/bin/screenshot

Expected: silent success. Verify it's gone:

ls -la ~/.local/bin/screenshot 2>&1

Expected: cannot access ... No such file or directory.

  • Step 4: Delete the script file from the repo
git rm scripts/screenshot.sh

Expected: rm 'scripts/screenshot.sh'.

  • Step 5: Verify nothing else in the repo references the deleted script
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
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).