detached f40b3c9

docs(readme): tighten the feature list to seven scannable points (#26)

* docs(readme): tighten the feature list to seven scannable points

Replace the four sub-sections and 20 bullets with one list of seven
features, each one line. Drop protocol names and minor features (vim
keys, cursor shapes, activation, headless) that the detailed sections
already cover, and stop repeating the performance path in the intro.

* docs: move desktop integration and headless guides out of the README

The README keeps the pitch, features, performance path, hardware, install
and configuration. Running commands, clipboard, X11 apps, idle, bars and
the state file move to docs/desktop.md; the headless walkthrough moves
to docs/headless.md. A Documentation section links to all three guides.

* docs(readme): keep the feature list factual

* docs(readme): plain label for the config example
commit
f40b3c940deb417be9b79d79804bcd29edd2cb19
author
bnema · · 2026-09-27 16:15 UTC
committer
GitHub · · 2026-09-27 16:15 UTC
parent
21a6d9a
signature
GPG UnverifiedB5690EEEBB952194 The key is unknown
4 files · +131 -147
M README.md +14 -146
@@ -16,45 +16,21 @@
1616
1717 ## Why NeferWL
1818
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.
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, and the compositor stays out of the way.
2020
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.
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. About 40–80 MB of RAM with two 4K monitors, and almost no CPU while the screen does not change.
2222
2323 ## Features
2424
25-### Windows and workspaces
25+- **Games.** A fullscreen window is scanned out directly, with tearing, VRR and explicit sync when the client asks for them. Steam and Wine run through xwayland-satellite. See [the performance path](#the-performance-path).
26+- **HDR.** HDR10 output on capable displays. HDR clients (games, browsers, video players) are shown at full range; SDR content is shown at a configured brightness.
27+- **Column tiling.** Up to `max-columns` windows share the screen, as in Sway; past that, columns scroll to the right, as in Niri. Limits are set per output or per workspace.
28+- **Workspaces.** Numbered workspaces are created and removed as needed. Named workspaces declare their columns (width and command); NeferWL starts the commands and places each window.
29+- **Multi-monitor.** Each output has its own workspaces. When an output is unplugged its workspaces move to another one, and return when it is plugged back. Fractional scale per output.
30+- **External clients.** No built-in bar, launcher or notifications. Waybar, fuzzel, mako, grim, cliphist, swayidle and wlr-randr work through their standard protocols. See [Desktop integration](docs/desktop.md).
31+- **Config.** One `key = value` file, reloaded on save without closing windows. A JSON state file describes outputs, workspaces and windows for scripts.
2632
27-- **Terminal first.** NeferWL opens your terminal at startup. Bars, launchers and notifications are external clients such as Waybar, fuzzel and mako.
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.
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-
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.
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
42-
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
33+Config example:
5834
5935 ```text
6036 keyboard.layout = fr
@@ -117,119 +93,11 @@ The file has one `key = value` per line, and `#` starts a comment. A missing fil
11793
11894 [docs/config.md](docs/config.md) lists every key, action and default bind. `examples/config` is a commented copy of the defaults.
11995
120-## Running commands
121-
122-`spawn <command>` binds, `startup = <command>` lines and `terminal = <command>` run one program directly, without a shell. NeferWL splits the line on spaces: the first word is the program, found in `PATH` or given as a path such as `/opt/tool/run`, and the other words are its arguments.
123-
124-```text
125-bind.ctrl+cmd+space = spawn fuzzel
126-startup = waybar
127-startup = wl-paste --watch cliphist store
128-```
129-
130-Pipes (`|`), `&&`, redirections, variables (`$HOME`), `~` and quotes have no special meaning: they reach the program as plain arguments. For those, write a script and run it:
131-
132-```sh
133-#!/bin/sh
134-# ~/.local/bin/screenshot-area: select an area, save it and copy it.
135-file="$HOME/Pictures/$(date +%F-%T).png"
136-grim -g "$(slurp)" "$file" && wl-copy < "$file"
137-```
138-
139-```text
140-bind.cmd+shift+s = spawn screenshot-area
141-```
142-
143-Make the script executable (`chmod +x`) and put it in a directory of your `PATH`, such as `~/.local/bin`. It can use any shell, including fish (`#!/usr/bin/env fish`).
144-
145-Programs started by NeferWL get `WAYLAND_DISPLAY`, `DISPLAY` (see [X11 apps](#x11-apps)) and `NEFERWL_STATE` (see below). `startup` commands run once when the session starts, so editing them takes effect at the next start.
146-
147-## Clipboard
148-
149-NeferWL supports the clipboard (`wl_data_device`), the primary selection (middle-click paste) and `ext_data_control_v1` for clipboard managers. To keep a history with [cliphist](https://github.com/sentriz/cliphist), store every copy at startup and bind a picker script:
150-
151-```text
152-startup = wl-paste --watch cliphist store
153-bind.cmd+v = spawn cliphist-pick
154-```
155-
156-`~/.local/bin/cliphist-pick`:
157-
158-```sh
159-#!/bin/sh
160-cliphist list | fuzzel --dmenu | cliphist decode | wl-copy
161-```
162-
163-Drag and drop is not supported yet.
164-
165-## X11 apps
166-
167-X11 apps such as Steam and Wine run through [xwayland-satellite](https://github.com/Supreeeme/xwayland-satellite) 0.7 or later, found in `PATH`. NeferWL opens an X11 display, sets `DISPLAY` for the programs it starts, and starts xwayland-satellite when the first X11 app connects. If xwayland-satellite exits, the next X11 app starts it again.
168-
169-```text
170-xwayland = xwayland-satellite # the default; a path also works
171-xwayland = off # no X11 display
172-```
173-
174-Do not start xwayland-satellite yourself with `startup`. Changing `xwayland` takes effect at the next start.
175-
176-## Idle and screen off
177-
178-NeferWL supports `ext_idle_notifier_v1` and `zwlr_output_power_management_v1`, so [swayidle](https://github.com/swaywm/swayidle) and [wlopm](https://git.sr.ht/~leon_plickat/wlopm) turn the screens off after a delay. A window that inhibits idle, such as a video player or a game, keeps them on.
179-
180-```text
181-startup = swayidle -w timeout 300 wlopm-off resume wlopm-on
182-```
183-
184-`swayidle` runs its commands through a shell; NeferWL does not, so the quoted form `timeout 300 'wlopm --off "*"'` does not fit on a `startup` line. Put each command in a script (see [Running commands](#running-commands)):
185-
186-```sh
187-#!/bin/sh
188-# ~/.local/bin/wlopm-off (wlopm-on is the same with --on)
189-exec wlopm --off '*'
190-```
191-
192-## Bars
193-
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.
195-
196-## State for scripts
197-
198-While it runs, NeferWL writes its state to `$XDG_RUNTIME_DIR/neferwl/<wayland socket>.json` and passes that path to the programs it starts as `NEFERWL_STATE`. The file lists:
199-
200-- every output, with its active numbered workspace, workspace count and the name of the workspace on screen;
201-- the focused output and window;
202-- every window, with its app ID, PID, output and workspace.
203-
204-```sh
205-neferwl state # the whole state as JSON
206-neferwl state output-of "$PID" # the output of that process's window, or its nearest parent's
207-```
208-
209-`output-of` finds application windows only, because a bar has no single output.
210-
211-## Try it (headless)
212-
213-The headless backend runs without a screen, for tests and quick checks:
214-
215-```sh
216-neferwl --backend=headless --screenshot /tmp/neferwl-shots
217-WAYLAND_DISPLAY=<name from the log> foot
218-```
219-
220-Screenshots through `grim` are verified with `zwlr_screencopy_v1` and `ext_image_copy_capture_v1`. The cursor is not included in captures: `overlay_cursor` and `paint_cursors` are ignored. Headless screenshot files include the cursor.
221-
222-`/tmp/neferwl-shots/latest.png` shows the current frame. `--timeout 5s` stops NeferWL after 5 seconds.
223-
224-`--input <path>`, or `--input -` for stdin, plays an input script. One command per line:
225-
226-- `type <text>`
227-- `key Super+Return` (Shift, Ctrl and Alt also work, as does a bare key)
228-- `sleep 1s`
229-- `move <x> <y>` (output coordinates)
230-- `click [left|right|middle]`, `down <button>`, `up <button>`
96+## Documentation
23197
232-The headless backend does not draw the cursor on screen. After a layout change, pointer focus updates on the next move.
98+- [Configuration](docs/config.md): every key, action and default bind, and HDR.
99+- [Desktop integration](docs/desktop.md): running commands, clipboard, X11 apps, idle and screen off, bars, and the state file for scripts.
100+- [Headless mode](docs/headless.md): run without a screen, take screenshots and play input scripts.
233101
234102 ## Why not Rust?
235103
@@ -16,45 +16,21 @@
16 16
17 ## Why NeferWL17 ## Why NeferWL
18 18
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.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, and the compositor stays out of the way.
20 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.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. About 40–80 MB of RAM with two 4K monitors, and almost no CPU while the screen does not change.
22 22
23 ## Features23 ## Features
24 24
25-### Windows and workspaces25+- **Games.** A fullscreen window is scanned out directly, with tearing, VRR and explicit sync when the client asks for them. Steam and Wine run through xwayland-satellite. See [the performance path](#the-performance-path).
26+- **HDR.** HDR10 output on capable displays. HDR clients (games, browsers, video players) are shown at full range; SDR content is shown at a configured brightness.
27+- **Column tiling.** Up to `max-columns` windows share the screen, as in Sway; past that, columns scroll to the right, as in Niri. Limits are set per output or per workspace.
28+- **Workspaces.** Numbered workspaces are created and removed as needed. Named workspaces declare their columns (width and command); NeferWL starts the commands and places each window.
29+- **Multi-monitor.** Each output has its own workspaces. When an output is unplugged its workspaces move to another one, and return when it is plugged back. Fractional scale per output.
30+- **External clients.** No built-in bar, launcher or notifications. Waybar, fuzzel, mako, grim, cliphist, swayidle and wlr-randr work through their standard protocols. See [Desktop integration](docs/desktop.md).
31+- **Config.** One `key = value` file, reloaded on save without closing windows. A JSON state file describes outputs, workspaces and windows for scripts.
26 32
27-- **Terminal first.** NeferWL opens your terminal at startup. Bars, launchers and notifications are external clients such as Waybar, fuzzel and mako.33+Config example:
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.
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-
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.
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
42-
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
58 34
59 ```text35 ```text
60 keyboard.layout = fr36 keyboard.layout = fr
@@ -117,119 +93,11 @@ The file has one `key = value` per line, and `#` starts a comment. A missing fil
117 93
118 [docs/config.md](docs/config.md) lists every key, action and default bind. `examples/config` is a commented copy of the defaults.94 [docs/config.md](docs/config.md) lists every key, action and default bind. `examples/config` is a commented copy of the defaults.
119 95
120-## Running commands96+## Documentation
121-
122-`spawn <command>` binds, `startup = <command>` lines and `terminal = <command>` run one program directly, without a shell. NeferWL splits the line on spaces: the first word is the program, found in `PATH` or given as a path such as `/opt/tool/run`, and the other words are its arguments.
123-
124-```text
125-bind.ctrl+cmd+space = spawn fuzzel
126-startup = waybar
127-startup = wl-paste --watch cliphist store
128-```
129-
130-Pipes (`|`), `&&`, redirections, variables (`$HOME`), `~` and quotes have no special meaning: they reach the program as plain arguments. For those, write a script and run it:
131-
132-```sh
133-#!/bin/sh
134-# ~/.local/bin/screenshot-area: select an area, save it and copy it.
135-file="$HOME/Pictures/$(date +%F-%T).png"
136-grim -g "$(slurp)" "$file" && wl-copy < "$file"
137-```
138-
139-```text
140-bind.cmd+shift+s = spawn screenshot-area
141-```
142-
143-Make the script executable (`chmod +x`) and put it in a directory of your `PATH`, such as `~/.local/bin`. It can use any shell, including fish (`#!/usr/bin/env fish`).
144-
145-Programs started by NeferWL get `WAYLAND_DISPLAY`, `DISPLAY` (see [X11 apps](#x11-apps)) and `NEFERWL_STATE` (see below). `startup` commands run once when the session starts, so editing them takes effect at the next start.
146-
147-## Clipboard
148-
149-NeferWL supports the clipboard (`wl_data_device`), the primary selection (middle-click paste) and `ext_data_control_v1` for clipboard managers. To keep a history with [cliphist](https://github.com/sentriz/cliphist), store every copy at startup and bind a picker script:
150-
151-```text
152-startup = wl-paste --watch cliphist store
153-bind.cmd+v = spawn cliphist-pick
154-```
155-
156-`~/.local/bin/cliphist-pick`:
157-
158-```sh
159-#!/bin/sh
160-cliphist list | fuzzel --dmenu | cliphist decode | wl-copy
161-```
162-
163-Drag and drop is not supported yet.
164-
165-## X11 apps
166-
167-X11 apps such as Steam and Wine run through [xwayland-satellite](https://github.com/Supreeeme/xwayland-satellite) 0.7 or later, found in `PATH`. NeferWL opens an X11 display, sets `DISPLAY` for the programs it starts, and starts xwayland-satellite when the first X11 app connects. If xwayland-satellite exits, the next X11 app starts it again.
168-
169-```text
170-xwayland = xwayland-satellite # the default; a path also works
171-xwayland = off # no X11 display
172-```
173-
174-Do not start xwayland-satellite yourself with `startup`. Changing `xwayland` takes effect at the next start.
175-
176-## Idle and screen off
177-
178-NeferWL supports `ext_idle_notifier_v1` and `zwlr_output_power_management_v1`, so [swayidle](https://github.com/swaywm/swayidle) and [wlopm](https://git.sr.ht/~leon_plickat/wlopm) turn the screens off after a delay. A window that inhibits idle, such as a video player or a game, keeps them on.
179-
180-```text
181-startup = swayidle -w timeout 300 wlopm-off resume wlopm-on
182-```
183-
184-`swayidle` runs its commands through a shell; NeferWL does not, so the quoted form `timeout 300 'wlopm --off "*"'` does not fit on a `startup` line. Put each command in a script (see [Running commands](#running-commands)):
185-
186-```sh
187-#!/bin/sh
188-# ~/.local/bin/wlopm-off (wlopm-on is the same with --on)
189-exec wlopm --off '*'
190-```
191-
192-## Bars
193-
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.
195-
196-## State for scripts
197-
198-While it runs, NeferWL writes its state to `$XDG_RUNTIME_DIR/neferwl/<wayland socket>.json` and passes that path to the programs it starts as `NEFERWL_STATE`. The file lists:
199-
200-- every output, with its active numbered workspace, workspace count and the name of the workspace on screen;
201-- the focused output and window;
202-- every window, with its app ID, PID, output and workspace.
203-
204-```sh
205-neferwl state # the whole state as JSON
206-neferwl state output-of "$PID" # the output of that process's window, or its nearest parent's
207-```
208-
209-`output-of` finds application windows only, because a bar has no single output.
210-
211-## Try it (headless)
212-
213-The headless backend runs without a screen, for tests and quick checks:
214-
215-```sh
216-neferwl --backend=headless --screenshot /tmp/neferwl-shots
217-WAYLAND_DISPLAY=<name from the log> foot
218-```
219-
220-Screenshots through `grim` are verified with `zwlr_screencopy_v1` and `ext_image_copy_capture_v1`. The cursor is not included in captures: `overlay_cursor` and `paint_cursors` are ignored. Headless screenshot files include the cursor.
221-
222-`/tmp/neferwl-shots/latest.png` shows the current frame. `--timeout 5s` stops NeferWL after 5 seconds.
223-
224-`--input <path>`, or `--input -` for stdin, plays an input script. One command per line:
225-
226-- `type <text>`
227-- `key Super+Return` (Shift, Ctrl and Alt also work, as does a bare key)
228-- `sleep 1s`
229-- `move <x> <y>` (output coordinates)
230-- `click [left|right|middle]`, `down <button>`, `up <button>`
231 97
232-The headless backend does not draw the cursor on screen. After a layout change, pointer focus updates on the next move.98+- [Configuration](docs/config.md): every key, action and default bind, and HDR.
99+- [Desktop integration](docs/desktop.md): running commands, clipboard, X11 apps, idle and screen off, bars, and the state file for scripts.
100+- [Headless mode](docs/headless.md): run without a screen, take screenshots and play input scripts.
233 101
234 ## Why not Rust?102 ## Why not Rust?
235 103
M docs/config.md +1 -1
@@ -65,7 +65,7 @@ HDR requires DRM HDR connector properties, suitable KMS planes, and Vulkan fp16
6565 - Keys are what the active layout prints: `cmd+é` on AZERTY. Write `=`, `#` and space by name: `cmd+equal`, `cmd+numbersign`, `cmd+space`.
6666 - `code:N` is a physical key (evdev code), the same on every layout: `code:2` to `code:10` are the digit row 1 to 9.
6767 - `none` removes a default bind.
68-- `spawn <command>` runs a program without a shell; see [Running commands](../README.md#running-commands).
68+- `spawn <command>` runs a program without a shell; see [Running commands](desktop.md#running-commands).
6969
7070 ### Actions
7171
@@ -65,7 +65,7 @@ HDR requires DRM HDR connector properties, suitable KMS planes, and Vulkan fp16
65 - Keys are what the active layout prints: `cmd+é` on AZERTY. Write `=`, `#` and space by name: `cmd+equal`, `cmd+numbersign`, `cmd+space`.65 - Keys are what the active layout prints: `cmd+é` on AZERTY. Write `=`, `#` and space by name: `cmd+equal`, `cmd+numbersign`, `cmd+space`.
66 - `code:N` is a physical key (evdev code), the same on every layout: `code:2` to `code:10` are the digit row 1 to 9.66 - `code:N` is a physical key (evdev code), the same on every layout: `code:2` to `code:10` are the digit row 1 to 9.
67 - `none` removes a default bind.67 - `none` removes a default bind.
68-- `spawn <command>` runs a program without a shell; see [Running commands](../README.md#running-commands).68+- `spawn <command>` runs a program without a shell; see [Running commands](desktop.md#running-commands).
69 69
70 ### Actions70 ### Actions
71 71
A docs/desktop.md +94 -0
@@ -0,0 +1,94 @@
1+# Desktop integration
2+
3+How NeferWL runs programs and works with bars, clipboard managers, X11 apps, idle tools and scripts.
4+
5+## Running commands
6+
7+`spawn <command>` binds, `startup = <command>` lines and `terminal = <command>` run one program directly, without a shell. NeferWL splits the line on spaces: the first word is the program, found in `PATH` or given as a path such as `/opt/tool/run`, and the other words are its arguments.
8+
9+```text
10+bind.ctrl+cmd+space = spawn fuzzel
11+startup = waybar
12+startup = wl-paste --watch cliphist store
13+```
14+
15+Pipes (`|`), `&&`, redirections, variables (`$HOME`), `~` and quotes have no special meaning: they reach the program as plain arguments. For those, write a script and run it:
16+
17+```sh
18+#!/bin/sh
19+# ~/.local/bin/screenshot-area: select an area, save it and copy it.
20+file="$HOME/Pictures/$(date +%F-%T).png"
21+grim -g "$(slurp)" "$file" && wl-copy < "$file"
22+```
23+
24+```text
25+bind.cmd+shift+s = spawn screenshot-area
26+```
27+
28+Make the script executable (`chmod +x`) and put it in a directory of your `PATH`, such as `~/.local/bin`. It can use any shell, including fish (`#!/usr/bin/env fish`).
29+
30+Programs started by NeferWL get `WAYLAND_DISPLAY`, `DISPLAY` (see [X11 apps](#x11-apps)) and `NEFERWL_STATE` (see below). `startup` commands run once when the session starts, so editing them takes effect at the next start.
31+
32+## Clipboard
33+
34+NeferWL supports the clipboard (`wl_data_device`), the primary selection (middle-click paste) and `ext_data_control_v1` for clipboard managers. To keep a history with [cliphist](https://github.com/sentriz/cliphist), store every copy at startup and bind a picker script:
35+
36+```text
37+startup = wl-paste --watch cliphist store
38+bind.cmd+v = spawn cliphist-pick
39+```
40+
41+`~/.local/bin/cliphist-pick`:
42+
43+```sh
44+#!/bin/sh
45+cliphist list | fuzzel --dmenu | cliphist decode | wl-copy
46+```
47+
48+Drag and drop is not supported yet.
49+
50+## X11 apps
51+
52+X11 apps such as Steam and Wine run through [xwayland-satellite](https://github.com/Supreeeme/xwayland-satellite) 0.7 or later, found in `PATH`. NeferWL opens an X11 display, sets `DISPLAY` for the programs it starts, and starts xwayland-satellite when the first X11 app connects. If xwayland-satellite exits, the next X11 app starts it again.
53+
54+```text
55+xwayland = xwayland-satellite # the default; a path also works
56+xwayland = off # no X11 display
57+```
58+
59+Do not start xwayland-satellite yourself with `startup`. Changing `xwayland` takes effect at the next start.
60+
61+## Idle and screen off
62+
63+NeferWL supports `ext_idle_notifier_v1` and `zwlr_output_power_management_v1`, so [swayidle](https://github.com/swaywm/swayidle) and [wlopm](https://git.sr.ht/~leon_plickat/wlopm) turn the screens off after a delay. A window that inhibits idle, such as a video player or a game, keeps them on.
64+
65+```text
66+startup = swayidle -w timeout 300 wlopm-off resume wlopm-on
67+```
68+
69+`swayidle` runs its commands through a shell; NeferWL does not, so the quoted form `timeout 300 'wlopm --off "*"'` does not fit on a `startup` line. Put each command in a script (see [Running commands](#running-commands)):
70+
71+```sh
72+#!/bin/sh
73+# ~/.local/bin/wlopm-off (wlopm-on is the same with --on)
74+exec wlopm --off '*'
75+```
76+
77+## Bars
78+
79+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.
80+
81+## State for scripts
82+
83+While it runs, NeferWL writes its state to `$XDG_RUNTIME_DIR/neferwl/<wayland socket>.json` and passes that path to the programs it starts as `NEFERWL_STATE`. The file lists:
84+
85+- every output, with its active numbered workspace, workspace count and the name of the workspace on screen;
86+- the focused output and window;
87+- every window, with its app ID, PID, output and workspace.
88+
89+```sh
90+neferwl state # the whole state as JSON
91+neferwl state output-of "$PID" # the output of that process's window, or its nearest parent's
92+```
93+
94+`output-of` finds application windows only, because a bar has no single output.
@@ -0,0 +1,94 @@
1+# Desktop integration
2+
3+How NeferWL runs programs and works with bars, clipboard managers, X11 apps, idle tools and scripts.
4+
5+## Running commands
6+
7+`spawn <command>` binds, `startup = <command>` lines and `terminal = <command>` run one program directly, without a shell. NeferWL splits the line on spaces: the first word is the program, found in `PATH` or given as a path such as `/opt/tool/run`, and the other words are its arguments.
8+
9+```text
10+bind.ctrl+cmd+space = spawn fuzzel
11+startup = waybar
12+startup = wl-paste --watch cliphist store
13+```
14+
15+Pipes (`|`), `&&`, redirections, variables (`$HOME`), `~` and quotes have no special meaning: they reach the program as plain arguments. For those, write a script and run it:
16+
17+```sh
18+#!/bin/sh
19+# ~/.local/bin/screenshot-area: select an area, save it and copy it.
20+file="$HOME/Pictures/$(date +%F-%T).png"
21+grim -g "$(slurp)" "$file" && wl-copy < "$file"
22+```
23+
24+```text
25+bind.cmd+shift+s = spawn screenshot-area
26+```
27+
28+Make the script executable (`chmod +x`) and put it in a directory of your `PATH`, such as `~/.local/bin`. It can use any shell, including fish (`#!/usr/bin/env fish`).
29+
30+Programs started by NeferWL get `WAYLAND_DISPLAY`, `DISPLAY` (see [X11 apps](#x11-apps)) and `NEFERWL_STATE` (see below). `startup` commands run once when the session starts, so editing them takes effect at the next start.
31+
32+## Clipboard
33+
34+NeferWL supports the clipboard (`wl_data_device`), the primary selection (middle-click paste) and `ext_data_control_v1` for clipboard managers. To keep a history with [cliphist](https://github.com/sentriz/cliphist), store every copy at startup and bind a picker script:
35+
36+```text
37+startup = wl-paste --watch cliphist store
38+bind.cmd+v = spawn cliphist-pick
39+```
40+
41+`~/.local/bin/cliphist-pick`:
42+
43+```sh
44+#!/bin/sh
45+cliphist list | fuzzel --dmenu | cliphist decode | wl-copy
46+```
47+
48+Drag and drop is not supported yet.
49+
50+## X11 apps
51+
52+X11 apps such as Steam and Wine run through [xwayland-satellite](https://github.com/Supreeeme/xwayland-satellite) 0.7 or later, found in `PATH`. NeferWL opens an X11 display, sets `DISPLAY` for the programs it starts, and starts xwayland-satellite when the first X11 app connects. If xwayland-satellite exits, the next X11 app starts it again.
53+
54+```text
55+xwayland = xwayland-satellite # the default; a path also works
56+xwayland = off # no X11 display
57+```
58+
59+Do not start xwayland-satellite yourself with `startup`. Changing `xwayland` takes effect at the next start.
60+
61+## Idle and screen off
62+
63+NeferWL supports `ext_idle_notifier_v1` and `zwlr_output_power_management_v1`, so [swayidle](https://github.com/swaywm/swayidle) and [wlopm](https://git.sr.ht/~leon_plickat/wlopm) turn the screens off after a delay. A window that inhibits idle, such as a video player or a game, keeps them on.
64+
65+```text
66+startup = swayidle -w timeout 300 wlopm-off resume wlopm-on
67+```
68+
69+`swayidle` runs its commands through a shell; NeferWL does not, so the quoted form `timeout 300 'wlopm --off "*"'` does not fit on a `startup` line. Put each command in a script (see [Running commands](#running-commands)):
70+
71+```sh
72+#!/bin/sh
73+# ~/.local/bin/wlopm-off (wlopm-on is the same with --on)
74+exec wlopm --off '*'
75+```
76+
77+## Bars
78+
79+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.
80+
81+## State for scripts
82+
83+While it runs, NeferWL writes its state to `$XDG_RUNTIME_DIR/neferwl/<wayland socket>.json` and passes that path to the programs it starts as `NEFERWL_STATE`. The file lists:
84+
85+- every output, with its active numbered workspace, workspace count and the name of the workspace on screen;
86+- the focused output and window;
87+- every window, with its app ID, PID, output and workspace.
88+
89+```sh
90+neferwl state # the whole state as JSON
91+neferwl state output-of "$PID" # the output of that process's window, or its nearest parent's
92+```
93+
94+`output-of` finds application windows only, because a bar has no single output.
A docs/headless.md +22 -0
@@ -0,0 +1,22 @@
1+# Headless mode
2+
3+The headless backend runs without a screen, for tests and quick checks:
4+
5+```sh
6+neferwl --backend=headless --screenshot /tmp/neferwl-shots
7+WAYLAND_DISPLAY=<name from the log> foot
8+```
9+
10+Screenshots through `grim` are verified with `zwlr_screencopy_v1` and `ext_image_copy_capture_v1`. The cursor is not included in captures: `overlay_cursor` and `paint_cursors` are ignored. Headless screenshot files include the cursor.
11+
12+`/tmp/neferwl-shots/latest.png` shows the current frame. `--timeout 5s` stops NeferWL after 5 seconds.
13+
14+`--input <path>`, or `--input -` for stdin, plays an input script. One command per line:
15+
16+- `type <text>`
17+- `key Super+Return` (Shift, Ctrl and Alt also work, as does a bare key)
18+- `sleep 1s`
19+- `move <x> <y>` (output coordinates)
20+- `click [left|right|middle]`, `down <button>`, `up <button>`
21+
22+The headless backend does not draw the cursor on screen. After a layout change, pointer focus updates on the next move.
@@ -0,0 +1,22 @@
1+# Headless mode
2+
3+The headless backend runs without a screen, for tests and quick checks:
4+
5+```sh
6+neferwl --backend=headless --screenshot /tmp/neferwl-shots
7+WAYLAND_DISPLAY=<name from the log> foot
8+```
9+
10+Screenshots through `grim` are verified with `zwlr_screencopy_v1` and `ext_image_copy_capture_v1`. The cursor is not included in captures: `overlay_cursor` and `paint_cursors` are ignored. Headless screenshot files include the cursor.
11+
12+`/tmp/neferwl-shots/latest.png` shows the current frame. `--timeout 5s` stops NeferWL after 5 seconds.
13+
14+`--input <path>`, or `--input -` for stdin, plays an input script. One command per line:
15+
16+- `type <text>`
17+- `key Super+Return` (Shift, Ctrl and Alt also work, as does a bare key)
18+- `sleep 1s`
19+- `move <x> <y>` (output coordinates)
20+- `click [left|right|middle]`, `down <button>`, `up <button>`
21+
22+The headless backend does not draw the cursor on screen. After a layout change, pointer focus updates on the next move.

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