nixscroll

A scrolling column of windows, declared instead of hand-edited.

A planned home-manager module around scroll — a sway fork that trades i3-style fixed workspaces for a niri-style infinite scrolling, PaperWM column layout: generate a real ~/.config/scroll/config from typed options instead of hand-edited config, with a planned software-rendering profile for machines with no GPU to speak of. Same contract as the rest of this family: config only, no packages.

Status: pre-alpha, design stage — no module exists yet

!

No line of this has touched a running scroll session yet

Unlike nixniri, which is moving already-running code out of nixdesktop, nixscroll starts from zero: nixdesktop never supported scroll, so there is no existing module to extract. Everything described on this page is the intended option surface, not yet verified against a live compositor. Treat it as a design document, not a changelog.

!

The split this repo exists to test

nixdesktop's shared policy and chrome layer (role policy, waybar, mako, swaylock, nwg-bar, eww, the idle/lock service) was written against niri first. Whether that layer is actually compositor-neutral, and not just designed with that intention, only gets settled once a second compositor plugs into it for real — that's the actual job this repo exists to do, not a side effect of it.

!

Packaging is explicitly out of scope

scroll isn't in nixpkgs. Consumers currently reach it through the community package flake scroll-flake. nixscroll won't declare that as its own flake input, for the same reason nixdesktop keeps noctalia out of its inputs: a flake input is fetched on every evaluation, so bundling a whole compositor-packaging flake would put it in the closure of every consumer — including anyone who already has scroll installed some other way.

What it will generate

A real sway-syntax config — not KDL

scroll is a fork of sway, so its config keeps sway/i3's classic directive syntax, not niri's KDL. Worth calling out plainly: nixscroll and nixniri do the identical job for sibling compositors, but render two structurally different file formats from two structurally different option shapes — this module can't just reuse nixniri's KDL renderer.

Installs nothing

Same contract as every config-generation module in this family: this module will assume the scroll binary already exists and never name a package or an absolute binary path itself. Getting scroll onto the box — via scroll-flake, a platform backend, or however else — is explicitly someone else's job.

Software-rendering profile

A planned opt-in profile setting whatever this fork actually needs to fall back to software rendering (llvmpipe/pixman) instead of a GPU render node — for a VM or a genuinely GPU-less box. The same instinct behind nixdesktop's CPU-side toolkit defaults, one layer further down the stack, at the renderer itself rather than the toolkit above it. Not yet measured against a real GPU-less machine — see Status.

Escape hatches, matching family convention

Planned raw-passthrough options for anything the structured surface doesn't model yet, following the same "structure for the common case, an escape hatch for everything else" pattern as nixniri's extraStartup/extraWindowRules/extraBinds/extraTopLevel.

Compositor-neutral policy stays upstream

nixdesktop keeps the role policy and the compositor-agnostic chrome — waybar, mako, swaylock, nwg-bar, eww. This repo will own exactly one thing: scroll's own config file.

Mechanism public, values private

No default will point at a specific hostname, monitor name, or personal keybind layout. Every default is meant to be a sensible one for any user — scroll's own upstream defaults where they exist, not this author's own setup.

The shape this will take

Matching nixniri's own module shape — not a tested example yet; see Status above.

1. Add the flake input

inputs.nixscroll.url = "github:julian-corbet/nixscroll-corbet-ch";

2. Import and configure

imports = [ inputs.nixscroll.homeManagerModules.scroll ];

nixscroll.scroll = {
  enable = true;
  softwareRendering = true; # no GPU on this box
};

3. Provide the binary yourself

This module never installs scroll. Add scroll-flake as your own input, or resolve it through whatever platform backend your host already uses, and import both.

Where this fits

1. Compositor config — nixscroll / nixniri

Generates the compositor's own config file. Nothing else. Doesn't know or care what bar you run, what notification daemon you have, or what a "role" is.

2. Policy + shared chrome — nixdesktop

Which roles a session wants filled (file manager, polkit agent, notification daemon, bar), plus the compositor-agnostic pieces: waybar, mako, swaylock, nwg-bar, eww, and the idle/lock systemd service. Imports whichever compositor layer(s) a machine actually uses.

3. The hub

An actual machine's own config, importing nixdesktop plus exactly one compositor layer, resolved into real installed packages by a platform backend such as nixarch.

Roadmap (planned, not yet built)

Write the actual module

home/scroll.nix doesn't exist yet. This page describes the target option surface; writing it against a real running scroll session, on real hardware, is next.

Prove the software-rendering profile

Verified against a genuine GPU-less box, not assumed from scroll's own docs — the same discipline nixremote applied to hardware video encoding before calling it a default.

Settle the packaging story

Whether a platform backend ends up wrapping scroll-flake, or a consumer always adds it directly, is genuinely open.

Prove nixdesktop's neutrality claim

A real config importing both nixdesktop and nixscroll (not nixniri) side by side, confirming the shared chrome layer doesn't secretly assume niri anywhere.