river: a Wayland compositor that leaves window management to a separate process
[mirror] A non-monolithic Wayland compositor
At a glance
- What is it?
- river splits the compositor from the window manager and talks to any program implementing the river-window-management-v1 protocol. It is aimed at people who want to write a Wayland window manager without touching compositor internals.
- Who is it for?
- Adopt river if you want to write a Wayland window manager in a language of your choice, or if you want to hot-swap window managers without restarting your session. Skip it if you want a ready-made tiling setup out of the box; the README points at river-classic for the old dynamic tiling version and at the wiki's list of compatible window managers for the current ones.
- Can I use it commercially?
- Not without permission. GitHub finds no licence file in the repository, and without a licence all rights are reserved by default: you may read the code but not reuse it. Check the README, or ask the authors, before using it.
- Is it still maintained?
- Yes. The repository last received commits 8 days ago.
- What is it written in?
- Mainly Zig, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 1, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The problem river solves: window management trapped inside the compositor
In most Wayland compositors the compositor and the window manager are the same program. Layout logic, keybindings, focus policy and rendering all live in one codebase, usually written in C or another systems language. Anyone who wants a different tiling behaviour has to fork the whole compositor or write a patch against internals that were never designed as a public interface.
river takes the opposite position. The README states that river "does not combine the compositor and window manager into one program" and that users can choose any window manager implementing the river-window-management-v1 protocol. Window position and size, pointer and keyboard bindings, focus management, window decorations and desktop shell graphics all move out of the compositor and into that separate process.
The audience follows from that split. The stated motivation is to lower the barrier to entry for writing a Wayland window manager, and to allow those window managers to be written in high-level garbage-collected languages without affecting compositor performance and latency. If you have ever wanted to prototype a layout algorithm in a language with a garbage collector, this is the design that makes it possible. If you want a finished desktop you configure and forget, the split is extra moving parts you did not ask for.
How the split works: a stable protocol between compositor and window manager
river keeps the parts that need to be close to the display server: rendering, input plumbing, Xwayland support, and the Wayland protocol extensions it exposes to clients. Everything above that is policy, and policy crosses a process boundary through river-window-management-v1.
The README describes the protocol and river's other protocol extensions as stable, with an explicit promise: "We do not break window managers." That is the contract that makes a separate window manager viable as a long-lived project rather than a toy. A window manager written against the protocol should keep working across river releases.
Because the window manager is a separate process, it can be replaced while river keeps running. The README lists hot-swapping window managers without restarting the compositor and all Wayland programs as a feature. That is a genuine architectural difference, not a configuration convenience: your terminal, editor and browser stay alive while the layout engine underneath them changes.
The repository layout reflects the same separation. There is a protocol/ directory for the protocol definitions, a river/ directory for the compositor itself, and a common/ directory for code shared between them. ARCHITECTURE.md is the file the README points to for an overview of the code base, and it is the right place to start reading if you intend to modify the compositor rather than write a window manager. For window manager authors, the protocol documentation is hosted separately, and the tinyrwm repository is given as an example implementation.
Building and installing river from source
The README does not describe a package manager install. It documents a source build, and it points packagers at PACKAGING.md. The dependency list is explicit and version-pinned: Zig 0.16, wayland, wayland-protocols, wlroots 0.20, xkbcommon 1.12 or newer, libevdev, pixman and pkg-config. scdoc is optional but required for man page generation. The README notes that development versions are required if applicable to your distribution.
With those installed, the build command given in the README is:
zig build -Doptimize=ReleaseSafe --prefix ~/.local installThis compiles river with the ReleaseSafe optimization mode and installs it under ~/.local. Xwayland support is off unless you pass the additional option:
zig build -Doptimize=ReleaseSafe -Dxwayland --prefix ~/.local installRun `zig build -h` to see the full option list, as the README instructs.
For a first run, river can be started nested inside an existing X11 or Wayland session, or directly from a tty using KMS/DRM. Either way the command is simply `river`. On startup river looks for an executable file at `$XDG_CONFIG_HOME/river/init`, falling back to `~/.config/river/init` when `$XDG_CONFIG_HOME` is unset. The README says this executable is usually a shell script that starts the user's window manager and any other long-running programs. That script is the first thing to write: without it, river starts with no window manager attached, and the README's usage section does not describe any built-in default layout.
Where river is the wrong tool
The most obvious limitation is that river is not a window manager. If you install it expecting tiling out of the box, you get a compositor and an init hook. The README points readers who want the old dynamic tiling behaviour at river-classic, a separate project. Current window managers are listed on the wiki, which means the practical quality of your desktop depends on a third-party project that river's own repository does not ship or maintain.
The build requirements are a second constraint. Pinning wlroots 0.20 and Zig 0.16 means river tracks two fast-moving upstreams. Distributions that ship older wlroots will not be able to build this version without updating, and Zig's pre-1.0 release cadence has historically broken build scripts between versions. The README gives no compatibility shims or fallback versions.
The project also carries a strict no LLM and no AI policy covering all contributions, including bug reports and comments on the issue tracker. That is a real constraint on how you participate, not a footnote. If your workflow includes AI-assisted patches or issue drafting, this project is closed to it.
Finally, the release history is sparse. The most recent release listed is v0.3.0 from 2024-04-16, with v0.2.6 and v0.2.5 before it in November 2023. The last push to the repository was on 2026-09-13, so development activity is visible in the repository, but anyone who expects frequent tagged releases should look at the commit history rather than the release page before committing to it.
Compared with a monolithic wlroots compositor
The natural alternative is a monolithic compositor built on wlroots, where layout and keybindings are compiled in. In that model you configure the window manager through a config file, and changing behaviour beyond what the config exposes means patching or forking the compositor. The advantage is that everything is tested together and there is one process to debug.
river inverts the trade-off. You get a narrower compositor and a stable protocol boundary, and in exchange you accept an extra process, an init script, and a dependency on a window manager that someone else maintains. The README's stated reasons for the split are lower barrier to entry, high-level languages for window managers, hot-swapping, and diversity in window manager design. Each of those is a benefit to someone writing a window manager, and none of them is a benefit to someone who just wants windows tiled.
That asymmetry is the honest way to choose between the two approaches. If your interest is in the policy layer, river gives you a documented protocol and a stable target. If your interest is in a working desktop, a monolithic compositor asks less of you.
Licence, packaging and the cost of keeping up
The README states that river follows the REUSE Specification and that all files carry SPDX copyright and license information. The breakdown it gives is: source code under GPL-3.0-only, Wayland protocols under MIT, and the logo and documentation under CC-BY-SA-4.0. The repository has a LICENSES/ directory and a PACKAGING.md file, and the README directs packagers to the latter.
The split licensing matters for anyone embedding the protocol definitions in their own window manager. The protocol side is MIT, which is permissive; the compositor itself is GPL-3.0-only, so distributing a modified river carries the usual copyleft obligations. This is a description of what the README says, not legal advice, and the per-file SPDX headers in LICENSES/ are the authoritative source for any specific file.
Upgrade cost comes from the pinned dependencies. Moving to a new river release may mean moving to a new wlroots and a new Zig, and Zig 0.16 is the only version the README names as supported. There is no documented rollback procedure in the README, and no LTS branch is mentioned. The funding section notes that river is funded in part through the NGI0 Commons Fund, which is a statement about project funding rather than a support commitment.
Editorial conclusion
Adopt river if you want to write a Wayland window manager in a language of your choice, or if you want to hot-swap window managers without restarting your session. Skip it if you want a ready-made tiling setup out of the box; the README points at river-classic for the old dynamic tiling version and at the wiki's list of compatible window managers for the current ones. Before installing, check your distribution's wlroots version against the required 0.20 and confirm that Zig 0.16 is available, because both are hard build dependencies.
Frequently asked questions
What is river (riverwm) and how is it different from other Wayland compositors?
river is a non-monolithic Wayland compositor: it does not combine the compositor and window manager into one program. Window management policy is deferred to a separate process implementing the river-window-management-v1 protocol, so you choose which window manager runs on top of it.
How do I install river?
The README documents a source build rather than a package manager install. After installing Zig 0.16, wayland, wayland-protocols, wlroots 0.20, xkbcommon 1.12 or newer, libevdev, pixman and pkg-config, you run zig build -Doptimize=ReleaseSafe --prefix ~/.local install, adding -Dxwayland if you want Xwayland support.
Does river include a window manager?
No. river defers window position and size, pointer and keyboard bindings, focus management, window decorations and desktop shell graphics to a separate window manager implementing the river-window-management-v1 protocol. The README points to a list of compatible window managers on the wiki and to river-classic for the old dynamic tiling version.
What licence is river released under?
According to the README, river's source code is GPL-3.0-only, its Wayland protocols are MIT, and its logo and documentation are CC-BY-SA-4.0. The project follows the REUSE Specification, so individual files carry SPDX copyright and license information.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/riverwm-river)