river Classic

river classic
is a wlroots-based Wayland dynamic tiling compositor, inspired by, but not based on dwm, xmonad and bspwm. Configuration is by an external executable file. It is the old branch of the now non-monolithic compositor
river
Its declared design goals are:
Simple and predictable behavior, river should be easy to use and have a low cognitive load.
Window management based on a stack of views and tags.
Dynamic layouts generated by external, user-written executables. A default rivertile layout generator is provided.
Scriptable configuration and control through a custom Wayland protocol and separate riverctl binary implementing it.
Installation
River Classic is
installed
with the
river-classic
package.
Starting
A single executable file is used as a configuration file. No initialisation file is set up for the user by default, so no keybindings or default applications are available until an init file is created. Note that this includes the exit keybinding, so set up in tty or another desktop environment before running river.
An example config init file is available in
/usr/share/river/example/
.
Copy this as
~/.config/river/init
and ensure it is
executable
.
Manually
Enter
river
(exits to tty with user still logged in) or
exec river
(more securely exits to tty with user logged out)
From TTY
River can be autostarted in a similar manner to
startx
, by setting up the environment variable checks in
.bash_profile
or the equivalent file for other shells. See
Xinit#Autostart X at login
, replacing
$DISPLAY
with
$WAYLAND_DISPLAY
, and running
exec river
.
Display manager
River does not officially support display managers but many will work with no or minimal effort. A session entry is installed by default in
/usr/share/wayland-sessions/
.
Configuration
The configuration file can be a shell script or executable program, comprising a list of
riverctl
individual commands which define key bindings, input settings and window rules. It is executed once at start-up but can be re-run like any other shell script (consider the effects of duplicating any autostarted spawned actions).
Each setting can also be run individually by simply running the relevant riverctl line in a terminal. This allows temporary override of the init settings, dynamic updates and testing new settings.
For example, to map the shortcut
Super+PrtSc
to take a screenshot with the application
grim
and display a temporary
desktop notification
:
riverctl map normal Super Print spawn "grim && notify-send -t 2000 'Screenshot taken'"
The
spawn
command can launch any application or script but expects a single word argument. Quote any longer expressions.
Keyboard layout
riverctl keyboard-layout gb
Multiple layouts can be entered as a comma-separated list, e.g.
gb,fr
.
Variables and other shell constructs can be used:
mod='Mod4'
,
set term foot
, etc, as per your shell.
Touchpad examples
Certain touchpad behaviour and focus preferences are available.
riverctl input pointer-2-7-SynPS/2_Synaptics_TouchPad tap enabled
riverctl focus-follows-cursor normal
Exact keyboard, mouse and touchpad models for use in these settings can be identified using:
riverctl list-inputs
Window rules
It is sometimes desirable to set certain windows to be non-tiling by default. Floating windows can be defined by class or title:
riverctl rule-add -app-id 'galculator' float
riverctl rule-add -app-id 'thunar' float       # make all Thunar windows floating
riverctl rule-add -app-id 'thunar' -title '* - Thunar' no-float  # except main window
Usage
Autostart
Use
riverctl spawn
without a keybinding to launch any executable at startup, for example:
riverctl spawn "i3-battery-popup -n -m 'Battery Low!'"
Tips and tricks
Scratchpads
River does not define any scratchpads by default, but these can be set up on any tag beyond the default 0-9. First, define the tag number, then the key mapping to move an application to the scratchpad tag and toggle its appearance, and, finally, prevent new windows being assigned to the scratchpad.
scratch_tag=$((1 << 20 ))

riverctl map normal Super P toggle-focused-tags ${scratch_tag}		# toggle the scratchpad
riverctl map normal Super+Shift P set-view-tags ${scratch_tag}		# send windows to the scratchpad

# Set spawn tagmask to ensure new windows do not have the scratchpad tag unless explicitly set.
all_but_scratch_tag=$(( ((1 << 32) - 1) ^ $scratch_tag ))
riverctl spawn-tagmask ${all_but_scratch_tag}
Modes
River supports modes for key mapping, which allows for reuse of mappings, and combinations of fewer keys. There are two default modes of 'normal' and 'locked' (defining allowed key mappings when the screen is locked).
Custom modes can be added. Eg. if floating windows are rarely used, the key mapping to manipulate those windows can be defined in a 'float' mode. Entry and exit key mappings for the mode are set as the first and last mappings, with other mapping between these.
riverctl declare-mode float
riverctl map normal Super R enter-mode float		# Super+R to enter float mode

### Floating window mappings but note that these also apply to tiled windows.
#
# Super {Arrows} to move views
  riverctl map float Super Left move left 100
  riverctl map float Super Down move down 100
  riverctl map float Super Up move up 100
  riverctl map float Super Right move right 100

# Alt+{arrows} to snap views to screen edges
  riverctl map float Alt Left snap left
  riverctl map float Alt Down snap down
  riverctl map float Alt Up snap up
  riverctl map float Alt Right snap right

# Shift+{arrows} to resize views
  riverctl map float Shift Left resize horizontal -100
  riverctl map float Shift Down resize vertical 100
  riverctl map float Shift Up resize vertical -100
  riverctl map float Shift Right resize horizontal 100

riverctl map float None Escape enter-mode normal	# Escape to exit float mode and return to normal mode
Note that floating window modifiers also work on tiled windows, making them floating and giving potentially unpredictable layouts.
External tools
In common with many other Wayland minimalist tiling clients, other tools are not included. Example external bars, screenshot tools, launchers, etc. are listed in the
River wiki
, including several with River-specific functionality.
Troubleshooting
Screencasting
If Screencasting is not working with river, check if the needed
environment variables
are properly set for systemd:
$ systemctl --user show-environment
You should find something like:
WAYLAND_DISPLAY=wayland-1
XDG_CURRENT_DESKTOP=river
If any of these variables are not set, you may add this to your
.config/river/init
:
systemctl --user import-environment WAYLAND_DISPLAY XDG_CURRENT_DESKTOP
dbus-update-activation-environment --systemd WAYLAND_DISPLAY XDG_CURRENT_DESKTOP=river
systemctl --user restart xdg-desktop-portal
If you need further troubleshooting, try to:
Make sure
XDG Desktop Portal
services are running:
$ systemctl --user status xdg-desktop-portal.service
$ systemctl --user status xdg-desktop-portal-wlr.service
Stop the
xdg-desktop-portal.service
and run it manually to see if it works:
$ systemctl --user stop xdg-desktop-portal
$ XDG_CURRENT_DESKTOP=river /usr/lib/xdg-desktop-portal
Test it using
Mozilla WebRTC test
Note
Contrary to what you may find in older posts in the internet, it is not necessary to install
pipewire-media-session
, since
wireplumber
is working just fine now.
See also
River Codeberg repository
River wiki
Developer set-up blog post