Skip to content

Install

Get a working scoot binary. Pick your build first (one command), then your path below — or take the whole desktop and skip choosing piece by piece.

Two axes, decided independently: CPU or GPU rendering, and whether you need X11 apps. Four prebuilt packages cover the combinations (all in the Cachix cache, below):

Package Renders with Needs Pick it when
scoot (default) pixman on the CPU; no GPU at all nothing VM, webtop/container, no /dev/dri, nested-only use, or unsure
scoot-gpu GPU scanout under --tty, dma-buf handoff under --nested a DRM render node + Mesa/GBM driver, and a real seat for --tty daily-driving on real hardware (laptop/desktop, Intel/AMD/Apple Silicon)
scoot-xwayland as scoot as scoot, plus X11 apps to run you need X apps but no GPU path
scoot-gpu-xwayland as scoot-gpu as scoot-gpu, plus X11 apps to run real hardware and X apps

XWayland is its own axis for a reason: it adds ~344 MiB of closure (all but ~12 MiB of it Xwayland’s own, which links Mesa) and a trust decision — any X client can keylog and read other X clients by design. Take it only if you run X apps. (More in XWayland.)

One visible side effect of the two -xwayland packages: their wrapper leaves the process name as .scoot-wrapped, not scoot — so pgrep -x scoot finds nothing there; use pgrep -x .scoot-wrapped.

Terminal window
ls /dev/dri/renderD*
  • No output (no such directory, no matches) → there is no GPU to use. Take the default scoot. This is the VM, webtop and container case, and it is a first-class configuration, not a degraded one: pixman is the default renderer and GPU-free operation is a hard requirement, not a fallback tier.
  • A render node listed (e.g. renderD128) → a GPU exists. On real hardware with Intel/AMD graphics or Apple Silicon under Asahi Linux, take scoot-gpu. On a VM the node is usually software (llvmpipe) — there gles is several times slower than pixman, so stay on the default unless you measured otherwise.

Confirm what you actually got from scoot’s own startup log: with --renderer gles a working GPU prints the GLES renderer is up with device=/dev/dri/renderD128 software=false. Trust that line over the flag name — a device node backed by a software driver answers software=true, and then you are rendering in software anyway.

What the GPU build buys, measured on an Apple M2 under Asahi Linux: 4–5x less compositor CPU under damage (20.8% of a core → 4.3% under large-damage pointer motion; 52.0% → 14.0% under a full relayout), the same pixels, ~0.2 W less power, 7–16 MB more RSS, and no measurable CPU difference at idle. What it costs: the EGL drivers must come from your system (NixOS: hardware.graphics enabled), and --tty scanout needs the real seat.

Symptom: --renderer gles exits at startup naming EGL devices. That is the intended behavior, not a bug to work around: when EGL itself is missing or broken, a wrong --renderer gles is a startup error, never a silent downgrade — scoot names each failure and points back at --renderer pixman, which needs no GPU at all. There is no automatic fallback to the CPU tier on that path. Either drop the flag (stay on pixman) or fix the cause: the GPU build installed, drivers present, render node visible. (The one deliberate fallback is the other direction: under --tty, a gles session whose device cannot drive GPU scanout warns and keeps the CPU renderer with dumb buffers instead of refusing to start — see Backends and rendering.)

The package knob is programs.scoot.package (home-manager and NixOS alike; the desktop profile never sets it — the choice stays yours):

programs.scoot = {
enable = true;
# Real hardware with a GPU: take the scanout build.
package = inputs.scoot.packages.${pkgs.system}.scoot-gpu;
# ...plus X11 apps? Use scoot-gpu-xwayland instead.
};

Leave the default (omit package) for the CPU build. The same names work with nix profile add and nix run below — swap scoot for scoot-gpu (or a -xwayland variant) wherever it appears.

If you have Nix, run scoot straight from the flake. Nothing is installed:

Terminal window
nix run github:scoot-sh/scoot -- --nested -- foot

This opens scoot in a window on your current desktop with a terminal in it. Close the window to quit. (Why foot? It is scoot’s default terminal — install it too, or name another one. More in First session.)

scoot runs on Linux. With Nix:

Terminal window
nix profile add github:scoot-sh/scoot#scoot github:scoot-sh/scoot#scootctl \
github:scoot-sh/scoot#scootbar

Symptom: nix: command 'nix' not found, or your Nix says nix profile install instead of nix profile add. Older Nix calls the subcommand install — same command, old name. If Nix itself is missing, install it from nixos.org first.

Every merge to main pushes built binaries for x86_64-linux and aarch64-linux to the public Cachix cache scoot-sh — all four scoot variants above, plus scootctl, scootbar and scootbg. Without it, Nix compiles Smithay and scoot’s crates on your machine (minutes); with it, you download. Opt in explicitly in your Nix configuration — NixOS (configuration.nix):

nix.settings = {
extra-substituters = [ "https://scoot-sh.cachix.org" ];
extra-trusted-public-keys = [
"scoot-sh.cachix.org-1:QMj7CMw8uqZxrvqqm6SggdxTHz6Q4prt30ydDcXJXCo="
];
};

Per user (~/.config/nix/nix.conf), the same two lines:

extra-substituters = https://scoot-sh.cachix.org
extra-trusted-public-keys = scoot-sh.cachix.org-1:QMj7CMw8uqZxrvqqm6SggdxTHz6Q4prt30ydDcXJXCo=

What this trusts: binaries built by CI from reviewed merges to main. A substituter can serve any store path your Nix asks for, so this trusts CI’s builds the way installing the flake already trusts its source.

The names in the chooser above are flake outputs (packages.<system>.*); the same derivations are also pkgs.* through the overlay, nix run apps, and per-system defaults:

Name Gives you Pick it when
scoot the compositor alone ($out/bin carries only scoot) the Linux default; VM, webtop, nested-only
scoot-gpu the same binary with the gpu-scanout feature real hardware with a GPU (still named scoot)
scoot-xwayland / scoot-gpu-xwayland those two with the xwayland feature and Xwayland on PATH (Linux only) you run X11 apps
scootctl the standalone remote-control client (every system) driving a compositor running in a VM
scootbg the wallpaper daemon (Linux only) [wallpaper] without the desktop profile
scootbar the status bar, no font in its closure (Linux only) the bar with your own fonts
scootbar-demo the bar with a nixpkgs font as its default trying the bar on a box with no fonts
default scoot on Linux, scootctl on macOS — whichever is honest there nix run without choosing

nix run mirrors six of them — default, scootctl, scoot-gpu, scoot-xwayland, scootbar and scootbar-demo (no scootbg, scoot-gpu-xwayland or docs-site app):

Terminal window
nix run github:scoot-sh/scoot -- --nested -- foot
nix run github:scoot-sh/scoot#scootbar-demo -- daemon --right clock

overlays.default adds pkgs.scoot, pkgs.scootctl and, on Linux, pkgs.scootbg and pkgs.scootbar:

nixpkgs.overlays = [ inputs.scoot.overlays.default ];

They are the flake’s own builds, the same derivations as packages.<system>.*, not rebuilt against your nixpkgs — nothing is built twice. With the overlay applied, the modules’ package and wallpaper.package default to these, which is what makes the pure modules usable without the flake’s wrappers. On macOS the overlay adds scoot and scootctl (the client) and no scootbg or scootbar. It never adds scootbar-demo: a demo to run, not a package to build on.

Per-side macOS split, same rule everywhere: the home-manager module manages the config file on any system (on macOS files-only, with package defaulting to null — the config you edit here deploys to a Linux box), while the NixOS module’s session entry only means anything on NixOS. scootbg and scootbar are Linux-only: no macOS package, and on macOS a [wallpaper] section renders as written and installs nothing.

Symptom: converting an old flexwm setup builds fine but the session boots on built-in defaults — scale and binds silently gone — or the login entry fails. Three renames, all silent at build time (Nix interpolates store paths without checking the binary exists): ${pkg}/bin/flexwm → ${pkg}/bin/scoot in wrappers and Exec= lines; xdg.configFile."flexwm/config.toml" → programs.scoot.settings (or "scoot/config.toml") — this is the dangerous one, so move the content and delete the old entry, otherwise your real config sits orphaned at a path nothing reads; and the module split (homeModules.scoot, with the legacy homeManagerModules.scoot spelling still resolving, owns the config file, nixosModules.scoot owns the binaries and the login entry — a hand-rolled xdg.configFile next to the module manages a file scoot never reads, so keep the module’s and delete the hand-rolled one).

Symptom: rebuild fails with not of type 'TOML value' naming programs.scoot.settings. A value with no TOML representation (a Nix function in settings) fails the option type-check at evaluation time — loud and early, before anything builds, let alone starts a session. A value that renders but has the wrong scoot type (a string for layout.gap) builds fine and is refused at session start instead, where the loader fails safe — see Failure semantics.

On Debian or Ubuntu (Rust 1.87 or newer):

Terminal window
sudo apt install pkg-config libwayland-dev libxkbcommon-dev libinput-dev \
libdrm-dev libdisplay-info-dev libseat-dev libudev-dev libpixman-1-dev \
libgbm-dev libegl-dev libdbus-1-dev
git clone https://github.com/scoot-sh/scoot && cd scoot
cargo build --release -p scoot -p scootctl -p scootbar

The binaries land in target/release/. For the GPU build, add the feature: cargo build --release -p scoot --features gpu-scanout (plus xwayland for X apps).

Terminal window
scoot --help

This prints the usage text and exits — no display needed. If it complains about a missing library, re-check the apt line above; if it says something about --headless on macOS, that is expected: on a Mac only the scootctl remote-control client builds.

Next: First session — run scoot, open a terminal, learn five keys. Or skip the piece-by-piece path: the scoot desktop is one switch plus a look.