detached 95250ed

docs: add alpha warning, contributing section and docs/config.md reference

commit
95250ed440e19cc60c3d4a4be54fa471b8ab5c5b
author
brice · · 2026-09-26 16:05 UTC
parent
0b8594d
signature
GPG VerifiedCD88F9E564E0102646FB6077A1A07C7C7C3E349D · arch-gpg Verified for the committer email
2 files · +138 -33
M README.md +10 -33
@@ -11,6 +11,9 @@
1111
1212 <p align="center">A minimal Wayland compositor in Go, built for performance: scrollable columns, multi-monitor workspaces and a zero-copy path for games.</p>
1313
14+> [!WARNING]
15+> **Early alpha.** NeferWL is developed and tested mostly on AMD CPUs and GPUs. NVIDIA support is incomplete and untested; expect bugs and breaking config changes.
16+
1417 ---
1518
1619 ## Why NeferWL
@@ -104,39 +107,7 @@ bind.ctrl+cmd+space = spawn fuzzel
104107 startup = wl-paste --watch cliphist store
105108 ```
106109
107-### Keys
108-
109-| Key | Default | Meaning |
110-|---|---|---|
111-| `keyboard.layout`, `.variant`, `.options` | empty | xkb names, e.g. `fr`, `caps:escape` |
112-| `keyboard.repeat-rate` / `repeat-delay` | `25` / `600` | Key repeat per second / delay in ms |
113-| `keyboard.cmd` | `super` | Modifier that `cmd` means in binds: `super`, `alt` or `ctrl` |
114-| `terminal` | `foot` | Opened at startup and by `spawn-terminal` |
115-| `startup` | none | Command run once at session start; repeat the key for more |
116-| `xwayland` | `xwayland-satellite` | X11 support; `off` disables it |
117-| `background` | `#111111` | Solid background color |
118-| `border.width` | `2` | Separator lines between tiles, in logical pixels; `0` hides them |
119-| `border.active` / `border.inactive` | `#808080` / `#111111` | Separator colors around the focused / other windows |
120-| `layout.gaps` | `0` | Space between windows |
121-| `layout.max-columns` | `2` | Columns that share the screen before scrolling |
122-| `layout.overflow` | `scroll` | Past the max: `scroll` right, or `fixed` spiral split |
123-| `layout.presets` | `1/3, 1/2, 2/3, 1` | Widths for `cycle-column-width` |
124-| `focus.follow-move` | `off` | Follow a column moved to another workspace |
125-| `workspace.<name>.hidden` | `off` | Reachable only through its bind, which toggles it |
126-| `workspace.<name>.monitor` | focused | Home monitor: connector (`DP-2`) or monitor key |
127-| `workspace.<name>.max-columns`, `.overflow` | layout values | Per-workspace layout |
128-| `workspace.<name>.column.<N>` | none | Slot: `<width>, <command>` |
129-| `output.<name>` | preferred | `WxH`, `WxH@Hz`, `preferred` or `off` |
130-| `output.<name>.scale` | `1` | 1 to 4, e.g. `1.5` or `4/3` |
131-| `output.<name>.primary` | `off` | Gets focus and pointer at startup |
132-| `render.direct-scanout` | `on` | Fullscreen buffers straight to the display |
133-| `render.tearing` / `render.vrr` | `on` / `on` | For games in direct scanout |
134-| `log.level` / `log.debug` | `info` / empty | Log level / debug components or `all` |
135-| `bind.<keys>` | see below | Action for a key combo; `none` removes a default |
136-
137-Bind actions: `spawn <command>`, `spawn-terminal`, `close-window`, `toggle-fullscreen`, `cycle-column-width`, `focus-column-left/right`, `focus-window-up/down`, `move-column-left/right`, `consume-or-expel-window-left/right`, `focus-workspace <N>`, `focus-workspace-up/down`, `workspace <name>`, `move-column-to-workspace <N|up|down>`, `move-window-to-workspace <N|up|down>`, `focus-monitor-left/right`, `move-workspace-to-monitor-left/right`, `scale-up`, `scale-down`, `quit`.
138-
139-See `examples/config` for every default bind, with comments. A missing file means defaults. An invalid line logs a warning and keeps that key's default; the rest of the file still applies. Every key applies live when the file changes, including the keyboard layout; each reload logs the keys that changed.
110+Every key, value and default bind is listed in [docs/config.md](docs/config.md); `examples/config` is a commented copy of the defaults. A missing file means defaults. An invalid line logs a warning and keeps that key's default; the rest of the file still applies. Every key applies live when the file changes, including the keyboard layout; each reload logs the keys that changed.
140111
141112 ## Running commands
142113
@@ -231,6 +202,12 @@ As a software engineer, my passion is bringing more tools to the Go ecosystem. N
231202
232203 What Go does not give us is Rust's borrow checker: memory and concurrency mistakes are not caught at compile time. NeferWL makes up for it with strict ownership (one goroutine owns each piece of state), the race detector on every test run, and protocol tests against real Wayland clients.
233204
205+## Contributing
206+
207+Contributions are welcome. Open an issue first, for a bug fix or a feature, and wait until it is accepted before sending a pull request. Pull requests without an accepted issue will be closed.
208+
209+Before a pull request, `make check`, `make race`, `make mocks-check` and `staticcheck ./...` must pass. Repository rules are in [AGENTS.md](AGENTS.md).
210+
234211 ## License
235212
236213 NeferWL is licensed under the [GNU General Public License v3.0](LICENSE).
@@ -11,6 +11,9 @@
11 11
12 <p align="center">A minimal Wayland compositor in Go, built for performance: scrollable columns, multi-monitor workspaces and a zero-copy path for games.</p>12 <p align="center">A minimal Wayland compositor in Go, built for performance: scrollable columns, multi-monitor workspaces and a zero-copy path for games.</p>
13 13
14+> [!WARNING]
15+> **Early alpha.** NeferWL is developed and tested mostly on AMD CPUs and GPUs. NVIDIA support is incomplete and untested; expect bugs and breaking config changes.
16+
14 ---17 ---
15 18
16 ## Why NeferWL19 ## Why NeferWL
@@ -104,39 +107,7 @@ bind.ctrl+cmd+space = spawn fuzzel
104 startup = wl-paste --watch cliphist store107 startup = wl-paste --watch cliphist store
105 ```108 ```
106 109
107-### Keys110+Every key, value and default bind is listed in [docs/config.md](docs/config.md); `examples/config` is a commented copy of the defaults. A missing file means defaults. An invalid line logs a warning and keeps that key's default; the rest of the file still applies. Every key applies live when the file changes, including the keyboard layout; each reload logs the keys that changed.
108-
109-| Key | Default | Meaning |
110-|---|---|---|
111-| `keyboard.layout`, `.variant`, `.options` | empty | xkb names, e.g. `fr`, `caps:escape` |
112-| `keyboard.repeat-rate` / `repeat-delay` | `25` / `600` | Key repeat per second / delay in ms |
113-| `keyboard.cmd` | `super` | Modifier that `cmd` means in binds: `super`, `alt` or `ctrl` |
114-| `terminal` | `foot` | Opened at startup and by `spawn-terminal` |
115-| `startup` | none | Command run once at session start; repeat the key for more |
116-| `xwayland` | `xwayland-satellite` | X11 support; `off` disables it |
117-| `background` | `#111111` | Solid background color |
118-| `border.width` | `2` | Separator lines between tiles, in logical pixels; `0` hides them |
119-| `border.active` / `border.inactive` | `#808080` / `#111111` | Separator colors around the focused / other windows |
120-| `layout.gaps` | `0` | Space between windows |
121-| `layout.max-columns` | `2` | Columns that share the screen before scrolling |
122-| `layout.overflow` | `scroll` | Past the max: `scroll` right, or `fixed` spiral split |
123-| `layout.presets` | `1/3, 1/2, 2/3, 1` | Widths for `cycle-column-width` |
124-| `focus.follow-move` | `off` | Follow a column moved to another workspace |
125-| `workspace.<name>.hidden` | `off` | Reachable only through its bind, which toggles it |
126-| `workspace.<name>.monitor` | focused | Home monitor: connector (`DP-2`) or monitor key |
127-| `workspace.<name>.max-columns`, `.overflow` | layout values | Per-workspace layout |
128-| `workspace.<name>.column.<N>` | none | Slot: `<width>, <command>` |
129-| `output.<name>` | preferred | `WxH`, `WxH@Hz`, `preferred` or `off` |
130-| `output.<name>.scale` | `1` | 1 to 4, e.g. `1.5` or `4/3` |
131-| `output.<name>.primary` | `off` | Gets focus and pointer at startup |
132-| `render.direct-scanout` | `on` | Fullscreen buffers straight to the display |
133-| `render.tearing` / `render.vrr` | `on` / `on` | For games in direct scanout |
134-| `log.level` / `log.debug` | `info` / empty | Log level / debug components or `all` |
135-| `bind.<keys>` | see below | Action for a key combo; `none` removes a default |
136-
137-Bind actions: `spawn <command>`, `spawn-terminal`, `close-window`, `toggle-fullscreen`, `cycle-column-width`, `focus-column-left/right`, `focus-window-up/down`, `move-column-left/right`, `consume-or-expel-window-left/right`, `focus-workspace <N>`, `focus-workspace-up/down`, `workspace <name>`, `move-column-to-workspace <N|up|down>`, `move-window-to-workspace <N|up|down>`, `focus-monitor-left/right`, `move-workspace-to-monitor-left/right`, `scale-up`, `scale-down`, `quit`.
138-
139-See `examples/config` for every default bind, with comments. A missing file means defaults. An invalid line logs a warning and keeps that key's default; the rest of the file still applies. Every key applies live when the file changes, including the keyboard layout; each reload logs the keys that changed.
140 111
141 ## Running commands112 ## Running commands
142 113
@@ -231,6 +202,12 @@ As a software engineer, my passion is bringing more tools to the Go ecosystem. N
231 202
232 What Go does not give us is Rust's borrow checker: memory and concurrency mistakes are not caught at compile time. NeferWL makes up for it with strict ownership (one goroutine owns each piece of state), the race detector on every test run, and protocol tests against real Wayland clients.203 What Go does not give us is Rust's borrow checker: memory and concurrency mistakes are not caught at compile time. NeferWL makes up for it with strict ownership (one goroutine owns each piece of state), the race detector on every test run, and protocol tests against real Wayland clients.
233 204
205+## Contributing
206+
207+Contributions are welcome. Open an issue first, for a bug fix or a feature, and wait until it is accepted before sending a pull request. Pull requests without an accepted issue will be closed.
208+
209+Before a pull request, `make check`, `make race`, `make mocks-check` and `staticcheck ./...` must pass. Repository rules are in [AGENTS.md](AGENTS.md).
210+
234 ## License211 ## License
235 212
236 NeferWL is licensed under the [GNU General Public License v3.0](LICENSE).213 NeferWL is licensed under the [GNU General Public License v3.0](LICENSE).
A docs/config.md +128 -0
@@ -0,0 +1,128 @@
1+# Configuration
2+
3+NeferWL reads `$XDG_CONFIG_HOME/neferwl/config` (or `~/.config/neferwl/config`). `neferwl --config <path>` selects another file; `neferwl validate-config [path]` checks one without starting the compositor.
4+
5+## Format
6+
7+- One `key = value` per line; `#` starts a comment.
8+- Lists are comma-separated; booleans are `on` / `off`.
9+- A missing file or key means the default. An invalid line logs a warning and keeps that key's default; the rest of the file still applies. A duplicate key warns and the last one wins.
10+- Every key applies live when the file is saved; windows stay open. `startup` and `xwayland` take effect at the next start.
11+
12+## Keys
13+
14+| Key | Default | Meaning |
15+|---|---|---|
16+| `keyboard.layout`, `.variant`, `.options` | empty | xkb names, e.g. `fr`, `caps:escape` |
17+| `keyboard.repeat-rate` / `repeat-delay` | `25` / `600` | Key repeat per second / delay in ms |
18+| `keyboard.cmd` | `super` | Modifier that `cmd` means in binds: `super`, `alt` or `ctrl` |
19+| `terminal` | `foot` | Opened at startup and by `spawn-terminal` |
20+| `startup` | none | Command run once at session start; repeat the key for more |
21+| `xwayland` | `xwayland-satellite` | X11 support; `off` disables it |
22+| `background` | `#111111` | Solid background color |
23+| `border.width` | `2` | Separator lines between tiles, in logical pixels; `0` hides them |
24+| `border.active` / `border.inactive` | `#808080` / `#111111` | Separator colors around the focused / other windows |
25+| `layout.gaps` | `0` | Space between windows |
26+| `layout.max-columns` | `2` | Columns that share the screen before scrolling |
27+| `layout.overflow` | `scroll` | Past the max: `scroll` right, or `fixed` spiral split |
28+| `layout.presets` | `1/3, 1/2, 2/3, 1` | Widths for `cycle-column-width` |
29+| `focus.follow-move` | `off` | Follow a column moved to another workspace |
30+| `workspace.<name>.hidden` | `off` | Reachable only through its bind, which toggles it |
31+| `workspace.<name>.monitor` | focused | Home monitor: connector (`DP-2`) or monitor key |
32+| `workspace.<name>.max-columns`, `.overflow` | layout values | Per-workspace layout |
33+| `workspace.<name>.column.<N>` | none | Slot: `<width>, <command>` |
34+| `output.<name>` | preferred | `WxH`, `WxH@Hz`, `preferred` or `off` |
35+| `output.<name>.scale` | `1` | 1 to 4, e.g. `1.5` or `4/3` |
36+| `output.<name>.primary` | `off` | Gets focus and pointer at startup |
37+| `render.direct-scanout` | `on` | Fullscreen buffers straight to the display |
38+| `render.tearing` / `render.vrr` | `on` / `on` | For games in direct scanout |
39+| `log.level` / `log.debug` | `info` / empty | Log level / debug components or `all` |
40+| `bind.<keys>` | see below | Action for a key combo; `none` removes a default |
41+
42+## Binds
43+
44+`bind.<keys> = <action>`. Modifiers: `cmd` (see `keyboard.cmd`), `shift`, `ctrl`, `alt`, `super`.
45+
46+- Keys are what the active layout prints: `cmd+é` on AZERTY. Write `=`, `#` and space by name: `cmd+equal`, `cmd+numbersign`, `cmd+space`.
47+- `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.
48+- `none` removes a default bind.
49+- `spawn <command>` runs a program without a shell; see [Running commands](../README.md#running-commands).
50+
51+### Actions
52+
53+| Action | Effect |
54+|---|---|
55+| `spawn <command>` | Run a program |
56+| `spawn-terminal` | Run `terminal` |
57+| `close-window` | Close the focused window |
58+| `toggle-fullscreen` | Fullscreen the focused window |
59+| `cycle-column-width` | Step through `layout.presets` |
60+| `focus-column-left/right` | Focus the neighbor column; at the edge, the neighbor monitor |
61+| `focus-window-up/down` | Focus in the column; past the edge, the next workspace |
62+| `move-column-left/right` | Move the focused column |
63+| `consume-or-expel-window-left/right` | A lone window joins the neighbor column; a stacked one leaves for a new column |
64+| `focus-workspace <N>` / `focus-workspace-up/down` | Show a numbered or neighbor workspace |
65+| `workspace <name>` | Toggle a named workspace |
66+| `move-column-to-workspace <N>` / `-up/-down` | Move the focused column |
67+| `move-window-to-workspace <N>` / `-up/-down` | Move only the focused window |
68+| `focus-monitor-left/right` | Focus the neighbor monitor |
69+| `move-workspace-to-monitor-left/right` | Move the workspace; it gets a new home |
70+| `scale-up` / `scale-down` | Zoom the whole display |
71+| `quit` | Exit NeferWL |
72+
73+### Default binds
74+
75+| Keys | Action |
76+|---|---|
77+| `cmd+return` | `spawn-terminal` |
78+| `cmd+left` | `focus-column-left` |
79+| `cmd+right` | `focus-column-right` |
80+| `cmd+up` | `focus-window-up` |
81+| `cmd+down` | `focus-window-down` |
82+| `cmd+shift+left` | `move-column-left` |
83+| `cmd+shift+right` | `move-column-right` |
84+| `cmd+h` | `focus-column-left` |
85+| `cmd+l` | `focus-column-right` |
86+| `cmd+k` | `focus-window-up` |
87+| `cmd+j` | `focus-window-down` |
88+| `cmd+shift+h` | `move-column-left` |
89+| `cmd+shift+l` | `move-column-right` |
90+| `cmd+bracketleft` | `consume-or-expel-window-left` |
91+| `cmd+bracketright` | `consume-or-expel-window-right` |
92+| `cmd+r` | `cycle-column-width` |
93+| `cmd+shift+f` | `toggle-fullscreen` |
94+| `cmd+q` | `close-window` |
95+| `ctrl+alt+backspace` | `quit` |
96+| `ctrl+cmd+space` | `spawn fuzzel` |
97+| `cmd+pageup` | `focus-workspace-up` |
98+| `cmd+pagedown` | `focus-workspace-down` |
99+| `cmd+shift+pageup` | `move-column-to-workspace-up` |
100+| `cmd+shift+pagedown` | `move-column-to-workspace-down` |
101+| `cmd+code:2` | `focus-workspace 1` |
102+| `cmd+code:3` | `focus-workspace 2` |
103+| `cmd+code:4` | `focus-workspace 3` |
104+| `cmd+code:5` | `focus-workspace 4` |
105+| `cmd+code:6` | `focus-workspace 5` |
106+| `cmd+code:7` | `focus-workspace 6` |
107+| `cmd+code:8` | `focus-workspace 7` |
108+| `cmd+code:9` | `focus-workspace 8` |
109+| `cmd+code:10` | `focus-workspace 9` |
110+| `cmd+shift+code:2` | `move-column-to-workspace 1` |
111+| `cmd+shift+code:3` | `move-column-to-workspace 2` |
112+| `cmd+shift+code:4` | `move-column-to-workspace 3` |
113+| `cmd+shift+code:5` | `move-column-to-workspace 4` |
114+| `cmd+shift+code:6` | `move-column-to-workspace 5` |
115+| `cmd+shift+code:7` | `move-column-to-workspace 6` |
116+| `cmd+shift+code:8` | `move-column-to-workspace 7` |
117+| `cmd+shift+code:9` | `move-column-to-workspace 8` |
118+| `cmd+shift+code:10` | `move-column-to-workspace 9` |
119+| `cmd+ctrl+left` | `focus-monitor-left` |
120+| `cmd+ctrl+right` | `focus-monitor-right` |
121+| `cmd+ctrl+h` | `focus-monitor-left` |
122+| `cmd+ctrl+l` | `focus-monitor-right` |
123+| `cmd+ctrl+shift+left` | `move-workspace-to-monitor-left` |
124+| `cmd+ctrl+shift+right` | `move-workspace-to-monitor-right` |
125+| `cmd+ctrl+shift+h` | `move-workspace-to-monitor-left` |
126+| `cmd+ctrl+shift+l` | `move-workspace-to-monitor-right` |
127+| `cmd+code:13` | `scale-up` |
128+| `cmd+code:12` | `scale-down` |
@@ -0,0 +1,128 @@
1+# Configuration
2+
3+NeferWL reads `$XDG_CONFIG_HOME/neferwl/config` (or `~/.config/neferwl/config`). `neferwl --config <path>` selects another file; `neferwl validate-config [path]` checks one without starting the compositor.
4+
5+## Format
6+
7+- One `key = value` per line; `#` starts a comment.
8+- Lists are comma-separated; booleans are `on` / `off`.
9+- A missing file or key means the default. An invalid line logs a warning and keeps that key's default; the rest of the file still applies. A duplicate key warns and the last one wins.
10+- Every key applies live when the file is saved; windows stay open. `startup` and `xwayland` take effect at the next start.
11+
12+## Keys
13+
14+| Key | Default | Meaning |
15+|---|---|---|
16+| `keyboard.layout`, `.variant`, `.options` | empty | xkb names, e.g. `fr`, `caps:escape` |
17+| `keyboard.repeat-rate` / `repeat-delay` | `25` / `600` | Key repeat per second / delay in ms |
18+| `keyboard.cmd` | `super` | Modifier that `cmd` means in binds: `super`, `alt` or `ctrl` |
19+| `terminal` | `foot` | Opened at startup and by `spawn-terminal` |
20+| `startup` | none | Command run once at session start; repeat the key for more |
21+| `xwayland` | `xwayland-satellite` | X11 support; `off` disables it |
22+| `background` | `#111111` | Solid background color |
23+| `border.width` | `2` | Separator lines between tiles, in logical pixels; `0` hides them |
24+| `border.active` / `border.inactive` | `#808080` / `#111111` | Separator colors around the focused / other windows |
25+| `layout.gaps` | `0` | Space between windows |
26+| `layout.max-columns` | `2` | Columns that share the screen before scrolling |
27+| `layout.overflow` | `scroll` | Past the max: `scroll` right, or `fixed` spiral split |
28+| `layout.presets` | `1/3, 1/2, 2/3, 1` | Widths for `cycle-column-width` |
29+| `focus.follow-move` | `off` | Follow a column moved to another workspace |
30+| `workspace.<name>.hidden` | `off` | Reachable only through its bind, which toggles it |
31+| `workspace.<name>.monitor` | focused | Home monitor: connector (`DP-2`) or monitor key |
32+| `workspace.<name>.max-columns`, `.overflow` | layout values | Per-workspace layout |
33+| `workspace.<name>.column.<N>` | none | Slot: `<width>, <command>` |
34+| `output.<name>` | preferred | `WxH`, `WxH@Hz`, `preferred` or `off` |
35+| `output.<name>.scale` | `1` | 1 to 4, e.g. `1.5` or `4/3` |
36+| `output.<name>.primary` | `off` | Gets focus and pointer at startup |
37+| `render.direct-scanout` | `on` | Fullscreen buffers straight to the display |
38+| `render.tearing` / `render.vrr` | `on` / `on` | For games in direct scanout |
39+| `log.level` / `log.debug` | `info` / empty | Log level / debug components or `all` |
40+| `bind.<keys>` | see below | Action for a key combo; `none` removes a default |
41+
42+## Binds
43+
44+`bind.<keys> = <action>`. Modifiers: `cmd` (see `keyboard.cmd`), `shift`, `ctrl`, `alt`, `super`.
45+
46+- Keys are what the active layout prints: `cmd+é` on AZERTY. Write `=`, `#` and space by name: `cmd+equal`, `cmd+numbersign`, `cmd+space`.
47+- `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.
48+- `none` removes a default bind.
49+- `spawn <command>` runs a program without a shell; see [Running commands](../README.md#running-commands).
50+
51+### Actions
52+
53+| Action | Effect |
54+|---|---|
55+| `spawn <command>` | Run a program |
56+| `spawn-terminal` | Run `terminal` |
57+| `close-window` | Close the focused window |
58+| `toggle-fullscreen` | Fullscreen the focused window |
59+| `cycle-column-width` | Step through `layout.presets` |
60+| `focus-column-left/right` | Focus the neighbor column; at the edge, the neighbor monitor |
61+| `focus-window-up/down` | Focus in the column; past the edge, the next workspace |
62+| `move-column-left/right` | Move the focused column |
63+| `consume-or-expel-window-left/right` | A lone window joins the neighbor column; a stacked one leaves for a new column |
64+| `focus-workspace <N>` / `focus-workspace-up/down` | Show a numbered or neighbor workspace |
65+| `workspace <name>` | Toggle a named workspace |
66+| `move-column-to-workspace <N>` / `-up/-down` | Move the focused column |
67+| `move-window-to-workspace <N>` / `-up/-down` | Move only the focused window |
68+| `focus-monitor-left/right` | Focus the neighbor monitor |
69+| `move-workspace-to-monitor-left/right` | Move the workspace; it gets a new home |
70+| `scale-up` / `scale-down` | Zoom the whole display |
71+| `quit` | Exit NeferWL |
72+
73+### Default binds
74+
75+| Keys | Action |
76+|---|---|
77+| `cmd+return` | `spawn-terminal` |
78+| `cmd+left` | `focus-column-left` |
79+| `cmd+right` | `focus-column-right` |
80+| `cmd+up` | `focus-window-up` |
81+| `cmd+down` | `focus-window-down` |
82+| `cmd+shift+left` | `move-column-left` |
83+| `cmd+shift+right` | `move-column-right` |
84+| `cmd+h` | `focus-column-left` |
85+| `cmd+l` | `focus-column-right` |
86+| `cmd+k` | `focus-window-up` |
87+| `cmd+j` | `focus-window-down` |
88+| `cmd+shift+h` | `move-column-left` |
89+| `cmd+shift+l` | `move-column-right` |
90+| `cmd+bracketleft` | `consume-or-expel-window-left` |
91+| `cmd+bracketright` | `consume-or-expel-window-right` |
92+| `cmd+r` | `cycle-column-width` |
93+| `cmd+shift+f` | `toggle-fullscreen` |
94+| `cmd+q` | `close-window` |
95+| `ctrl+alt+backspace` | `quit` |
96+| `ctrl+cmd+space` | `spawn fuzzel` |
97+| `cmd+pageup` | `focus-workspace-up` |
98+| `cmd+pagedown` | `focus-workspace-down` |
99+| `cmd+shift+pageup` | `move-column-to-workspace-up` |
100+| `cmd+shift+pagedown` | `move-column-to-workspace-down` |
101+| `cmd+code:2` | `focus-workspace 1` |
102+| `cmd+code:3` | `focus-workspace 2` |
103+| `cmd+code:4` | `focus-workspace 3` |
104+| `cmd+code:5` | `focus-workspace 4` |
105+| `cmd+code:6` | `focus-workspace 5` |
106+| `cmd+code:7` | `focus-workspace 6` |
107+| `cmd+code:8` | `focus-workspace 7` |
108+| `cmd+code:9` | `focus-workspace 8` |
109+| `cmd+code:10` | `focus-workspace 9` |
110+| `cmd+shift+code:2` | `move-column-to-workspace 1` |
111+| `cmd+shift+code:3` | `move-column-to-workspace 2` |
112+| `cmd+shift+code:4` | `move-column-to-workspace 3` |
113+| `cmd+shift+code:5` | `move-column-to-workspace 4` |
114+| `cmd+shift+code:6` | `move-column-to-workspace 5` |
115+| `cmd+shift+code:7` | `move-column-to-workspace 6` |
116+| `cmd+shift+code:8` | `move-column-to-workspace 7` |
117+| `cmd+shift+code:9` | `move-column-to-workspace 8` |
118+| `cmd+shift+code:10` | `move-column-to-workspace 9` |
119+| `cmd+ctrl+left` | `focus-monitor-left` |
120+| `cmd+ctrl+right` | `focus-monitor-right` |
121+| `cmd+ctrl+h` | `focus-monitor-left` |
122+| `cmd+ctrl+l` | `focus-monitor-right` |
123+| `cmd+ctrl+shift+left` | `move-workspace-to-monitor-left` |
124+| `cmd+ctrl+shift+right` | `move-workspace-to-monitor-right` |
125+| `cmd+ctrl+shift+h` | `move-workspace-to-monitor-left` |
126+| `cmd+ctrl+shift+l` | `move-workspace-to-monitor-right` |
127+| `cmd+code:13` | `scale-up` |
128+| `cmd+code:12` | `scale-down` |

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