detached 21a6d9a

docs(readme): list features by category and rewrite the motivation (#24)

Add a Features section that lists everything NeferWL supports today
(windows and workspaces, displays, games, desktop integration), including
HDR, output management, scale persistence, ext-workspace, screencopy and
the systemd session. Rewrite Why NeferWL around performance-first design
and early protocol adoption, and drop the borrow checker paragraph.
commit
21a6d9ac7b28d8c79f844bc67a96040b1f013b13
author
bnema · · 2026-09-27 16:02 UTC
committer
GitHub · · 2026-09-27 16:02 UTC
parent
3c68abd
signature
GPG UnverifiedB5690EEEBB952194 The key is unknown
1 file · +37 -9
M README.md +37 -9
@@ -16,17 +16,45 @@
1616
1717 ## Why NeferWL
1818
19-NeferWL has no animations, themes, built-in bar or wallpaper, by design. The compositor stays small so the CPU and GPU go to your terminal and your games.
19+NeferWL exists because I wanted a compositor that puts performance first and picks up new Wayland protocols and kernel features as soon as they land. Games get the whole GPU: direct scanout, tearing, VRR, explicit sync and HDR are in from the start.
20+
21+The design is deliberately small, and it will stay small: no animations, no themes, no built-in bar or wallpaper. Anything that adds latency or work per frame is left out. NeferWL uses about 40–80 MB of RAM with two 4K monitors and almost no CPU while the screen does not change.
22+
23+## Features
24+
25+### Windows and workspaces
2026
2127 - **Terminal first.** NeferWL opens your terminal at startup. Bars, launchers and notifications are external clients such as Waybar, fuzzel and mako.
22-- **Column tiling.** Up to `max-columns` windows share the screen, as in Sway. Past that, new columns scroll to the right as in Niri, or split in a spiral with `overflow = fixed`. Each workspace can set its own rules.
28+- **Column tiling.** Up to `max-columns` windows share the screen, as in Sway. Past that, new columns scroll to the right as in Niri, or split in a spiral with `overflow = fixed`. Each monitor and workspace can set its own rules.
2329 - **Custom workspaces.** Numbered workspaces appear and disappear as you use them. Named workspaces are outside the numbered list and shown through a bind. **Slots** declare a workspace's columns (width and command): NeferWL starts the apps in the background and puts each window in its column.
30+- **Window moves.** Move a column or a single window to another workspace or monitor, stack a window into the neighbor column or pull it out, and cycle column widths.
31+- **Vim keys.** Every arrow bind has an `hjkl` twin.
32+- **Live config.** One `key = value` file. Every key applies when you save, keyboard layout included, and windows stay open. `neferwl validate-config` checks a file before you use it.
33+
34+### Displays
35+
2436 - **Multi-monitor.** Each monitor has its own workspaces. When you unplug a monitor, its workspaces move to another one; when you plug it back, they return, and your focus stays where it was.
25-- **Games.** A fullscreen game is shown without composition, with tearing and VRR when the game asks for them. Details are in [the performance path](#the-performance-path).
26-- **Low footprint.** About 40–80 MB of RAM with two 4K monitors, and almost no CPU while the screen does not change.
27-- **Live config.** One `key = value` file. Every key applies when you save, keyboard layout included, and windows stay open.
37+- **HDR.** HDR10 output on capable displays. HDR games, browsers and video players show their full range, and the desktop stays SDR at a brightness you choose. See [HDR](docs/config.md#hdr).
38+- **Scaling.** Fractional scale per output, sent to clients through `wp_fractional_scale_v1` and `wp_viewporter` so text stays sharp. Zooming with a bind saves the new scale to your config.
39+- **Output tools.** `wlr-output-management` lets tools such as wlr-randr and kanshi change modes, scale and position.
40+
41+### Games
2842
29-An example config:
43+A fullscreen game is shown without composition, with tearing and VRR when the game asks for them. Steam and Wine run through xwayland-satellite. Details are in [the performance path](#the-performance-path).
44+
45+### Desktop integration
46+
47+- **Bars.** `ext-workspace-v1` for Waybar and ironbar, plus layer shell.
48+- **Screenshots.** grim and slurp work through screencopy and image copy capture.
49+- **Clipboard.** Clipboard, primary selection and clipboard managers such as cliphist. See [Clipboard](#clipboard).
50+- **Idle.** swayidle and wlopm turn screens off; a video or a game keeps them on. See [Idle and screen off](#idle-and-screen-off).
51+- **systemd session.** The NeferWL session starts `graphical-session.target`, so bars, portals and XDG autostart start and stop with it.
52+- **Focus requests.** `xdg_activation_v1` lets a launcher or notification focus the window it opens.
53+- **Cursors and input tools.** Client cursor shapes (`wp_cursor_shape_v1`) and virtual keyboards for tools such as wtype.
54+- **Scripting.** A JSON state file lists outputs, workspaces and windows. See [State for scripts](#state-for-scripts).
55+- **Headless mode.** Runs without a screen, takes screenshots and plays input scripts, for tests and quick checks. See [Try it](#try-it-headless).
56+
57+### Example config
3058
3159 ```text
3260 keyboard.layout = fr
@@ -47,7 +75,7 @@ bind.cmd+d = workspace dev
4775
4876 The terminal command comes from `terminal`, then `$TERMINAL`, then `foot`. `terminal.auto-open = first` opens it once on the initial numbered workspace; `all` opens it on each visible empty workspace without slots, and `off` disables automatic opening. `--no-terminal` overrides automatic opening for one run; `spawn-terminal` still works. Launched programs inherit `$SHELL`, `$EDITOR`, and `$VISUAL`.
4977
50-### The performance path
78+## The performance path
5179
5280 These protocols and kernel features cut copies, waits and latency between the app and the screen:
5381
@@ -161,6 +189,8 @@ startup = swayidle -w timeout 300 wlopm-off resume wlopm-on
161189 exec wlopm --off '*'
162190 ```
163191
192+## Bars
193+
164194 NeferWL supports `ext_workspace_manager_v1` for bars such as Waybar 0.13+ (`ext/workspaces`) and ironbar. Bars receive workspace updates and can switch workspaces without polling.
165195
166196 ## State for scripts
@@ -212,8 +242,6 @@ Most Wayland compositors are written in C (wlroots, Sway, Mutter), C++ (KWin, Hy
212242
213243 I like bringing more tools to the Go ecosystem. NeferWL grew its own libraries along the way, [purego-libwayland](https://github.com/bnema/purego-libwayland), [purego-vulkan](https://github.com/bnema/purego-vulkan) and [wlturbo](https://github.com/bnema/wlturbo), and other Go projects can use them.
214244
215-Go has no borrow checker, so the compiler does not catch memory and concurrency mistakes as Rust's does. NeferWL compensates with strict ownership (one goroutine owns each piece of state), the race detector on every test run, and protocol tests against real Wayland clients.
216-
217245 ## Developing the bindings
218246
219247 NeferWL uses tagged releases of [purego-libwayland](https://github.com/bnema/purego-libwayland) and [purego-vulkan](https://github.com/bnema/purego-vulkan). To change a binding and NeferWL together, clone the binding next to NeferWL and use a Go workspace, which is not committed:
@@ -16,17 +16,45 @@
16 16
17 ## Why NeferWL17 ## Why NeferWL
18 18
19-NeferWL has no animations, themes, built-in bar or wallpaper, by design. The compositor stays small so the CPU and GPU go to your terminal and your games.19+NeferWL exists because I wanted a compositor that puts performance first and picks up new Wayland protocols and kernel features as soon as they land. Games get the whole GPU: direct scanout, tearing, VRR, explicit sync and HDR are in from the start.
20+
21+The design is deliberately small, and it will stay small: no animations, no themes, no built-in bar or wallpaper. Anything that adds latency or work per frame is left out. NeferWL uses about 40–80 MB of RAM with two 4K monitors and almost no CPU while the screen does not change.
22+
23+## Features
24+
25+### Windows and workspaces
20 26
21 - **Terminal first.** NeferWL opens your terminal at startup. Bars, launchers and notifications are external clients such as Waybar, fuzzel and mako.27 - **Terminal first.** NeferWL opens your terminal at startup. Bars, launchers and notifications are external clients such as Waybar, fuzzel and mako.
22-- **Column tiling.** Up to `max-columns` windows share the screen, as in Sway. Past that, new columns scroll to the right as in Niri, or split in a spiral with `overflow = fixed`. Each workspace can set its own rules.28+- **Column tiling.** Up to `max-columns` windows share the screen, as in Sway. Past that, new columns scroll to the right as in Niri, or split in a spiral with `overflow = fixed`. Each monitor and workspace can set its own rules.
23 - **Custom workspaces.** Numbered workspaces appear and disappear as you use them. Named workspaces are outside the numbered list and shown through a bind. **Slots** declare a workspace's columns (width and command): NeferWL starts the apps in the background and puts each window in its column.29 - **Custom workspaces.** Numbered workspaces appear and disappear as you use them. Named workspaces are outside the numbered list and shown through a bind. **Slots** declare a workspace's columns (width and command): NeferWL starts the apps in the background and puts each window in its column.
30+- **Window moves.** Move a column or a single window to another workspace or monitor, stack a window into the neighbor column or pull it out, and cycle column widths.
31+- **Vim keys.** Every arrow bind has an `hjkl` twin.
32+- **Live config.** One `key = value` file. Every key applies when you save, keyboard layout included, and windows stay open. `neferwl validate-config` checks a file before you use it.
33+
34+### Displays
35+
24 - **Multi-monitor.** Each monitor has its own workspaces. When you unplug a monitor, its workspaces move to another one; when you plug it back, they return, and your focus stays where it was.36 - **Multi-monitor.** Each monitor has its own workspaces. When you unplug a monitor, its workspaces move to another one; when you plug it back, they return, and your focus stays where it was.
25-- **Games.** A fullscreen game is shown without composition, with tearing and VRR when the game asks for them. Details are in [the performance path](#the-performance-path).37+- **HDR.** HDR10 output on capable displays. HDR games, browsers and video players show their full range, and the desktop stays SDR at a brightness you choose. See [HDR](docs/config.md#hdr).
26-- **Low footprint.** About 40–80 MB of RAM with two 4K monitors, and almost no CPU while the screen does not change.38+- **Scaling.** Fractional scale per output, sent to clients through `wp_fractional_scale_v1` and `wp_viewporter` so text stays sharp. Zooming with a bind saves the new scale to your config.
27-- **Live config.** One `key = value` file. Every key applies when you save, keyboard layout included, and windows stay open.39+- **Output tools.** `wlr-output-management` lets tools such as wlr-randr and kanshi change modes, scale and position.
40+
41+### Games
28 42
29-An example config:43+A fullscreen game is shown without composition, with tearing and VRR when the game asks for them. Steam and Wine run through xwayland-satellite. Details are in [the performance path](#the-performance-path).
44+
45+### Desktop integration
46+
47+- **Bars.** `ext-workspace-v1` for Waybar and ironbar, plus layer shell.
48+- **Screenshots.** grim and slurp work through screencopy and image copy capture.
49+- **Clipboard.** Clipboard, primary selection and clipboard managers such as cliphist. See [Clipboard](#clipboard).
50+- **Idle.** swayidle and wlopm turn screens off; a video or a game keeps them on. See [Idle and screen off](#idle-and-screen-off).
51+- **systemd session.** The NeferWL session starts `graphical-session.target`, so bars, portals and XDG autostart start and stop with it.
52+- **Focus requests.** `xdg_activation_v1` lets a launcher or notification focus the window it opens.
53+- **Cursors and input tools.** Client cursor shapes (`wp_cursor_shape_v1`) and virtual keyboards for tools such as wtype.
54+- **Scripting.** A JSON state file lists outputs, workspaces and windows. See [State for scripts](#state-for-scripts).
55+- **Headless mode.** Runs without a screen, takes screenshots and plays input scripts, for tests and quick checks. See [Try it](#try-it-headless).
56+
57+### Example config
30 58
31 ```text59 ```text
32 keyboard.layout = fr60 keyboard.layout = fr
@@ -47,7 +75,7 @@ bind.cmd+d = workspace dev
47 75
48 The terminal command comes from `terminal`, then `$TERMINAL`, then `foot`. `terminal.auto-open = first` opens it once on the initial numbered workspace; `all` opens it on each visible empty workspace without slots, and `off` disables automatic opening. `--no-terminal` overrides automatic opening for one run; `spawn-terminal` still works. Launched programs inherit `$SHELL`, `$EDITOR`, and `$VISUAL`.76 The terminal command comes from `terminal`, then `$TERMINAL`, then `foot`. `terminal.auto-open = first` opens it once on the initial numbered workspace; `all` opens it on each visible empty workspace without slots, and `off` disables automatic opening. `--no-terminal` overrides automatic opening for one run; `spawn-terminal` still works. Launched programs inherit `$SHELL`, `$EDITOR`, and `$VISUAL`.
49 77
50-### The performance path78+## The performance path
51 79
52 These protocols and kernel features cut copies, waits and latency between the app and the screen:80 These protocols and kernel features cut copies, waits and latency between the app and the screen:
53 81
@@ -161,6 +189,8 @@ startup = swayidle -w timeout 300 wlopm-off resume wlopm-on
161 exec wlopm --off '*'189 exec wlopm --off '*'
162 ```190 ```
163 191
192+## Bars
193+
164 NeferWL supports `ext_workspace_manager_v1` for bars such as Waybar 0.13+ (`ext/workspaces`) and ironbar. Bars receive workspace updates and can switch workspaces without polling.194 NeferWL supports `ext_workspace_manager_v1` for bars such as Waybar 0.13+ (`ext/workspaces`) and ironbar. Bars receive workspace updates and can switch workspaces without polling.
165 195
166 ## State for scripts196 ## State for scripts
@@ -212,8 +242,6 @@ Most Wayland compositors are written in C (wlroots, Sway, Mutter), C++ (KWin, Hy
212 242
213 I like bringing more tools to the Go ecosystem. NeferWL grew its own libraries along the way, [purego-libwayland](https://github.com/bnema/purego-libwayland), [purego-vulkan](https://github.com/bnema/purego-vulkan) and [wlturbo](https://github.com/bnema/wlturbo), and other Go projects can use them.243 I like bringing more tools to the Go ecosystem. NeferWL grew its own libraries along the way, [purego-libwayland](https://github.com/bnema/purego-libwayland), [purego-vulkan](https://github.com/bnema/purego-vulkan) and [wlturbo](https://github.com/bnema/wlturbo), and other Go projects can use them.
214 244
215-Go has no borrow checker, so the compiler does not catch memory and concurrency mistakes as Rust's does. NeferWL compensates with strict ownership (one goroutine owns each piece of state), the race detector on every test run, and protocol tests against real Wayland clients.
216-
217 ## Developing the bindings245 ## Developing the bindings
218 246
219 NeferWL uses tagged releases of [purego-libwayland](https://github.com/bnema/purego-libwayland) and [purego-vulkan](https://github.com/bnema/purego-vulkan). To change a binding and NeferWL together, clone the binding next to NeferWL and use a Go workspace, which is not committed:247 NeferWL uses tagged releases of [purego-libwayland](https://github.com/bnema/purego-libwayland) and [purego-vulkan](https://github.com/bnema/purego-vulkan). To change a binding and NeferWL together, clone the binding next to NeferWL and use a Go workspace, which is not committed:

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 23

Tags 10

↑↓ moveenter openesc close