Skip to content

rafaself/Screenux

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

64 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

Screenux Screenshot

Simple, private screenshot tool for Linux desktops.

Screenux focuses on a clean capture flow: take a screenshot, optionally annotate it, and save locally with safe defaults.

โœจ Why Screenux

  • ๐Ÿงญ Clean interface with one primary action and clear status messages
  • ๐Ÿ”’ Local-first behavior (no cloud upload flow)
  • ๐Ÿ–ผ๏ธ Wayland-friendly capture via desktop portal APIs
  • ๐Ÿ“ Practical folder defaults (Pictures/Screenshots, then Home fallback)

๐Ÿงฉ Features

  • Capture with Take Screenshot
  • Default global hotkey: Ctrl+Print
  • Status updates: Ready, Capturing..., Saved: <path>, Cancelled, Failed: <reason>
  • Built-in editor for quick annotations (shapes/text)
  • Screenshot preview/editor opens in a separate window from the main app controls
  • Editor toolbar tool icons use bundled light/dark PNG assets with theme-aware selection (fallback when SVG loaders are unavailable in some .deb runtimes)
  • Editor color picker supports older GTK4 runtimes used by some distro .deb installs
  • Editor zoom controls with Best fit and quick presets (33% to 2000%)
  • Timestamped output names with safe, non-overwriting writes
  • Packaged app icon for desktop launcher integration
  • Wider default window for comfortable hotkey editing, with centered initial presentation (best-effort by desktop/session)

Install

Recommended: .deb package via Docker

This is the clearest end-user path if you want a system install (/usr/bin, app launcher, icon).

Requirements:

  • Docker
  • sudo access
  • dpkg (already present on Debian/Ubuntu)
  1. Build the package:
mkdir -p dist-deb && docker build -f Dockerfile.deb -t app-deb . && docker run --rm -v "$PWD/dist-deb:/out" app-deb
  1. Install the generated .deb:
sudo dpkg -i dist-deb/screenux-screenshot_*_amd64.deb
  1. If dpkg reports missing dependencies, fix and retry:
sudo apt-get install -f -y
sudo dpkg -i dist-deb/screenux-screenshot_*_amd64.deb
  1. Validate the install:
screenux-screenshot --help || true
which screenux-screenshot

Expected after install:

  • CLI available at /usr/bin/screenux-screenshot
  • Desktop launcher visible in app menu
  • Icon installed at /usr/share/icons/hicolor/256x256/apps/io.github.rafa.ScreenuxScreenshot.png (PNG primary)

Remove later (optional):

sudo apt remove -y screenux-screenshot

Alternative: Flatpak installer script

./install-screenux.sh --bundle /path/to/screenux-screenshot.flatpak

The installer creates a desktop entry and installs app icons so launcher/taskbar icon lookup works reliably: PNG primary at ~/.local/share/icons/hicolor/256x256/apps/io.github.rafa.ScreenuxScreenshot.png plus complementary SVG assets in ~/.local/share/icons/hicolor/scalable/apps/ (including io.github.rafa.ScreenuxScreenshot-light.svg and io.github.rafa.ScreenuxScreenshot-dark.svg). It refreshes the local icon cache when GTK cache tools are available.

Optional GNOME Print Screen shortcut:

./install-screenux.sh --bundle /path/to/screenux-screenshot.flatpak --print-screen

This maps Print to screenux-screenshot --capture, which opens Screenux directly in the final capture/edit stage (without stopping on the main screen first).

If Screenux is already installed for your user, you can rerun:

./install-screenux.sh

Optional global CLI command (screenux):

sudo tee /usr/local/bin/screenux >/dev/null <<'EOF'
#!/usr/bin/env bash

/home/${USER}/dev/Screenux/screenux-screenshot
EOF
sudo chmod +x /usr/local/bin/screenux

Uninstall

./uninstall-screenux.sh

Preserve app data in ~/.var/app/io.github.rafa.ScreenuxScreenshot:

./uninstall-screenux.sh --preserve-user-data

๐Ÿ–ฑ๏ธ Usage

  1. Launch the app.
  2. Click Take Screenshot.
  3. Confirm or cancel in the system screenshot flow.
  4. (Optional) annotate in the separate preview/editor window.
  5. Save and check the status line for the resulting file path.

Save folder behavior:

  • Default target is Pictures/Screenshots (created automatically when possible).
  • If Pictures/Screenshots is unavailable or not writable, Screenux falls back to Home.
  • You can change the destination from the app (Save to โ†’ Changeโ€ฆ).

Global hotkey behavior:

  • Default shortcut is Ctrl+Print.
  • On GNOME/Linux, when your selected shortcut matches a native screenshot binding (including clipboard variants like Ctrl+Print), Screenux first tries to disable that native binding so your shortcut can be used directly.
  • If the shortcut is still unavailable, Screenux falls back to Ctrl+Shift+S (then Ctrl+Alt+S, then Alt+Shift+S, then Super+Shift+S).
  • On GNOME, the shortcut is persisted as a GNOME custom shortcut and works when the app is closed.
  • On non-GNOME desktops, global shortcut support is best-effort while the app is running.
  • Shortcut config is stored at ~/.config/screenux/settings.json as global_hotkey (null disables it).
  • While the shortcut field is focused, press the key combo and Screenux builds it automatically (example: Ctrl + S).
  • You can apply with Enter or Apply.
  • You can return to default with Default, or clear/disable with Clear (on GNOME this also restores native Print screenshot bindings).
  • Set SCREENUX_LOG_LEVEL=INFO to emit hotkey telemetry to stderr (registration resolution and --capture detection/handling) when debugging shortcut issues.

๐Ÿ–ผ๏ธ UI example

image

๐Ÿ› ๏ธ Development

Project layout

  • src/screenux_screenshot.py: app entrypoint, config/path helpers, offline enforcement
  • src/screenux_window.py: GTK window, portal flow, save-folder picker
  • src/screenux_editor.py: annotation editor and secure file writing
  • src/screenux_hotkey.py: hotkey normalization, fallback logic, and GNOME shortcut registration
  • tests/: automated tests for path, window, screenshot, and editor logic
  • screenux-screenshot: launcher script for host and Flatpak runtime

Install dev dependencies

python3 -m pip install -r requirements-dev.txt

Local dev run

./screenux-screenshot

โœ… Testing

Run fast checks locally:

python3 -m py_compile src/screenux_screenshot.py
pytest -q

Manual sanity checklist:

  1. App starts with Ready.
  2. Capture shows Capturing... and returns to interactive state.
  3. Save shows Saved: <path> and writes a file.
  4. Cancel shows Cancelled.
  5. Invalid/failed portal path shows Failed: ... with a clear reason.

โš™๏ธ CI/CD

Main workflow: .github/workflows/ci.yml

Runs automatically on:

  • Pull requests targeting main
  • Pushes to main
  • Published releases

Quality gates include:

  • Compile validation (python -m compileall -q src)
  • Automated tests (pytest -q)
  • Security checks (bandit, pip-audit)
  • Shell script hardening (ShellCheck, shfmt, policy checks, installer SHA256 artifact)
  • Dependency checks (pip check, dependency review action with warning fallback when GitHub Dependency graph is disabled)
  • Build/package validation (launcher, Flatpak manifest, desktop entry, Docker Compose, Docker build)
  • Debian package assurance (Docker .deb build, control/path integrity checks, no setuid/setgid/world-writable payload files, SHA256 report, startup/size budget checks)

Release artifacts workflow: .github/workflows/release-artifacts.yml

  • Builds screenux-screenshot.flatpak
  • Generates screenux-screenshot.flatpak.sha256
  • Verifies installability in CI before publishing
  • Uploads artifacts to workflow results and GitHub Release assets
  • Uses least-privilege job permissions

๐Ÿ“ฆ Packaging

Docker (dev/build environment)

Use Docker for reproducible tests and checks (GUI screenshot capture is not intended for Docker):

# optional one-time setup
cp .env.example .env

export LOCAL_UID=$(id -u) LOCAL_GID=$(id -g)
docker compose build dev
docker compose run --rm dev python3 -m py_compile src/screenux_screenshot.py
docker compose run --rm dev pytest -q
docker compose run --rm dev bandit -q -r src -x tests

Notes:

  • dev runs as host UID/GID (LOCAL_UID/LOCAL_GID, default 1000:1000) to avoid root-owned files.
  • You can store LOCAL_UID and LOCAL_GID in .env to avoid exporting every session.
  • .env must be at repository root (same directory as docker-compose.yml) for Compose auto-loading.
  • .env config is for Docker Compose only; Screenux runtime does not read it.
  • Python bytecode and pytest cache are disabled in container runs to reduce bind-mount noise/permission issues.

Debian package via Docker

Build a .deb into ./dist-deb/:

mkdir -p dist-deb && docker build -f Dockerfile.deb -t app-deb . && docker run --rm -v "$PWD/dist-deb:/out" app-deb

Expected artifact:

  • dist-deb/screenux-screenshot_<version>_amd64.deb

Notes:

  • The .deb build uses project-local PyInstaller hooks in packaging/pyinstaller_hooks/ to force GTK4 GI collection and avoid mixed GTK/Cairo runtime library mismatches.

Flatpak

Requirements:

  • flatpak
  • flatpak-builder

Install tools (examples):

# Debian/Ubuntu
sudo apt-get install -y flatpak flatpak-builder

# Fedora
sudo dnf install -y flatpak flatpak-builder

# Arch
sudo pacman -S --needed flatpak flatpak-builder

Build a local bundle and install with Print Screen mapping:

make build-flatpak-bundle FLATPAK_BUNDLE=./screenux-screenshot.flatpak
make install-print-screen BUNDLE=./screenux-screenshot.flatpak

make build-flatpak-bundle now auto-checks Flatpak build deps and, when missing, installs org.gnome.Platform//47 and org.gnome.Sdk//47 from Flathub in user scope.

flatpak-builder --force-clean build-dir flatpak/io.github.rafa.ScreenuxScreenshot.json
flatpak-builder --run build-dir flatpak/io.github.rafa.ScreenuxScreenshot.json screenux-screenshot

Flatpak permissions stay intentionally narrow (portal access + Desktop filesystem).

๐Ÿ” Privacy & security

  • Offline-only runtime behavior blocks networking and DNS calls.
  • Screenshot sources are validated as local, readable file:// URIs.
  • Config parsing is defensive (invalid/non-object/oversized files are ignored).
  • Save operations use exclusive file creation to avoid accidental overwrite.

๐Ÿค Contributing

See CONTRIBUTING.md for development workflow and PR guidance.

๐Ÿ“„ License

This project is licensed under the MIT License. See LICENSE.

About

Screenshot Tool for Linux

Topics

Resources

License

Contributing

Stars

Watchers

Forks

Packages

 
 
 

Contributors