RediWM is a wlroots compositor that draws its whole shell itself: taskbar, start menu, settings, lock and login screens, notifications and OSDs, all in one process, benchmarked against labwc to stay as lean.
https://github.com/user-attachments/assets/60bc1190-694c-4fb7-b2bc-d90e5e9faa90
rediwm-dm, a small display manager.rediwm-msg), desktop icons, a file manager and an image viewer.curl -fsSL https://raw.githubusercontent.com/oxydizer/rediwm/HEAD/scripts/install.sh | sh # add `-s -- --dm` for rediwm-dm
scripts/install.sh installs the prebuilt release for your distro (Arch,
Debian, Ubuntu and Fedora on x86_64, and their derivatives): the compositor,
the apps and the exact wlroots 0.20 they were tested with, including the
window-title patch. Installing never replaces your login manager. SDDM, GDM and the
like keep working, and RediWM only appears as a session in their picker. The
rediwm-dm login manager is installed only with --dm, and even then it is
not enabled (see below).
Requirements: Zig 0.16, wlroots 0.20 (scripts/install.sh --build builds it
into a private prefix on Debian/Ubuntu, and REDIWM_PRIVATE_WLROOTS=1 does so
on Arch and Fedora), and the development files for Wayland,
wayland-protocols, xkbcommon, pixman, FreeType, HarfBuzz, Fontconfig,
librsvg/GdkPixbuf, PangoCairo, libinput, PAM, libpulse, libpipewire-0.3, Poppler GLib,
libseccomp, libjpeg and libpng. Optional:
Xwayland, foot, brightnessctl, gio/xdg-open, git (Files repository status).
Runtime portals: xdg-desktop-portal, xdg-desktop-portal-wlr for screen
sharing, and xdg-desktop-portal-gtk for fallback portals. scripts/install.sh
installs all three.
zig build run -- foot # nested in your current Wayland session
zig build -Doptimize=ReleaseSafe # for daily use and measurements
sh scripts/install-session.sh # install and restart the running session
sh scripts/install-session.sh --no-restart --dm # install only, plus rediwm-dm
Run from a checkout, scripts/install.sh builds that checkout (dependencies,
then install-session.sh with the arguments you give it).
scripts/make-release.sh builds each distro's tarball (rediwm-<distro>-x86_64.tar.gz)
in a clean container of that distro, with scripts/build-wlroots.sh's pinned.
rediwm-pdf FILE opens one PDF in a sandboxed viewer process. It requires
Landlock ABI 3 or newer and a compositor with security-context-v1 (including
RediWM); it refuses to parse a document if isolation cannot be established.
| Keys | Action |
|---|---|
| Super+Space | start menu |
| Super+T / E / B | terminal / Files / browser |
| Super+Q, Super+F, Super+M | close, fullscreen, maximize |
| Super+Shift+arrows | tile halves and quarters |
| Super+arrows | slide to the neighbouring desktop |
| Super+Ctrl+arrows | focus the window in that direction |
| Alt+Tab | window switcher |
| Super+1…5, Super+=/-/0 | window zoom |
| Super+Shift+=/-/0 | desktop zoom |
| Super+L | lock |
| Ctrl+Shift+S, Print | region / full-screen screenshot |
| Super+Z | undo the last window move or resize |
| Super+Shift+E | quit |
All bindings live in [keybinds] ("noop" disables one).
[compositor] focus_zoom = "boost", "keep", or "camera".
Window reveals ease over 320 ms, and titlebar scrolling uses the same
eased window zoom as Alt+scroll. Animation speed and reduced motion apply
to these transitions; [animations.camera_reveal] can override the pan.[compositor] window_tab_apps.
Arrow buttons and scrolling over the strip switch tabs; Alt+scroll still
zooms the window. Apps need a desktop entry with a usable launch command;
launches that only activate an existing window do not create a tab.[compositor] lock_on_suspend, on by default), and on
loginctl lock-session. RediWM doesn't lock on idle itself: run
swayidle -w timeout 300 'swaylock -f' from [[autostart]]..desktop launcher only if it is installed, owned by
root, executable, or an exact copy of an installed entry. Any other
launcher shows as the file it is until you choose Allow Launching from
its menu.rediwm-dm runs the greeter as an unprivileged user on its own VT. After
installing, disable your current display manager, sudo systemctl enable rediwm-dm and reboot; options live in /etc/rediwm/dm.conf.rediwm-files, Space opens images, PDFs and text files. Text Editor
(rediwm-editor [FILE ...]) opens text files in tabs in one window per display.
Use Ctrl+N for a new tab, Ctrl+O to open, Ctrl+S to save,
Ctrl+Shift+S for the existing Save As dialog, Ctrl+Page Up/Down to
switch tabs, Ctrl+W to close a tab, and Ctrl+F / F3 to find text.
It supports UTF-8 files up to 16 MiB, preserves BOM and line endings, and
prompts before discarding changes. Files, Images and Text Editor also run
on other Wayland compositors.Beyond xdg-shell, layer-shell and Xwayland:
| Area | Protocols | Works with |
|---|---|---|
| Displays | wlr-output-management-v1, xdg-output-v1 | wlr-randr, kanshi, nwg-displays |
| Window lists | wlr-foreign-toplevel-management-v1, ext-foreign-toplevel-list-v1 | docks, waybar, rofi/fuzzel, wlrctl |
| Capture | wlr-screencopy-v1, ext-image-copy-capture-v1 | grim, wf-recorder, OBS, xdg-desktop-portal-wlr |
| Locking and idle | ext-session-lock-v1, ext-idle-notify-v1, idle-inhibit-v1 | swaylock, gtklock, swayidle |
| Remote input | virtual-pointer-v1, virtual-keyboard-v1 | wayvnc, KDE Connect, wtype |
| Clipboard | wlr-data-control-v1, ext-data-control-v1, primary selection | wl-clipboard |
| Input | text-input-v3, input-method-v2, relative-pointer-v1, pointer-constraints-v1, keyboard-shortcuts-inhibit-v1, pointer-gestures-v1, cursor-shape-v1 | fcitx5, IBus, games, virt-manager |
| Workspace | ext-workspace-v1 | one active Canvas workspace shared by all outputs |
| Window metadata | xdg-toplevel-tag-v1, content-type-v1, xdg-activation-v1 | window rules, content hints, authorized activation |
| Colour | color-management-v1, color-representation-v1 | renderer-supported colour spaces and pixel representations |
| Presentation | tearing-control-v1, drm-lease-v1 | opt-in fullscreen tearing, DRM-connected VR headsets |
| Rendering | fractional-scale-v1, viewporter, single-pixel-buffer-v1, linux-dmabuf-v1, linux-drm-syncobj-v1, presentation-time |
$XDG_CONFIG_HOME/rediwm/config.toml (REDIWM_CONFIG overrides) is written with
commented defaults on first run and reloads on save; a parse error keeps the
previous config. Sections: [theme], [input], [input_method],
[compositor], [region], [idle], [night_light], [notifications], [desktop],
[polkit], [ipc], [keybinds], [[outputs]], [[autostart]],
[[window_rules]], [[notification_rules]] and [[sandbox_allow]].
The .toml files use a line-based TOML subset, including standalone theme
files.
Window rules match by globs; for each property the last matching rule wins:
[[window_rules]]
app_id = ["firefox", "chromium"]
title = "*Picture-in-Picture*"
opacity = 0.9
skip_taskbar = true
focus = false
Matchers: app_id, title, x11_class, x11_instance, backend, dialog
and exclude_*. Properties: output, x, y, center, width, height,
maximized, fullscreen, focus, depth, opacity, decorations,
skip_taskbar.
The socket is $XDG_RUNTIME_DIR/rediwm-<WAYLAND_DISPLAY>.sock (or
REDIWM_SOCKET), in a private directory only. rediwm-msg wraps it
(rediwm-msg outputs, output-config DP-1 --scale 1.5, notifications, …);
src/ipc/protocol.zig is the reference. Synthetic input and pixel reads need
[ipc] automation = true (or REDIWM_IPC_AUTOMATION=1), and everything is
refused while locked.
IPC v1 is UTF-8 JSON, one request and one response per newline. Every request uses this envelope (command names are case-sensitive snake_case):
{"version":1,"id":1,"command":"windows"}
{"version":1,"id":2,"command":"move_cursor","params":{"x":100,"y":200}}
Settings and desktop inspection also work without opening Settings:
| Query/action | Parameters and behavior |
|---|---|
get_services | System services, raw systemd state, activation times (activation_us) and total boot_us. First requests may report loading/analyzing; unavailable times are null. |
set_service_mode | service, mode: on, disabled, or on-demand. Changes boot policy without starting/stopping the unit. on-demand requires an existing activation trigger and disables boot enablement; it does not create or enable a socket/timer. deferred returns UnsupportedServiceMode. Static/masked units are read-only. |
get_sounds | Configured theme and registered events, including enabled/available flags and resolved files. |
play_sound | event: a name from get_sounds. Queues an enabled, available event using /usr/bin/paplay; returns an accepted playback PID, not a playback-completion guarantee. |
get_wallpaper | Configured selection, resolved and displayed paths, dimensions, loading and failure/fallback status. |
set_wallpaper | path: wallpaper name or file path; "" restores the bundled default. Decode is asynchronous; inspect get_wallpaper for completion/fallback. |
get_theme | Effective theme tokens, theme file path (null for inline configuration), and dark-mode preference. Colors are straight RGBA arrays in 0–1; null optional tokens use the UI's automatic defaults. |
set_accent_color | color: #RRGGBB or #RRGGBBAA; updates live shell decorations and widgets. |
get_processes | Window-owning app processes grouped by PID, with window IDs, RSS bytes and CPU sampled for approximately 200 ms on a worker. 100% means one logical CPU; this excludes background processes and app child-process aggregation. Missing/exited processes have null usage. No idle sampling. |
set_night_light | Optional enabled and temperature (1700–10000 K); at least one required. Enabling follows the configured schedule. |
RediWM's own code is dual-licensed under either of
at your option. Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in RediWM by you, as defined in the Apache-2.0 license, shall be dual-licensed as above, without any additional terms or conditions.
Bundled third-party assets keep their own licenses: the fonts under
assets/fonts (SIL OFL 1.1) and the cursors under assets/cursors (CC BY-SA 4.0).
RediWM is a wlroots compositor that draws its whole shell itself: taskbar, start menu, settings, lock and login screens, notifications and OSDs, all in one process, benchmarked against labwc to stay as lean.
https://github.com/user-attachments/assets/60bc1190-694c-4fb7-b2bc-d90e5e9faa90
rediwm-dm, a small display manager.rediwm-msg), desktop icons, a file manager and an image viewer.curl -fsSL https://raw.githubusercontent.com/oxydizer/rediwm/HEAD/scripts/install.sh | sh # add `-s -- --dm` for rediwm-dm
scripts/install.sh installs the prebuilt release for your distro (Arch,
Debian, Ubuntu and Fedora on x86_64, and their derivatives): the compositor,
the apps and the exact wlroots 0.20 they were tested with, including the
window-title patch. Installing never replaces your login manager. SDDM, GDM and the
like keep working, and RediWM only appears as a session in their picker. The
rediwm-dm login manager is installed only with --dm, and even then it is
not enabled (see below).
Requirements: Zig 0.16, wlroots 0.20 (scripts/install.sh --build builds it
into a private prefix on Debian/Ubuntu, and REDIWM_PRIVATE_WLROOTS=1 does so
on Arch and Fedora), and the development files for Wayland,
wayland-protocols, xkbcommon, pixman, FreeType, HarfBuzz, Fontconfig,
librsvg/GdkPixbuf, PangoCairo, libinput, PAM, libpulse, libpipewire-0.3, Poppler GLib,
libseccomp, libjpeg and libpng. Optional:
Xwayland, foot, brightnessctl, gio/xdg-open, git (Files repository status).
Runtime portals: xdg-desktop-portal, xdg-desktop-portal-wlr for screen
sharing, and xdg-desktop-portal-gtk for fallback portals. scripts/install.sh
installs all three.
zig build run -- foot # nested in your current Wayland session
zig build -Doptimize=ReleaseSafe # for daily use and measurements
sh scripts/install-session.sh # install and restart the running session
sh scripts/install-session.sh --no-restart --dm # install only, plus rediwm-dm
Run from a checkout, scripts/install.sh builds that checkout (dependencies,
then install-session.sh with the arguments you give it).
scripts/make-release.sh builds each distro's tarball (rediwm-<distro>-x86_64.tar.gz)
in a clean container of that distro, with scripts/build-wlroots.sh's pinned.
rediwm-pdf FILE opens one PDF in a sandboxed viewer process. It requires
Landlock ABI 3 or newer and a compositor with security-context-v1 (including
RediWM); it refuses to parse a document if isolation cannot be established.
| Keys | Action |
|---|---|
| Super+Space | start menu |
| Super+T / E / B | terminal / Files / browser |
| Super+Q, Super+F, Super+M | close, fullscreen, maximize |
| Super+Shift+arrows | tile halves and quarters |
| Super+arrows | slide to the neighbouring desktop |
| Super+Ctrl+arrows | focus the window in that direction |
| Alt+Tab | window switcher |
| Super+1…5, Super+=/-/0 | window zoom |
| Super+Shift+=/-/0 | desktop zoom |
| Super+L | lock |
| Ctrl+Shift+S, Print | region / full-screen screenshot |
| Super+Z | undo the last window move or resize |
| Super+Shift+E | quit |
All bindings live in [keybinds] ("noop" disables one).
[compositor] focus_zoom = "boost", "keep", or "camera".
Window reveals ease over 320 ms, and titlebar scrolling uses the same
eased window zoom as Alt+scroll. Animation speed and reduced motion apply
to these transitions; [animations.camera_reveal] can override the pan.[compositor] window_tab_apps.
Arrow buttons and scrolling over the strip switch tabs; Alt+scroll still
zooms the window. Apps need a desktop entry with a usable launch command;
launches that only activate an existing window do not create a tab.[compositor] lock_on_suspend, on by default), and on
loginctl lock-session. RediWM doesn't lock on idle itself: run
swayidle -w timeout 300 'swaylock -f' from [[autostart]]..desktop launcher only if it is installed, owned by
root, executable, or an exact copy of an installed entry. Any other
launcher shows as the file it is until you choose Allow Launching from
its menu.rediwm-dm runs the greeter as an unprivileged user on its own VT. After
installing, disable your current display manager, sudo systemctl enable rediwm-dm and reboot; options live in /etc/rediwm/dm.conf.rediwm-files, Space opens images, PDFs and text files. Text Editor
(rediwm-editor [FILE ...]) opens text files in tabs in one window per display.
Use Ctrl+N for a new tab, Ctrl+O to open, Ctrl+S to save,
Ctrl+Shift+S for the existing Save As dialog, Ctrl+Page Up/Down to
switch tabs, Ctrl+W to close a tab, and Ctrl+F / F3 to find text.
It supports UTF-8 files up to 16 MiB, preserves BOM and line endings, and
prompts before discarding changes. Files, Images and Text Editor also run
on other Wayland compositors.Beyond xdg-shell, layer-shell and Xwayland:
| Area | Protocols | Works with |
|---|---|---|
| Displays | wlr-output-management-v1, xdg-output-v1 | wlr-randr, kanshi, nwg-displays |
| Window lists | wlr-foreign-toplevel-management-v1, ext-foreign-toplevel-list-v1 | docks, waybar, rofi/fuzzel, wlrctl |
| Capture | wlr-screencopy-v1, ext-image-copy-capture-v1 | grim, wf-recorder, OBS, xdg-desktop-portal-wlr |
| Locking and idle | ext-session-lock-v1, ext-idle-notify-v1, idle-inhibit-v1 | swaylock, gtklock, swayidle |
| Remote input | virtual-pointer-v1, virtual-keyboard-v1 | wayvnc, KDE Connect, wtype |
| Clipboard | wlr-data-control-v1, ext-data-control-v1, primary selection | wl-clipboard |
| Input | text-input-v3, input-method-v2, relative-pointer-v1, pointer-constraints-v1, keyboard-shortcuts-inhibit-v1, pointer-gestures-v1, cursor-shape-v1 | fcitx5, IBus, games, virt-manager |
| Workspace | ext-workspace-v1 | one active Canvas workspace shared by all outputs |
| Window metadata | xdg-toplevel-tag-v1, content-type-v1, xdg-activation-v1 | window rules, content hints, authorized activation |
| Colour | color-management-v1, color-representation-v1 | renderer-supported colour spaces and pixel representations |
| Presentation | tearing-control-v1, drm-lease-v1 | opt-in fullscreen tearing, DRM-connected VR headsets |
| Rendering | fractional-scale-v1, viewporter, single-pixel-buffer-v1, linux-dmabuf-v1, linux-drm-syncobj-v1, presentation-time |
$XDG_CONFIG_HOME/rediwm/config.toml (REDIWM_CONFIG overrides) is written with
commented defaults on first run and reloads on save; a parse error keeps the
previous config. Sections: [theme], [input], [input_method],
[compositor], [region], [idle], [night_light], [notifications], [desktop],
[polkit], [ipc], [keybinds], [[outputs]], [[autostart]],
[[window_rules]], [[notification_rules]] and [[sandbox_allow]].
The .toml files use a line-based TOML subset, including standalone theme
files.
Window rules match by globs; for each property the last matching rule wins:
[[window_rules]]
app_id = ["firefox", "chromium"]
title = "*Picture-in-Picture*"
opacity = 0.9
skip_taskbar = true
focus = false
Matchers: app_id, title, x11_class, x11_instance, backend, dialog
and exclude_*. Properties: output, x, y, center, width, height,
maximized, fullscreen, focus, depth, opacity, decorations,
skip_taskbar.
The socket is $XDG_RUNTIME_DIR/rediwm-<WAYLAND_DISPLAY>.sock (or
REDIWM_SOCKET), in a private directory only. rediwm-msg wraps it
(rediwm-msg outputs, output-config DP-1 --scale 1.5, notifications, …);
src/ipc/protocol.zig is the reference. Synthetic input and pixel reads need
[ipc] automation = true (or REDIWM_IPC_AUTOMATION=1), and everything is
refused while locked.
IPC v1 is UTF-8 JSON, one request and one response per newline. Every request uses this envelope (command names are case-sensitive snake_case):
{"version":1,"id":1,"command":"windows"}
{"version":1,"id":2,"command":"move_cursor","params":{"x":100,"y":200}}
Settings and desktop inspection also work without opening Settings:
| Query/action | Parameters and behavior |
|---|---|
get_services | System services, raw systemd state, activation times (activation_us) and total boot_us. First requests may report loading/analyzing; unavailable times are null. |
set_service_mode | service, mode: on, disabled, or on-demand. Changes boot policy without starting/stopping the unit. on-demand requires an existing activation trigger and disables boot enablement; it does not create or enable a socket/timer. deferred returns UnsupportedServiceMode. Static/masked units are read-only. |
get_sounds | Configured theme and registered events, including enabled/available flags and resolved files. |
play_sound | event: a name from get_sounds. Queues an enabled, available event using /usr/bin/paplay; returns an accepted playback PID, not a playback-completion guarantee. |
get_wallpaper | Configured selection, resolved and displayed paths, dimensions, loading and failure/fallback status. |
set_wallpaper | path: wallpaper name or file path; "" restores the bundled default. Decode is asynchronous; inspect get_wallpaper for completion/fallback. |
get_theme | Effective theme tokens, theme file path (null for inline configuration), and dark-mode preference. Colors are straight RGBA arrays in 0–1; null optional tokens use the UI's automatic defaults. |
set_accent_color | color: #RRGGBB or #RRGGBBAA; updates live shell decorations and widgets. |
get_processes | Window-owning app processes grouped by PID, with window IDs, RSS bytes and CPU sampled for approximately 200 ms on a worker. 100% means one logical CPU; this excludes background processes and app child-process aggregation. Missing/exited processes have null usage. No idle sampling. |
set_night_light | Optional enabled and temperature (1700–10000 K); at least one required. Enabling follows the configured schedule. |
RediWM's own code is dual-licensed under either of
at your option. Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in RediWM by you, as defined in the Apache-2.0 license, shall be dual-licensed as above, without any additional terms or conditions.
Bundled third-party assets keep their own licenses: the fonts under
assets/fonts (SIL OFL 1.1) and the cursors under assets/cursors (CC BY-SA 4.0).