-
Install with mise (2026.9.2 or later):
mise use -g packslip:github.com/844196/wk
mise checks the release's packslip signature before installing it.
-
Activate in
$ZDOTDIR/.zshrc:# Bind space as the leader key and comma as the major-leader key. # The major-prefix "m" is used for the major menu. eval "$(wk init --leader ' ' --major-leader ',' --major-prefix 'm')"
-
Restart zsh.
Tip
If you want to register only the widgets, change it as follows:
eval "$(wk init)"Download the archive for your platform from the latest release,
extract it, and put the wk binary into your $PATH. Then continue from step 2 above. The archive
also holds the JSON Schemas for the configuration files and the license.
wk reads two files of the same shape: a global one, and a local one in the working directory that overrides it.
- Global:
${XDG_CONFIG_HOME:-$HOME/.config}/wk/config.yaml - Local:
$PWD/wk.yaml
Either may also be named with .yml. If both exist in the same place, only the .yaml one is read.
Each file has two sections, config: and bindings:, and either may be left out. Any other key at
the top level is an error.
# yaml-language-server: $schema=/path/to/schemas/config.json
config:
timeout: 60000
symbols:
prompt: '❯ '
colors:
prompt: 8
inputKeys:
color: 8
attrs: [dim]
breadcrumb:
color: 8
attrs: [dim]
lastInputKey:
color: 6
attrs: [underline]
bindingKey: 5
separator:
color: 5
attrs: [dim]
group: 8
bindingIcon: 8
bindingDescription: 8
bindings:
- key: g
desc: Git
type: bindings
bindings:
- key: p
desc: Push/Pull
type: bindings
bindings:
- key: return
desc: git push
type: command
buffer: 'git push origin $(git symbolic-ref --short HEAD)'
eval: true
- key: f
desc: git push -f
type: command
buffer: 'git push --force-with-lease --force-if-includes origin $(git symbolic-ref --short HEAD)'
eval: true
- key: l
type: command
buffer: 'git pull'
accept: true
- key: y
desc: Yank
type: bindings
bindings:
- key: .
desc: Copy $PWD
type: command
buffer: ' echo -ne "\e]52;c;$(base64 <(pwd | tee >$TTY | sed -z ''$s/\n$//''))\a"'
accept: trueThe modeline on the first line points your editor at the schema, for completion and validation. The
schema ships in the release archive as schemas/config.json; with mise, look for it inside the
directory that mise where packslip:github.com/844196/wk prints. The same schema covers both files.
A key is the key to press. YAML reads an unquoted digit as a number, and wk reads it back as that
digit, so key: 1 and key: '1' both bind the 1 key. Most punctuation needs no quoting either —
key: . above is one. YAML's indicator characters do, though: unquoted they are read as null or
rejected outright, so write key: '~' and key: ':'.
$PWD/wk.yaml is laid over the global file:
config:is merged field by field, so the local file only needs the fields it changes. A colour is replaced whole,attrsincluded;symbols.keysis merged key by key.bindings:adds to the global bindings. A local binding replaces a global one with the samekeyentirely — a group is not merged with the global group it replaces.
The menu lists commands first and groups after them, each sorted by the symbol it shows — letters and digits before other symbols — wherever each binding was defined.
config:
colors:
prompt: 5 # only in this project
bindings:
- key: m
desc: Major
type: bindings
bindings:
- key: b
type: command
buffer: 'npm run build'
accept: true
- key: l
type: command
buffer: 'npm run lint'
accept: true
- key: t
type: command
buffer: 'npm run test'
accept: truewk run --config <file> (-c) reads the named file instead of the global and local ones. Repeat it
to layer several files: each one is laid over the ones before it, by the same rules as above.
wk run -c ~/.config/wk/tmux.yaml
wk run -c ~/.config/wk/config.yaml -c ~/.config/wk/tmux.yaml # keep the global config: sectionThis lets a menu opened somewhere else, such as a tmux popup, have bindings of its own without the
working directory's wk.yaml mixing in. A named path is read as written, with no .yml tried in its
place, and a missing one stops wk instead of being skipped.
