A tiny Flameshot-style screenshot uploader for the COSMIC desktop (Pop!_OS) — with retro templates.
Select an area → it uploads to your Zipline server → the URL lands on your clipboard, ready to paste. Optionally render the shot inside a CRT monitor, a Commodore Amiga screen, or any scene you make.
On the COSMIC desktop (Pop!_OS 24.04+), Flameshot, grim, scrot and friends don't work — COSMIC's compositor doesn't implement the wlr-screencopy protocol they rely on, so they capture nothing. The only sanctioned way to grab the screen is COSMIC's own cosmic-screenshot.
zupload builds on that: it uses cosmic-screenshot for the capture, then does everything else itself — upload, clipboard, notification, and an extensible template engine for retro effects.
- 📸 Interactive area select via COSMIC's native screenshot UI
- ☁️ Uploads to Zipline, copies the resulting URL to your clipboard
- 🔔 Desktop notification on success (no extra packages needed — uses
gdbusifnotify-sendis absent) - 🖥️ Template system — drop your screenshot inside a monitor/scene:
amiga— a real Commodore 1081 photo, with a heavy classic-CRT lookdelorean— an empty slot ready for your artwork
- 🎛️ Classic CRT effects: scanlines, RGB aperture grille, phosphor bloom, chromatic aberration, vignette — all tunable
- 🧩 Add your own scenes with one folder + a few numbers (see below)
- 🪶 Pure
bash+ffmpeg+pycairo. No daemon, no GUI toolkit, ~150 lines.
Required: ffmpeg (with ffprobe), curl, jq, python3 + python3-cairo, and cosmic-screenshot (COSMIC desktop).
Recommended: zenity (template menu), wl-clipboard or xclip (clipboard), libnotify-bin (notifications).
sudo apt install ffmpeg curl jq python3-cairo zenity wl-clipboard libnotify-binNot on COSMIC? Everything except the capture step is portable. Swap the
cosmic-screenshotcall inbin/zupload/bin/zupload-fxforgrim -g "$(slurp)"(wlroots) orgnome-screenshot -a -f(GNOME) and the rest works unchanged.
git clone https://github.com/<you>/zupload.git
cd zupload
./install.shThis copies the scripts to ~/.local/bin, the templates to ~/.config/zupload/templates,
and creates ~/.config/zupload/config from the example.
Edit ~/.config/zupload/config and add your Zipline endpoint and token
(Zipline web UI → User Settings → Manage Tokens):
ZIPLINE_URL="https://your-zipline-host.example/api/upload"
ZIPLINE_TOKEN="your-secret-token"
ZIPLINE_FORMAT="random"The file is chmod 600 and git-ignored — your token never leaves your machine.
Settings → Keyboard → Shortcuts → Custom, add:
| Shortcut | Command | What it does |
|---|---|---|
Super + Print |
zupload |
fast upload |
Super + Shift + Print |
zupload-fx |
pick a template, then upload |
Or write them directly to ~/.config/cosmic/com.system76.CosmicSettings.Shortcuts/v1/custom:
{
(modifiers: [Super], key: "Print"): Spawn("zupload"),
(modifiers: [Super, Shift], key: "Print"): Spawn("zupload-fx"),
}zupload # capture an area, upload, URL to clipboard
zupload /path/img.png # upload an existing image instead
zupload-fx # pop a menu, pick a template, then capture + upload
zupload-fx amiga # use a template directly
zupload-fx plain # no effectA template is just a folder in ~/.config/zupload/templates/<name>/ containing a
render.sh that defines one function:
render() { # $1 = input screenshot, $2 = output image to upload
local in="$1" out="$2"
# ...produce $out from $in however you like (ffmpeg, ImageMagick, ...)
}It shows up in the menu automatically. For a "screenshot inside a scene" template
(like amiga), the recipe is:
- Put a picture of the scene as
frame.png. - Note the four corners of its "screen" (open
frame.pngin GIMP, read the pixel coordinates of each corner). - The render warps the screenshot onto that quad and clips it with a mask.
Gotcha worth knowing: ffmpeg's
perspectivefilter edge-extends outside the destination quad — it does not go transparent. So when the frame is an opaque background photo, you must clip the warped shot with an explicit polygon mask (theamigatemplate generates a rounded one with pycairo at runtime). Seetemplates/amiga/render.shfor the full, commented pipeline.
All knobs are at the top of templates/amiga/render.sh:
| Knob | Effect |
|---|---|
SCAN_DARK |
scanline strength |
GLOW |
phosphor bloom |
GRILLE |
RGB aperture-grille depth |
FRINGE |
chromatic aberration |
VIGNETTE |
edge darkening (bigger angle = darker) |
SCREEN_RADIUS |
rounded-corner radius of the screen mask |
TLx … BRy |
screen corner alignment |
zupload-fx ── pick template (zenity) ── cosmic-screenshot ── template render() ─┐
│
zupload ◄───────────────────────────────────── rendered image ─────────────────┘
└── curl → Zipline → jq .files[0].url → clipboard (wl-copy/xclip) → notify
MIT — see LICENSE. Note: templates/amiga/frame.png is a photo of a
Commodore monitor and is not covered by the MIT license; replace it with your
own image if you need a clean redistribution.
