The unofficial, missing GUI for day-to-day Guix usage (+ rust library) — search, install, upgrade, and (with polkit) pull and reconfigure the system. https://gofranz.com/software/guix-rs/
  • Rust 83%
  • Fluent 14.9%
  • Scheme 2.1%
Find a file
2026-06-03 16:40:52 +01:00
.github/workflows chore: fix ci 2026-05-17 18:36:41 +01:00
assets feat: channel-gated home tiles, development category, and about tab 2026-05-18 10:14:48 +01:00
guix-gui feat: libguix installer support — system init, already-root mode, build flags, archive, retry 2026-06-03 16:40:52 +01:00
libguix feat: libguix installer support — system init, already-root mode, build flags, archive, retry 2026-06-03 16:40:52 +01:00
polkit feat: initial commit 2026-05-17 16:13:52 +01:00
.envrc feat: initial commit 2026-05-17 16:13:52 +01:00
.gitignore feat: initial commit 2026-05-17 16:13:52 +01:00
Cargo.lock feat: libguix installer support — system init, already-root mode, build flags, archive, retry 2026-06-03 16:40:52 +01:00
Cargo.toml feat: libguix installer support — system init, already-root mode, build flags, archive, retry 2026-06-03 16:40:52 +01:00
CHANGELOG.md feat: libguix installer support — system init, already-root mode, build flags, archive, retry 2026-06-03 16:40:52 +01:00
LICENSE feat: initial commit 2026-05-17 16:13:52 +01:00
manifest.scm feat: initial commit 2026-05-17 16:13:52 +01:00
NOTES.md feat: initial commit 2026-05-17 16:13:52 +01:00
README.md feat: libguix installer support — system init, already-root mode, build flags, archive, retry 2026-06-03 16:40:52 +01:00

Guix GUI + Library (rust)

guix GUI

The unofficial, missing GUI for day-to-day Guix usage — search, install, upgrade, and (with polkit) pull and reconfigure the system.

Description

Two pieces: a Rust library (libguix) that wraps the guix CLI and its machine-readable REPL, and a GUI (guix-gui, built on Iced) that uses the library to search packages, install / remove / upgrade them, and — with polkit — pull and reconfigure the system. The library surface also covers generation listing, switching, and rollback; the GUI doesn't expose those yet.

Home Search Installed Updates Settings

Install — GUI

Packaged on the panther channel. With the channel configured:

guix package -i guix-gui

Or build and run from source:

cargo run -p guix-gui --release

For smoke-testing without mutating your real profile, build with the dev-temp-profile feature — install/remove will target a temp profile instead of $GUIX_PROFILE:

cargo run -p guix-gui --release --features dev-temp-profile

Translations

The GUI ships in English plus German, Spanish, French, Italian, Brazilian Portuguese, and Simplified Chinese. It follows your system locale by default and falls back to English; you can also override the language in Settings, and the switch is live — no restart.

Strings live as Fluent catalogues under guix-gui/i18n/ — one <lang>/guix-gui.ftl per locale, embedded into the binary at build time. Adding a language is just dropping a new i18n/<code>/guix-gui.ftl (copy en/ as the template) and rebuilding — no code change.

One caveat: only the English catalogue is hand-written. The rest are machine-translated and haven't had a native-speaker pass, so expect the odd rough edge. Corrections and new languages are very welcome — a PR against the relevant .ftl is the whole job.

Build

The repo has a manifest.scm that pins every native dep libguix and guix-gui need — Rust toolchain, gcc-toolchain with CC set, pkg-config, openssl with OPENSSL_DIR set, plus the X11 / Wayland / Vulkan / fontconfig stack that Iced 0.13 (on wgpu) requires at build and run time.

guix shell -m manifest.scm -- cargo build --release

Or, à la carte:

guix shell rust rust:cargo gcc-toolchain -- sh -c "CC=gcc cargo build --release -p libguix"

Usage — library

Crates.io Docs.rs

[dependencies]
libguix = "0.1"
use libguix::Guix;

let guix = Guix::discover().await?;
for hit in guix.package().search_fast("ripgrep").await? {
    println!("{}{}", hit.name, hit.synopsis);
}

Long-running operations return an Operation with a coalesced event stream and a CancelHandle:

use futures_util::StreamExt;
use libguix::ProgressEvent;

let mut op = guix.package().install(&["ripgrep", "fd"])?;
while let Some(batch) = op.events_mut().next().await {
    for evt in batch {
        if let ProgressEvent::Line { text, .. } = evt {
            println!("{}", text);
        }
    }
}
op.await_completion().await?;

See libguix/README.md and libguix/src/lib.rs for the full surface.

Polkit

Polkit is required only for the privileged pathsSystemOps::reconfigure and PullOps::as_root — both of which need to mutate system state owned by root. Everything else (user-profile install/remove/upgrade, search, generation listing) runs unprivileged against $GUIX_PROFILE and needs no agent. (Library consumers that are already root, e.g. an installer on a TTY, can pass Privilege::AlreadyRoot to skip polkit entirely — see libguix/README.md.)

Two custom polkit actions ship under polkit/:

  • org.libguix.system-reconfigure — permits /run/current-system/profile/bin/guix system reconfigure …
  • org.libguix.system-pull — permits /run/current-system/profile/bin/guix pull … (updates the root catalog at /var/guix/profiles/per-user/root/current-guix, which is what system reconfigure resolves against)

Both are scoped via argv constraints so they only match the specific subcommand, and both use auth_admin_keep so successive calls within polkit's grace window don't re-prompt. Full rationale and install instructions are in polkit/README.md.

Authentication agent

pkexec only works if a polkit authentication agent is running in your session — the agent is what shows the password prompt. Without one, the privileged calls from the GUI will hang or fail silently. libguix detects this case and surfaces a clear error pointing at the polkit README.

Pick whichever agent matches your desktop:

Agent Notes
lxqt-policykit-agent Lightweight, works under any WM. I run this one — lxqt-policykit-agent & from my session startup.
polkit-gnome-authentication-agent-1 GNOME
polkit-kde-authentication-agent-1 KDE Plasma
mate-polkit, xfce-polkit, hyprpolkitagent matching desktops

Install the actions

  • Guix System: declare the policies via polkit-service-type. A reference package (libguix-polkit) lives in the panther channel at px/packages/libguix.scm — lift it into any channel. See polkit/README.md for the simple-service snippet.
  • Foreign distro: copy both .policy files into /etc/polkit-1/actions/ as root. Polkit picks them up without a restart.

Verify either way:

pkaction --action-id org.libguix.system-reconfigure --verbose
pkaction --action-id org.libguix.system-pull        --verbose

Packaging

For packagers — the app icon and a reference .desktop entry ship under assets/:

  • assets/icon.svg — square SVG. SVG icons are picked up directly by most desktops (GNOME, KDE, LXQt, Xfce) when installed to share/icons/hicolor/scalable/apps/guix-gui.svg. For desktops that insist on raster, render PNGs at 48/64/128/256 from the SVG.
  • assets/guix-gui.desktop — drop into share/applications/.

Development

guix shell -m manifest.scm -- cargo test

libguix has a live-tests feature that actually shells out to a working guix on the host (rather than the controlled subprocess used by default). Off by default; opt in when you want to exercise the real CLI:

guix shell -m manifest.scm -- cargo test -p libguix --features live-tests

Format via Podman (the rustfmt component isn't in the Guix toolchain):

podman run --rm -v $PWD:/work -w /work rust:latest \
  sh -c "rustup component add rustfmt && cargo fmt"

License

Licensed per crate:

  • libguix — MIT OR Apache-2.0 (permissive, so other tools can embed it freely). See libguix/LICENSE-MIT and libguix/LICENSE-APACHE.
  • guix-gui — GPL-3.0-only (end-user binary). See the root LICENSE file.