English · Português (Brasil)
A customizable Wayland lock screen, built with Rust and GTK4. External themes, photo and video backgrounds, an embedded keyboard and native visual settings. Optional controller support includes devices such as the Steam Deck.
Version 0.3.6 is published on GitHub Releases for Arch, Fedora 43 and Ubuntu 26.04 on x86_64, and for Ubuntu 26.04 on aarch64 (arm64). Each package installs the application, a DeckLock Settings launcher, the included media pack and the PAM service DeckLock uses. The package manager resolves the runtime dependencies; no Rust toolchain is needed. These are GitHub downloads, not packages from official repositories.
Locking only works on one of the desktops that work: installing on a stock GNOME or KDE Plasma desktop will not let DeckLock lock it.
curl -fLO https://github.com/yan-vidal/DeckLock/releases/download/v0.3.6/decklock-0.3.6-1-x86_64.pkg.tar.zst
curl -fLO https://github.com/yan-vidal/DeckLock/releases/download/v0.3.6/SHA256SUMS
sha256sum --check --ignore-missing SHA256SUMS
sudo pacman -Syu
sudo pacman -U ./decklock-0.3.6-1-x86_64.pkg.tar.zstcurl -fLO https://github.com/yan-vidal/DeckLock/releases/download/v0.3.6/decklock-0.3.6-1.fc43.x86_64.rpm
curl -fLO https://github.com/yan-vidal/DeckLock/releases/download/v0.3.6/SHA256SUMS
sha256sum --check --ignore-missing SHA256SUMS
sudo dnf install ./decklock-0.3.6-1.fc43.x86_64.rpmcurl -fLO https://github.com/yan-vidal/DeckLock/releases/download/v0.3.6/decklock_0.3.6-1_amd64.deb
curl -fLO https://github.com/yan-vidal/DeckLock/releases/download/v0.3.6/SHA256SUMS
sha256sum --check --ignore-missing SHA256SUMS
sudo apt install ./decklock_0.3.6-1_amd64.debcurl -fLO https://github.com/yan-vidal/DeckLock/releases/download/v0.3.6/decklock_0.3.6-1_arm64.deb
curl -fLO https://github.com/yan-vidal/DeckLock/releases/download/v0.3.6/SHA256SUMS
sha256sum --check --ignore-missing SHA256SUMS
sudo apt install ./decklock_0.3.6-1_arm64.debEach package is built against its own distribution's libraries. Derivatives that
share those repositories, such as EndeavourOS or Fedora spins, may work but are not
tested. Ubuntu 24.04 and Debian 13 are not supported: Ubuntu 24.04 does not
package gtk4-layer-shell at all, and Debian 13 packages a version older than the
1.2 DeckLock needs.
Open DeckLock Settings from your app launcher, or run:
decklock --settingsDeckLock is not tied to Arch. It needs GTK4, GStreamer, Linux-PAM and
gtk4-layer-shell 1.2+, and one of the desktops that work.
The packages above are not universal Linux binaries: each targets its own distribution's library stack, on x86_64 only. For another distribution, see build from source.
The package installs /etc/pam.d/decklock, which pam_service now defaults to.
Installing from the archive or from source does not create it, and DeckLock refuses
to lock rather than trap you behind a screen it cannot authenticate: create the file
with auth include and account include lines for your distribution's stack (see
packaging/<distro>/pam/decklock), or point pam_service at a service you already
have.
Open Background → Library → Procedurals. Select Starfield, Particles, Lissajous curves, Matrix rain, Doom fire, Aurora, Flow field or Ridgeline and add it to the pool, just like a photo or video. A procedural replaces the background; it is not an overlay. If selected for a lock, it keeps playing throughout that session. Photo selections still cycle only among photos. Rest has its own pool; Reuse background keeps the normal media.
Use the eye to view an item in the reusable media viewer, and the gear to adjust that item's colors, speed, particle count, seed and FPS (1–30). Apply updates the draft and open previews; Save in settings writes the configuration. Closing the item editor without applying discards its edits. Settings belong to the item and are shared by every pool using it; removing it from a pool keeps its settings.
decklock config set background_pool '["procedural:starfield"]'
decklock config set procedurals.starfield.color '#b4befe'
decklock config set procedurals.starfield.speed 1.0
decklock config set idle_pool '["procedural:lissajous"]'
decklock config set idle_reuse_background false
decklock --previewThe IDs are procedural:starfield, procedural:particles,
procedural:lissajous, procedural:matrix, procedural:doom-fire,
procedural:aurora, procedural:flow-field and procedural:ridgeline.
Density means particle count, matrix columns, doom-fire flame height (120 keeps the top dark, 300 fills the frame), aurora bands, flow-field streamlines or ridgeline rows, depending on the item.
Per-item TOML tables live under [procedurals.starfield] (and the other IDs).
config unset procedurals restores default parameters. No third-party code runs.
Rendering uses an opaque raster texture capped at 640 pixels on the longest side,
scaled to the window. Hidden widgets stop requesting frames. Battery savings are
not yet measured. See example configuration.
decklock --preview # Try without locking
decklock --preview --keyboard # Show the embedded keyboard
decklock --greeter # Native greetd login or standalone greeter preview
decklock --lock # Explicitly lock the sessionWith no arguments, decklock prints help. Use decklock --help or
decklock config --help for commands and examples. Preview never authenticates or runs
power actions. Escape hides the keyboard, then closes the preview.
0.3.6 is experimental. Preview/settings have been tested on Hyprland. Isolated protocol tests cover lock acquisition, monitor changes and termination without unlocking, and disposable virtual machines exercise each packaged locker against real Sway and real Linux-PAM on Arch, Fedora and Ubuntu, including denial, unlock and account lockout. GPU paths, physical controllers and power actions, other compositors and other PAM policies still need validation before replacing an existing locker.
Select Classic, Catppuccin Mocha/Latte, Dracula, Nord, Tokyo Night or Gruvbox. Colors update settings and the open preview immediately, without restarting the video for palette-only changes. The language selector switches between English and Brazilian Portuguese without discarding unsaved edits.
The settings background has a subtle woven texture, controlled by CSS. Cards and controls retain readable surfaces. Open preview shows unsaved changes; Save persists your configuration.
The left side is your media library; the right side is the selected pool. Use the Images/Videos tabs, select an item and click Add →. Removing an item from the pool does not delete its file. The ⓘ tooltip explains selection behavior. The eye opens one reusable viewer for images and muted videos.
Each lock randomly selects a pool item. A video loops for that session; a photo
starts a crossfading slideshow of the pool's photos, using the configured interval.
After login setup, Import media (and decklock media import FILE) uses the
same shared library as the locker and greeter. Your files move there; their old
paths become links, so there is one stored payload. decklock media path prints
the directory. All local accounts can read shared media; only its owner can write
it. Removing a pool entry still leaves the file intact. Without login sharing,
imports keep the private-library behavior: copies under
$XDG_DATA_HOME/decklock/library (default ~/.local/share/decklock/library).
The default installation includes this original video by Yan Vidal. Click the thumbnail to open the file. Additional original photos/videos will be added in future releases.
Osaka Dōtonbori · video · 1920×1080 · 10 seconds · loops without sound in DeckLock. Credits and distribution notes.
The pack is installed at /usr/share/decklock/media, outside the Rust executable.
On a fresh setup it supplies the default background. Updates preserve imported
files and your selected pools. Existing explicit backgrounds retain priority.
See the media pack guide to add future artwork.
Choose the Rest tab to see the idle appearance in the open preview. Set its inactivity time, independent media pool and photo interval, or keep the normal background and hide the controls. Disable idle mode hides all dependent options while preserving their values. The Background tab returns to the normal preview.
The clock stays visible by default, including when reusing the normal background.
Themes can change this with [layout] idle_clock_visible = false. Rest mode is
DeckLock's own visual inactivity mode; it does not suspend the computer.
Expand Layout & preferences to change alignment, spacing, padding, keyboard scale and visibility. Edit CSS & theme.toml opens the live theme editor: CSS controls appearance, while TOML controls supported layout options.
Valid edits appear live. Invalid drafts retain the last valid appearance and cannot be saved. Saving creates an editable theme copy under your configuration directory without overwriting the original theme. No recompilation is needed.
Settings are stored at ~/.config/decklock/config.toml. --config PATH selects
another file. GUI [layout] values override theme defaults. Existing PAM settings
are preserved when saving. Example configuration.
- Themes and palette credits
- CSS selectors and layout guide (Portuguese)
- Translation guide (Portuguese)
Every configuration field is also available through the binary, without opening GTK windows. These commands use the same validated, atomic save as the interface:
decklock # Usage and examples
decklock config --help
decklock config path
decklock config show
decklock config get idle_seconds
decklock config set theme_preset catppuccin-mocha
decklock config set locale en-US
decklock config set idle_seconds 120
decklock config set idle_reuse_background true
decklock config set layout.padding 48
decklock config set layout.idle_clock_visible false
decklock config set background_pool '["/path/photo.jpg", "/path/video.mp4"]'
decklock config unset layout # Inherit the theme layout again
decklock config import ./my-config.tomlset accepts numbers, booleans, TOML arrays/tables and plain strings. Unknown
fields and invalid values fail without modifying the file. unset resets a key
to its schema default; unsetting an optional field restores inheritance.
--config PATH selects another configuration file for any command. For example:
decklock --config ./demo.toml config set idle_enabled falseCustom themes still use ordinary style.css and theme.toml files: edit them with
your terminal editor, then select the directory with decklock config set theme /path/to/theme. Use decklock config unset theme to return to bundled presets.
CLI commands change the saved file; reopen an existing lock/preview to load it.
The visual editor's live preview follows that editor's unsaved controls.
These installation improvements are published from 0.3.3; the 0.3.2 and earlier packages predate them. Use 0.3.3 or newer, a verified updated candidate, or a source build for the commands below.
DeckLock can serve as a greetd login greeter and compositor screen locker (hypridle) with the same UI and on-screen keyboard. The greeter runs as the configured greetd service account (greeter on Arch, greetd on Fedora), with private configuration/state storage. Setup uses one publicly readable media library shared with the locker, so login does not need permission to traverse your HOME. A manually configured shared --config still requires readable files. --greeter without a greetd socket is a safe preview: it cannot log in or run power actions.
Once the login uses DeckLock, "Apply to login" in the settings' Login tab carries later changes to it, asking for the administrator password through polkit (install and start a polkit agent such as hyprpolkitagent on Hyprland, Sway, labwc or Wayfire). From a terminal: sudo decklock setup login-appearance. It refreshes only the login's appearance and media.
Inspect your system's current integration:
decklock setup statusConfigure both login and the invoking user's hypridle with one command (greetd, Cage and hypridle must already be installed):
sudo decklock setup allUnder sudo, the lock configuration and backups are written as the invoking user in their ~/.config/hypr/hypridle.conf, preserving ownership and mode. Use --lock-target for a custom XDG location. Both configurations are reviewed before writes; if login setup subsequently fails, the error reports the completed lock changes and backups. Setup does not restart services. Run sudo decklock setup all --dry-run to review first.
Configure greetd to launch DeckLock greeter inside the cage kiosk compositor (virtual keyboard enabled by default):
sudo decklock setup greeterConfigure hypridle to lock using DeckLock:
decklock setup lockWith no hypridle.conf it writes the template. With an existing one it edits only lock_cmd, before_sleep_cmd and the on-timeout of listeners, keeping indentation and trailing comments. A known locker (hyprlock, gtklock, swaylock, waylock, i3lock, alone or behind a pidof … || guard) becomes decklock --lock. Anything else, such as your own wrapper script, is kept and listed, because a wrapper may add guards or steps DeckLock does not know about. Add --replace-custom to replace those too; a listener is only replaced when it runs the same command as lock_cmd, so systemctl suspend and dpms off are never touched. Running it again changes nothing, and a changed file is backed up first.
Reference configuration templates are installed under /usr/share/decklock/setup/ (greetd.toml, hypridle.conf, decklock.service). Use --dry-run to preview file changes without writing to disk. Setup preserves other greetd TOML options and backs up the existing file. Only installed Wayland desktop sessions are offered for greetd login; it does not launch an X session from Cage's bare VT.
The system greeter uses private config, cache, data and state under
/var/lib/decklock-greeter (or /var/lib/greetd/decklock with SELinux) (mode 0750, owned by the configured greetd account). Setup
preserves the packaged default_session.user (greeter on Arch, greetd on Fedora) and passes those paths to the login command, including a custom --state-dir; a
storage, ancestor-access or ownership failure leaves the existing greetd command intact. With
--target, only that target is written unless --state-dir is also supplied.
Dry runs create nothing. The greeter reads media without creating user folders;
optional media-folder errors in preview/lock mode are warnings that name the path. A service account with HOME=/ does not need /.config/midias.
Run sudo decklock setup all from your desktop account to configure both login
and locking, or sudo decklock setup greeter for login only. Setup migrates
selected normal/rest media and existing user-library media to one dedicated
library outside your personal HOME. Its default is /var/lib/decklock/media/UID.
If HOME is on a separate, common volume, setup prefers PARENT/.decklock-media/UID
(e.g. /home/.decklock-media/1000) on that volume, provided its existing parents
are publicly traversable and root-controlled; otherwise it falls back to
/var/lib/decklock/media/UID. This avoids filling the system
partition with large videos. Use --media-dir /absolute/dedicated/path to choose
another location; its parents must be root-owned and not writable by unprivileged
users/groups. Existing administrator group 0 permissions are preserved. The volume must be mounted before login. Private/encrypted home mounts
are not selected automatically; setup does not make them available before login.
Shared media is readable by any local account. Only the desktop owner can write the library/files (directories 0755, files 0644). The migration reads as that owner, preserves HOME permissions, and replaces original file paths with links to the canonical files. On the same filesystem it preserves the inode; between filesystems it verifies and syncs a temporary transfer before replacing the original. There is no permanent second media payload. Temporary transfers need free space on the destination. Existing generated login media copies also become links; small appearance/config/theme generations remain private for recovery. Already-public packaged media stays in place.
Videos, photo slideshows, intentionally empty pools and procedurals retain their
behavior. Repeat setup after changing the selected pools/theme; imports already
use the shared library. User configuration is backed up before migration.
--user-config PATH selects a custom XDG/config file;
--no-user-appearance keeps independent login appearance.
Explicit decklock --greeter --config PATH overrides the setup appearance.
Authentication/session options and remembered choices remain private and are
preserved. Invalid/unreadable selected inputs fail before media migration and
leave the saved login command and appearance intact. On SELinux systems setup
uses a persistent xdm_var_lib_t mapping for this dedicated directory and verifies
it without disabling enforcement; Fedora packages require semanage for that.
Reading the library does not add login-manager integrations: DeckLock's login
backend is greetd. Fullscreen is requested after the initial surface frame so older Cage/wlroots versions can initialize the login window.
The login window is always fullscreen and undecorated. Until a session choice is remembered, an installed uwsm-managed session is preferred; a remembered choice still wins. The normal user controller daemon is unavailable before login; the embedded touch/mouse keyboard remains available without capturing a controller.
For an Arch Steam Deck OLED with Hyprland 0.55 or newer installed, configure the panel and touchscreen together using the Lua greeter compositor:
sudo decklock setup all --compositor hyprland --output eDP-1 --transform 3 --dry-run
sudo decklock setup all --compositor hyprland --output eDP-1 --transform 3Use the transform appropriate to your hardware; this is the OLED orientation.
This setup needs 0.3.5 or newer: through sudo, 0.3.3 and 0.3.4 reject the Lua they
generate and leave greetd unchanged.
Setup verifies the generated Lua using the installed Hyprland before changing
greetd, preserves other greetd options, saves backups and leaves the running
service alone. Hyprland refuses to run as root, so setup verifies as greetd's
configured account. The compositor exits when DeckLock finishes so greetd can start
the authenticated session. Repeating setup without a compositor option preserves
an existing Hyprland greeter. --compositor cage explicitly returns to Cage.
This does not migrate your desktop Hyprland configuration. Panel/touch alignment,
GPU behavior and an actual Hyprland login still need hardware validation.
To use both Steam Deck pads before authentication, install sc-controller and add
--controller to setup greeter or setup all. For an existing Hyprland greeter,
repeat its compositor/output/transform options when changing this setting:
sudo decklock setup all --compositor hyprland --output eDP-1 --transform 3 --controller --dry-run
sudo decklock setup all --compositor hyprland --output eDP-1 --transform 3 --controllerThis is opt-in. Setup preserves the choice on repeat; --controller=false
disables it. Real greetd login then owns a separate foreground daemon and an
embedded login profile in private runtime storage. It does not read the desktop
controller profiles or start another keyboard/OSD. Closing the keyboard releases
pad capture; the right pad and triggers provide mouse/click input via the profile.
While the keyboard is open, A confirms like Enter.
Normal exit stops and reaps the daemon; a killed greeter also kills its daemon.
Missing sc-controller, device access or a failed daemon leaves the mouse/touch
keyboard available. The greetd account needs the controller/uinput access granted
by the sc-controller package's device rules; setup does not change device permissions
or account groups. --greeter-controller never starts a daemon in preview or
without greetd. This option is published from 0.3.4, before its validation on a
physical Steam Deck: the packaged VM gates install no sc-controller, and pad input,
device access and the handoff to the desktop daemon are tested only against fake
processes. See the device procedure.
Reboot to activate a changed login command, or end the managed desktop session and restart greetd from a separate TTY. greetd caches its configuration at startup; logout alone does not reload it. Keep the printed backup and a working TTY available for recovery; restarting greetd from its live desktop session can terminate that session. Install the packaged candidate with its PAM file for lock testing.
Controls automatically fit logical viewports smaller than 1280×800, in lock, login and preview. On a 1280×800 Steam Deck at desktop scale 1.6 (800×500 logical), they shrink by 0.625 to match the scale-1 login size. Desktop zoom stays unchanged; media and its gradient still fill the surface. Keyboard hit testing follows the same transform. Larger viewports retain their current control size, and existing theme/layout options remain valid.
Mouse, physical keyboard and optional controller input use the same password field. Double-tap Shift to latch Caps Lock; tap again to release. Alt provides supplementary symbols when the system layout has no AltGr layer. Keyboard layout uses the first GDK keymap group at startup.
The external sc-controller daemon is optional:
decklock --preview --controller
# From another terminal or shortcut:
decklock --toggle-keyboardThe settings preview never captures a controller. Normal controller preview needs
explicit --controller or --controller-socket. Existing deck-osk --toggle
shortcuts remain compatible. Capture is released when the keyboard closes.
Power and session buttons use switch_user_command, LightDM, GDM or activation of an existing logind greeter session for user switching, as well as systemctl suspend, hibernate, reboot and poweroff. A single greetd instance starts its greeter again after its current user session ends; it does not create a concurrent greeter for fast switching. Configure a separate supported display-manager action if that behavior is needed.
Permissions and working sleep/hibernate behavior belong to the host system.
Preview buttons only show tooltips. Plugins are not implemented; media playback
uses installed GStreamer codecs.
In settings, F1 or the ? button opens an offline guide that follows the settings language.
The lock screen, login and preview show a short guide inside the screen instead
(unlocking, signing in).
Read General and Advanced.
Ordinary windows have close controls; the title-bar preference is also available through decklock config set window_decorations false.
See the roadmap, changelog and release procedure.
DeckLock targets modern Linux desktop sessions. Because session locking interacts directly with display protocols and PAM authentication, compatibility depends on your compositor, distribution, and architecture:
| Environment | Status | Security Guarantee | Validation |
|---|---|---|---|
| Sway | ✅ Supported | Full (ext-session-lock-v1) |
Automated disposable VM (Arch, Fedora 43, Ubuntu 26.04) with real PAM, lockout and account policy |
| Labwc, Wayfire | ✅ Supported | Full (ext-session-lock-v1) |
Automated disposable VM (Arch, Fedora 43, Ubuntu 26.04): input isolation, real PAM denial and unlock, input restored, killed locker stays locked. Wayfire renders there with software GLES, not a real GPU |
| Hyprland, niri, river, COSMIC | ✅ Supported | Full (ext-session-lock-v1) |
Protocol compliance only; same Wayland backend, not run in the VM (Hyprland's Aquamarine backend needs a real GPU allocator, niri and COSMIC have no headless mode, river is not packaged on Ubuntu 26.04) |
| X11 sessions | --features x11) |
Reduced (keystrokes not isolated by protocol; screen unlocks if process dies) | Isolated gate (Xvfb + xfwm4 + intruder probe); accelerated video via GLX/EGL |
| GNOME & KDE Plasma | ❌ Not supported | N/A | Refuses to lock safely (both draw their own internal lock screen) |
| Distribution | Prebuilt Package | PAM Service Included | VM Automated Test | Notes |
|---|---|---|---|---|
| Arch Linux | ✅ .pkg.tar.zst |
✅ /etc/pam.d/decklock |
✅ Real PAM + faillock | Primary tier |
| Fedora 43+ | ✅ .rpm |
✅ /etc/pam.d/decklock |
✅ Real PAM | Stock install requires authselect to enable faillock counting |
| Ubuntu 26.04+ | ✅ .deb |
✅ /etc/pam.d/decklock |
✅ Real PAM | Packages gtk4-layer-shell >= 1.3 |
| Ubuntu 24.04 | ❌ No | — | — | Missing gtk4-layer-shell in distribution repositories |
| Debian 13 | ❌ Blocked | — | — | Ships gtk4-layer-shell 1.0.4 (below 1.2 requirement); a weekly CI job reports when a Debian release or backport carries 1.2 |
| Other Linux | ⚙️ Build from source | Manual setup | — | Requires GTK 4.22+, GStreamer 1.28+, Linux-PAM, gtk4-layer-shell >= 1.2 |
| BSD (FreeBSD / OpenBSD) | ❌ Out of scope | — | — | Different auth/power stacks (BSD Auth, OpenPAM without faillock, no systemd) |
| Architecture | Status | Package Availability |
|---|---|---|
| x86_64 (AMD64) | ✅ Supported | Published packages (.pkg.tar.zst, .rpm, .deb, .tar.gz) |
| aarch64 (ARM64) | ✅ Ubuntu · 🚧 Fedora | Ubuntu 26.04 .deb published from 0.3.2, after the full VM gate in an emulated guest (hosted arm64 runners have no KVM). Fedora arm64 is built and passes the package contract, but stays unpublished until it has its own VM target. Untested on real ARM hardware |
What about X11? An X11 backend is included in candidate release packages (--features x11). X11 gives a weaker lock than Wayland, and the lock screen says so while it is up: any other program in the session can read what you type, and if DeckLock stops, the screen unlocks. Prefer Wayland where you have it; DeckLock never uses X11 in a session that has ext-session-lock-v1. Video backgrounds take the accelerated GL path on X11 when built with this feature.
Why not GNOME or KDE Plasma? Both draw their own lock screen inside the desktop and do not let another program replace it, so there is nothing for DeckLock to connect to. On them DeckLock refuses to lock and says so, rather than locking in a way that would not be safe. Use the desktop's own lock screen there. Their X11 sessions are not a way around this: GNOME has removed its X11 session and Plasma is dropping its own.
Every PR runs the full regression gate and builds an Arch candidate package on GitHub. Main requires passing checks; public releases are built and verified from version tags after merge. See test coverage and limits and agent rules.
Requires Rust 1.93+, GTK4 4.12+ development files, GStreamer base/good/GL libraries and codecs, Linux-PAM, pkg-config and gtk4-layer-shell 1.3+. On Arch:
sudo pacman -S --needed base-devel rust gtk4 gtk4-layer-shell gstreamer gst-plugins-base gst-plugins-good gst-libav pam
git clone https://github.com/yan-vidal/DeckLock.git
cd DeckLock
cargo build --release --locked
cargo run -- --settingsIf the distribution does not provide gtk4-layer-shell 1.3+, the local bootstrap requires Meson, Ninja, a C compiler, Wayland and wayland-protocols:
scripts/bootstrap-native
scripts/cargo-local build --release --locked
scripts/cargo-local run -- --previewThe bootstrap verifies a pinned archive and installs only into .deps/.
scripts/cargo-local test --locked
scripts/cargo-local fmt --all -- --check
scripts/cargo-local clippy --locked --all-targets -- -D warnings
scripts/cargo-local run --locked --example settings_check
scripts/cargo-local run --locked --example settings_live_check
scripts/cargo-local run --locked --example preview_check
scripts/cargo-local run --locked --example media_check
python3 scripts/test-controller-shortcut.py
scripts/bootstrap-native --tests
python3 scripts/test-lock-isolated.pyGUI tests use temporary configurations. Protocol tests use a separate Wayland socket and never lock the active desktop. Documentation GIFs show the real GTK interface; the capture harness moves the pointer before applying each action.
python3 scripts/package-release.py
cd dist
makepkg --nodeps
sha256sum decklock-*.pkg.tar.zst >> SHA256SUMSThis stages the optimized binary and assets/media together. It does not install
or enable a locker on the build machine. The emitted Arch recipe records runtime
requirements for the release build. Packaging details.
The application runs in Rust; Python is used only for development helpers and the optional legacy theme importer. The old Python app remains in Git history. Implementation status.




