Documentation

ujust commands — every Margine recipe

On an atomic system you don't hand-edit the OS — you run small, repeatable recipes. Margine ships its opinionated actions as `ujust` commands (Universal Blue's wrapper around the `just` task runner). Each one is idempotent, documents itself, and does exactly one job. This page is the full reference for Margine's own recipes: what each does, how to use it well, and the caveats (does it need sudo? a reboot? does it layer packages?). Type `ujust` on its own for the interactive menu, or `ujust --list` to see every recipe with a one-line description.

How to find them

  • ujust — opens the interactive menu (arrow keys + Enter).
  • ujust --list — prints every recipe grouped by category, each with the one-line help shown below.
  • ujust <name> <args> — runs one directly, e.g. ujust margine-scheduler lavd.

Most recipes take an optional argument; where one does, the default is shown in brackets. Margine's recipes are listed below by theme. (Bluefin/Universal Blue's base image also ships many ujust recipes — those show up in ujust --list too; this page covers only Margine's own.)

Setup & maintenance

The four you'll use most — bring the desktop to its intended state, update safely, and check health.

ujust margine-bootstrap [interactive]

Applies the full Margine user-state in one shot: home layout (~/data + ~/dev + ~/scratch + XDG remap + bookmarks), Hyprland-style keybindings, GNOME appearance, default apps (Zen, Ptyxis), and the Activities app-folder grouping. Runs every margine-configure-* step and prints a pass/fail summary.

  • Why: gets a fresh login (or a drifted session after upgrades) to the complete intended state without running each step by hand.
  • Best: it's idempotent — re-run it any time keybindings, bookmarks, or appearance drift; matching keys report [no change]. Pass unattended to skip the confirmation prompt (this is what runs automatically on first login). Afterwards, log out/in (or Alt+F2 → r) to refresh the dock and bindings.
  • No sudo, no reboot, no package changes — pure user-state under $HOME, reversible by hand.

ujust margine-update

Pulls the latest Margine :stable and stages it for the next reboot, automatically choosing the right upgrader: rpm-ostree upgrade if you have layered packages (e.g. native gaming), otherwise bootc upgrade.

  • Why: it's the single correct way to update. bootc upgrade refuses a layered deployment; this recipe always picks the one that works (and re-applies your layers).
  • Best: always use this instead of raw bootc upgrade, especially after margine-gaming-native. It prints margine-status first so you see how far behind you are, then reboot with systemctl reboot to switch in.
  • Needs sudo; the update is staged, not live (reboot required).

ujust margine-status

Read-only report: your deployment vs the latest published :stable, the Fedora → Bluefin → Margine lineage, and the running kernel. No sudo, changes nothing. Run it before deciding to update (margine-update calls it for you).

ujust margine-doctor

Runs every Margine validator in sequence with a one-line PASS/FAIL each — the "is my system as shipped?" health check. On a FAIL it points you at a per-run log under /tmp. It deliberately exits with an error if zero validators are found (that would itself be an image regression), so a clean run really means the checks ran.

Performance & input

ujust margine-scheduler [status|off|<scheduler>]

Switches the CPU scheduler (sched_ext / BPF) at runtime. No argument (or status) shows the current scheduler and the list of available ones; off stops scx_loader and returns to the kernel default (BORE); a name from the list (e.g. lavd) applies it and saves it as the boot default.

  • Why: opt into a latency/throughput-tuned BPF scheduler. The schedulers ship in the image but stay off by default.
  • Best: run ujust margine-scheduler first to see the valid names for your kernel (they come straight from scxctl list — an unknown name is rejected with the list reprinted, so you never guess). The GUI equivalent is Activities → Margine CPU Scheduler.
  • Applying/off self-escalate via sudo; status needs none. Live, no reboot.

ujust wsf-preload [on|off|status]

Toggles the wayland-scroll-factor preload that Margine injects into GNOME Shell (on by default). off installs a systemd user drop-in that unsets it; on removes it; status reports the state.

  • Best: off/on only take effect after a logout/login (the preload loads at shell start). To change scroll speed without logging out, run wsf set 1.0 (or another factor) live instead.
  • on/off use sudo (system-level drop-in); status is read-only.

ujust margine-grub-hidpi

Forces the HiDPI GRUB font + grub.cfg re-render right now. You normally never need this — a boot service applies it automatically whenever the image's GRUB config changes. Run it only to apply the change immediately after an update instead of waiting for the next reboot. Needs sudo; idempotent and backed up (safe to re-run).

Gaming

Two flavours of the same layer — pick by how much you game. Both prompt before doing anything, both roll back, both need a reboot to activate their RPMs.

ujust margine-gaming

The default, Flatpak-first layer: Steam, Lutris, Heroic, Bottles, Protontricks, ProtonPlus and RetroArch as Flatpaks, plus gamescope + vkBasalt as the only rpm-ostree-layered RPMs.

  • Why: the supported way to game on Margine (the separate Gaming image was retired). Sandboxed Flatpaks mean near-zero upgrade overhead — ideal for the occasional gamer.
  • Best: the Flatpaks work immediately from Activities, but you must reboot to activate gamescope/vkBasalt. For host MangoHud inside Flatpak Steam: flatpak override --user --filesystem=xdg-config/MangoHud:ro com.valvesoftware.Steam, then MANGOHUD=1 %command% (and gamescope -- %command%) in a game's launch options.
  • Needs sudo; layers via rpm-ostree → from then on update with ujust margine-update, never bootc upgrade. Roll back with margine-gaming-remove.

ujust margine-gaming-native

The native-RPM variant: Steam, Lutris and RetroArch as layered RPMs (Heroic/Bottles/Protontricks/ProtonPlus stay Flatpak).

  • Why: maximum Proton/Wine compatibility — anti-cheat (EAC/BattlEye) works, VR/Steam Link/USB controllers integrate cleanly, Mesa always matches the system. The cost is +30–60s per update.
  • Best: choose this if you game daily, run anti-cheat titles, or use VR; otherwise the Flatpak default is plenty. If you already ran the Flatpak variant, run margine-gaming-remove first. Reboot to activate the RPMs.

ujust margine-gaming-remove / ujust margine-gaming-native-remove

Roll back the respective variant (uninstall the gaming Flatpaks + un-layer the RPMs). Reboot afterwards to release the layer. Both keep the base-Margine helpers (mangohud, goverlay, gamemode, steam-devices, input-remapper, tuned…) since those are useful outside gaming too.

Security & disk

ujust margine-tpm-unlock [status|enable|disable] [7]

Manages TPM2 auto-unlock for the encrypted root. status inspects; enable [PCRS] enrolls the TPM2 and wires tpm2-device=auto into /etc/crypttab; disable removes only the TPM2 keyslot + its crypttab option. PCRs default to 7 (binds unlocking to the Secure Boot state).

  • Why: the disk unlocks automatically from the TPM at boot — no passphrase prompt — while your LUKS passphrase stays as a fallback.
  • Best: enable it after Secure Boot is on (PCR 7 measures it). Run status first, then enable, then reboot to confirm a prompt-free unlock. It's lockout-proof by design: it refuses to leave the TPM as the only key.
  • Runs under sudo (all actions). Changes take effect at the next boot.

The old ujust margine-tpm2-enroll is a deprecated alias kept for muscle memory (enrollenable, removedisable). Use margine-tpm-unlock for new work.

ujust margine-autologin [status|on|off] [user]

Enables/disables GDM autologin. status (read-only, no sudo) reports the config; on [user] enables it (backs up /etc/gdm/custom.conf and self-escalates); off disables it.

  • Best: only enable this on a LUKS-encrypted machine — autologin boots straight to the desktop with no password, so disk encryption is what's still gating access at power-on. Pairs naturally with margine-keyring.

ujust margine-keyring [status|blank|restore]

Fixes the login-keyring password prompt that appears under fingerprint login or autologin (PAM never gets the password that encrypts the keyring). status reports whether it's password-protected; blank backs it up and sets the password empty so it auto-unlocks; restore reverts.

  • Best: run status first; use blank together with autologin/fingerprint to stop the prompts. Keep the backup — restore puts the encrypted keyring back.
  • Per-user, no sudo. After blank the keyring is stored unencrypted — acceptable only because Margine encrypts the disk (LUKS + TPM2).

AI / local LLMs

ujust margine-ai

Installs the local-AI workflow: the Alpaca Flatpak (a chat GUI for local LLMs that bundles its own Ollama backend — no host install, no daemon). It detects your GPU and, on AMD, offers the in-sandbox ROCm plugin.

  • Why: a one-command, fully offline/private ChatGPT-style chat. Models download on first launch from Alpaca's UI.
  • Best: starter models — llama3.1:8b (general), qwen2.5-coder:7b (code), phi3.5:3.8b (CPU-only/low-RAM). On an integrated AMD APU, if ROCm won't see the card, set HSA_OVERRIDE_GFX_VERSION=11.0.0 in Alpaca → Preferences, or just skip ROCm and let Ollama's Vulkan backend run (usually works on APUs). ~8 GB VRAM is comfortable for ~7B models.
  • No sudo, no reboot (installs a system Flatpak; may show a polkit dialog). Undo with margine-ai-remove.

ujust margine-ai-remove

Uninstalls Alpaca (and its AMD plugin). It deliberately keeps your downloaded models — delete ~/.var/app/com.jeffser.Alpaca/data/ by hand to reclaim that (multi-GB) space.

Testing ISOs in a VM

ujust margine-test-vm [iso] [name] [80]

Spins up a throwaway VM to test a Margine ISO on the real secure path: UEFI Secure Boot with Microsoft's keys pre-enrolled (so you exercise the MOK enrollment flow) + an emulated TPM 2.0 (so you can test LUKS auto-unlock). With an ISO it creates and boots a ready installer VM; with no ISO it defines a shut-off template to clone in virt-manager.

  • Why: validate a freshly built ISO end-to-end on the exact firmware path real hardware uses — without touching your host, sudo, or copying multi-GB files.
  • Best: pass the ISO as the first arg: ujust margine-test-vm ~/Downloads/margine-<date>.iso. Then follow the printed walkthrough — enroll the MOK (password margine-os, public by design), confirm with mokutil --sb-state, then ujust margine-tpm-unlock enable and reboot to test TPM2 unlock. The ISO can stay inserted (boot order is hd,cdrom, so after install the disk wins — no install loop).
  • Rootless on qemu:///session (no sudo). Needs Bluefin DX's virt stack. Tear down with margine-test-vm-remove.

ujust margine-test-vm-remove [margine-test-template]

Stops and fully deletes a test VM — domain, disk(s) and UEFI nvram. Defaults to the clone template; pass the exact name otherwise (virsh -c qemu:///session list --all to check). Rootless, no sudo, irreversible. Run it whenever margine-test-vm reports a name collision, then recreate.

Apps

ujust install-koofr [install|remove] (alias: ujust koofr)

Installs the Koofr Desktop cloud-sync client natively and rootless into ~/.koofr-dist (Koofr has no Flatpak/RPM — only a self-updating tarball, so it stays out of the read-only image and updates itself). It autostarts hidden to the system tray at login (the binary's -silent flag), while a manual launch from the menu opens the window normally.

  • Best: re-run it to update (there's no separate updater). It persists the hidden-start preference into ~/.koofr/config.json only when Koofr isn't running, so quit Koofr before re-running. ujust install-koofr remove uninstalls the client and its launchers (it keeps your ~/.koofr config and synced data).
  • No sudo, no reboot — fully per-user. Needs network + jq (both present on Margine).