detached f74d545

docs(readme): explain how commands run and when to use a script

commit
f74d545f87351b757ce5822ae9bd873324df2fa2
author
brice · · 2026-09-25 12:07 UTC
parent
99dc921
signature
GPG VerifiedCD88F9E564E0102646FB6077A1A07C7C7C3E349D · arch-gpg Verified for the committer email
2 files · +35 -5
M README.md +31 -2
@@ -32,16 +32,45 @@ See `examples/config` for every key and its default. A missing file means defaul
3232
3333 Building requires sibling checkouts of purego-libwayland and purego-vulkan until they are published.
3434
35+## Running commands
36+
37+`spawn <command>` binds, `startup = <command>` lines and `terminal = <command>` run one program directly, without a shell. The line is split on spaces: the first word is the program (looked up in `PATH`, or a path such as `/opt/tool/run`), the other words are its arguments.
38+
39+```text
40+bind.ctrl+cmd+space = spawn fuzzel
41+startup = waybar
42+startup = wl-paste --watch cliphist store
43+```
44+
45+There is no shell, so pipes (`|`), `&&`, redirections, variables (`$HOME`), `~` and quotes have no special meaning: they reach the program as plain arguments. What you write is what runs.
46+
47+For anything more complex, write a script and run the script:
48+
49+```sh
50+#!/bin/sh
51+# ~/.local/bin/screenshot-area: select an area, save it and copy it.
52+file="$HOME/Pictures/$(date +%F-%T).png"
53+grim -g "$(slurp)" "$file" && wl-copy < "$file"
54+```
55+
56+```text
57+bind.cmd+shift+s = spawn screenshot-area
58+```
59+
60+Make it executable (`chmod +x`) and put it in a directory of your `PATH`, such as `~/.local/bin`. The script can use any shell, including fish (`#!/usr/bin/env fish`).
61+
62+Programs started by NeferTTY get `WAYLAND_DISPLAY` and `NEFERTTY_STATE` (see below). `startup` commands run once when the session starts; editing them takes effect at the next start.
63+
3564 ## Clipboard
3665
37-NeferTTY supports the clipboard (`wl_data_device`), the primary selection (middle-click paste) and `ext_data_control_v1` for clipboard managers. With [cliphist](https://github.com/sentriz/cliphist):
66+NeferTTY supports the clipboard (`wl_data_device`), the primary selection (middle-click paste) and `ext_data_control_v1` for clipboard managers. With [cliphist](https://github.com/sentriz/cliphist), store every copy at startup and bind a picker script (see [Running commands](#running-commands)):
3867
3968 ```text
4069 startup = wl-paste --watch cliphist store
4170 bind.cmd+v = spawn cliphist-pick
4271 ```
4372
44-Commands are split on spaces and run without a shell, so the picker is a script on your `PATH`, for example `cliphist-pick`:
73+`~/.local/bin/cliphist-pick`:
4574
4675 ```sh
4776 #!/bin/sh
@@ -32,16 +32,45 @@ See `examples/config` for every key and its default. A missing file means defaul
32 32
33 Building requires sibling checkouts of purego-libwayland and purego-vulkan until they are published.33 Building requires sibling checkouts of purego-libwayland and purego-vulkan until they are published.
34 34
35+## Running commands
36+
37+`spawn <command>` binds, `startup = <command>` lines and `terminal = <command>` run one program directly, without a shell. The line is split on spaces: the first word is the program (looked up in `PATH`, or a path such as `/opt/tool/run`), the other words are its arguments.
38+
39+```text
40+bind.ctrl+cmd+space = spawn fuzzel
41+startup = waybar
42+startup = wl-paste --watch cliphist store
43+```
44+
45+There is no shell, so pipes (`|`), `&&`, redirections, variables (`$HOME`), `~` and quotes have no special meaning: they reach the program as plain arguments. What you write is what runs.
46+
47+For anything more complex, write a script and run the script:
48+
49+```sh
50+#!/bin/sh
51+# ~/.local/bin/screenshot-area: select an area, save it and copy it.
52+file="$HOME/Pictures/$(date +%F-%T).png"
53+grim -g "$(slurp)" "$file" && wl-copy < "$file"
54+```
55+
56+```text
57+bind.cmd+shift+s = spawn screenshot-area
58+```
59+
60+Make it executable (`chmod +x`) and put it in a directory of your `PATH`, such as `~/.local/bin`. The script can use any shell, including fish (`#!/usr/bin/env fish`).
61+
62+Programs started by NeferTTY get `WAYLAND_DISPLAY` and `NEFERTTY_STATE` (see below). `startup` commands run once when the session starts; editing them takes effect at the next start.
63+
35 ## Clipboard64 ## Clipboard
36 65
37-NeferTTY supports the clipboard (`wl_data_device`), the primary selection (middle-click paste) and `ext_data_control_v1` for clipboard managers. With [cliphist](https://github.com/sentriz/cliphist):66+NeferTTY supports the clipboard (`wl_data_device`), the primary selection (middle-click paste) and `ext_data_control_v1` for clipboard managers. With [cliphist](https://github.com/sentriz/cliphist), store every copy at startup and bind a picker script (see [Running commands](#running-commands)):
38 67
39 ```text68 ```text
40 startup = wl-paste --watch cliphist store69 startup = wl-paste --watch cliphist store
41 bind.cmd+v = spawn cliphist-pick70 bind.cmd+v = spawn cliphist-pick
42 ```71 ```
43 72
44-Commands are split on spaces and run without a shell, so the picker is a script on your `PATH`, for example `cliphist-pick`:73+`~/.local/bin/cliphist-pick`:
45 74
46 ```sh75 ```sh
47 #!/bin/sh76 #!/bin/sh
M examples/config +4 -3
@@ -14,8 +14,8 @@ keyboard.cmd = super
1414 # Command for spawn-terminal and the terminal opened at startup.
1515 terminal = foot
1616
17-# Commands run once when the session starts, one line each. Arguments are
18-# split on spaces and there is no shell: put pipes in a script.
17+# Commands run once when the session starts, one line each. Like spawn, a
18+# command runs without a shell: see "Running commands" in the README.
1919 # Programs get WAYLAND_DISPLAY and NEFERTTY_STATE.
2020 # startup = waybar
2121 # startup = wl-paste --watch cliphist store
@@ -74,7 +74,8 @@ log.debug =
7474 # keys right of 0 (- and = on US).
7575 # Keys are what your layout prints (cmd+é on AZERTY). Write = # and space
7676 # by name: cmd+equal, cmd+numbersign, cmd+space. `none` removes a default.
77-# `spawn <command>` runs a program; arguments split on spaces, no shell.
77+# `spawn <command>` runs a program; arguments split on spaces, no shell
78+# (pipes and variables go in a script: see "Running commands" in the README).
7879 bind.cmd+return = spawn-terminal
7980 bind.cmd+left = focus-column-left
8081 bind.cmd+right = focus-column-right
@@ -14,8 +14,8 @@ keyboard.cmd = super
14 # Command for spawn-terminal and the terminal opened at startup.14 # Command for spawn-terminal and the terminal opened at startup.
15 terminal = foot15 terminal = foot
16 16
17-# Commands run once when the session starts, one line each. Arguments are17+# Commands run once when the session starts, one line each. Like spawn, a
18-# split on spaces and there is no shell: put pipes in a script.18+# command runs without a shell: see "Running commands" in the README.
19 # Programs get WAYLAND_DISPLAY and NEFERTTY_STATE.19 # Programs get WAYLAND_DISPLAY and NEFERTTY_STATE.
20 # startup = waybar20 # startup = waybar
21 # startup = wl-paste --watch cliphist store21 # startup = wl-paste --watch cliphist store
@@ -74,7 +74,8 @@ log.debug =
74 # keys right of 0 (- and = on US).74 # keys right of 0 (- and = on US).
75 # Keys are what your layout prints (cmd+é on AZERTY). Write = # and space75 # Keys are what your layout prints (cmd+é on AZERTY). Write = # and space
76 # by name: cmd+equal, cmd+numbersign, cmd+space. `none` removes a default.76 # by name: cmd+equal, cmd+numbersign, cmd+space. `none` removes a default.
77-# `spawn <command>` runs a program; arguments split on spaces, no shell.77+# `spawn <command>` runs a program; arguments split on spaces, no shell
78+# (pipes and variables go in a script: see "Running commands" in the README).
78 bind.cmd+return = spawn-terminal79 bind.cmd+return = spawn-terminal
79 bind.cmd+left = focus-column-left80 bind.cmd+left = focus-column-left
80 bind.cmd+right = focus-column-right81 bind.cmd+right = focus-column-right

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 25

Tags 10

↑↓ moveenter openesc close