Both plans were generated during their respective implementation runs but never committed. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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
flameshottopackages.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.shparses 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+Printstill 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+Printopens Flameshot. Region selector + on-canvas toolbar with drawing tools and Save/Copy/Discard buttons. flameshot guiproduces a usable capture. Pick a region, click Copy → confirm clipboard has the image (wl-paste --list-types | grep image/pngshould showimage/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.shand confirm flameshot.ini is preserved (the[ ! -f ]guard) and no~/.local/bin/screenshotsymlink 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).