This project was just an experiment. It works, but I have no time to develop or maintain it any further, so it is not actively maintained.
If you want to take it over, please do! Feel free to fork it and carry it forward — you don't need my permission. If you open an issue or a pull request to let me know, I'm happy to link your fork here as the official successor so that people land on the maintained version instead of this one.
Bug reports and feature requests will most likely go unanswered — please don't take it personally.
A LazyVim-style which-key popup for tmux. Press a trigger key to open a discoverable, keyboard-driven command menu with nested groups, breadcrumb navigation, and Nord-themed colors.
- Discoverable keybindings - see all available commands at a glance
- Nested groups - organize commands hierarchically (git, window, session, etc.)
- Breadcrumb navigation - always know where you are in the menu tree
- Nord color theme - clean, readable color scheme using 24-bit true color
- JSON configuration - easy to customize, extend, and share
- Five action types - shell commands (with optional auto-execute), tmux commands, external scripts, popups, and nested groups
- Single-keystroke input - no Enter key required, instant response
- tmux >= 3.3 (for
display-popupsupport) jq(for JSON parsing)- A terminal with true color (24-bit) support
With TPM (recommended)
Add to your ~/.tmux.conf:
set -g @plugin 'Nucc/tmux-which-key'Then press prefix + I to install.
Clone the repository:
git clone https://github.com/Nucc/tmux-which-key.git ~/.tmux/plugins/tmux-which-keyAdd to your ~/.tmux.conf:
run-shell ~/.tmux/plugins/tmux-which-key/which-key.tmuxReload tmux:
tmux source-file ~/.tmux.confIf you use Nix and Flakes, you can add this plugin to your Home Manager configuration.
- Add to your
flake.nixinputs:
{
inputs.tmux-which-key.url = "github:Nucc/tmux-which-key";
}- Add the package to
programs.tmux.pluginsin your configuration:
{ pkgs, inputs, ... }: {
programs.tmux.plugins = [
inputs.tmux-which-key.packages.${pkgs.system}.default
];
}Note: Ensure jq is available in your system path, as it is required for JSON parsing.
Press prefix + Space (default) to open the which-key popup.
- Press a key to execute the corresponding command or enter a group
- Escape to go back one level or close the menu
- Backspace to go back one level or close the menu
Groups are indicated by a + prefix and shown in cyan. Pressing a group key opens its submenu with a breadcrumb showing your navigation path.
Set these in your ~/.tmux.conf before loading the plugin:
| Option | Default | Description |
|---|---|---|
@which-key-trigger |
Space |
Key binding (after prefix) to open the menu |
@which-key-config |
(auto-detected) | Path to a custom JSON config file |
@which-key-popup-height |
16 |
Popup height in lines |
@which-key-popup-width |
100 |
Popup width in characters |
@which-key-popup-bg |
#2E3440 |
Popup background color |
@which-key-popup-fg |
#4C566A |
Popup border/foreground color |
@which-key-popup-x |
C |
Popup X position (C = centered) |
@which-key-popup-y |
S |
Popup Y position (S = status line) |
Example:
set -g @which-key-config '~/.config/tmux-which-key/config.json'
set -g @which-key-popup-height '20'
set -g @which-key-popup-width '120'
set -g @plugin 'Nucc/tmux-which-key'By default the plugin binds prefix + Space. You can override this with @which-key-trigger, or create your own binding entirely in ~/.tmux.conf.
To bind Ctrl-Space directly (no prefix needed):
# Disable the default prefix binding
set -g @which-key-trigger 'None'
# Bind Ctrl-Space directly (-n = no prefix)
bind-key -n C-Space run-shell 'tmux display-popup -E -h 16 -w 100 -x C -y S -S "fg=#4C566A" -s "bg=#2E3440" "~/.tmux/plugins/tmux-which-key/scripts/which-key.sh #{pane_id}"'To use a custom config with a manual binding:
bind-key -n C-Space run-shell 'tmux display-popup -E -h 16 -w 100 -x C -y S -S "fg=#4C566A" -s "bg=#2E3440" "~/.tmux/plugins/tmux-which-key/scripts/which-key.sh --config ~/.config/tmux-which-key/config.json #{pane_id}"'The plugin looks for a config file in this order:
- Path set via
@which-key-configtmux option $XDG_CONFIG_HOME/tmux-which-key/config.json(usually~/.config/tmux-which-key/config.json)~/.tmux-which-key.json- Plugin's built-in
configs/default.json
To create your own config:
mkdir -p ~/.config/tmux-which-key
cp ~/.tmux/plugins/tmux-which-key/configs/default.json ~/.config/tmux-which-key/config.jsonThen edit ~/.config/tmux-which-key/config.json to your liking.
The config file is a JSON object with a top-level items array. Each item has:
| Field | Type | Required | Description |
|---|---|---|---|
key |
string | yes | Single character that triggers this item |
type |
string | yes | One of: group, action, tmux, script, popup |
description |
string | yes | Label shown in the menu |
command |
string | for non-groups | Command to execute |
items |
array | for groups | Nested items in this group |
immediate |
boolean | no | For action type: also press Enter after pasting (default: false) |
| Type | Behavior | Example |
|---|---|---|
group |
Opens a submenu with nested items | Navigate to git commands |
action |
Sends text to the active pane (as if typed). With "immediate": true, also presses Enter. |
git status |
tmux |
Executes a tmux command directly | split-window -h |
script |
Runs a shell script via tmux run-shell |
~/scripts/my-script.sh |
popup |
Opens command in a temporary display-popup at the pane's working directory. Closes on exit or Escape. |
lazygit |
{
"items": [
{
"key": "g",
"type": "group",
"description": "git",
"items": [
{ "key": "s", "type": "action", "command": "git status", "description": "Status", "immediate": true },
{ "key": "c", "type": "action", "command": "git commit", "description": "Commit" },
{ "key": "g", "type": "popup", "command": "lazygit", "description": "Lazygit" }
]
},
{
"key": "w",
"type": "group",
"description": "window",
"items": [
{ "key": "v", "type": "tmux", "command": "split-window -h -c '#{pane_current_path}'", "description": "Split vertical" },
{ "key": "s", "type": "tmux", "command": "split-window -v -c '#{pane_current_path}'", "description": "Split horizontal" }
]
},
{ "key": "r", "type": "tmux", "command": "source-file ~/.tmux.conf \\; display-message 'Config reloaded'", "description": "Reload config" },
{ "key": "h", "type": "popup", "command": "htop", "description": "System monitor" },
{ "key": "d", "type": "script", "command": "~/scripts/deploy.sh", "description": "Deploy" }
]
}The built-in default config provides ~75 commands organized into 8 groups plus standalone items. Press prefix + Space to open the root menu:
| Key | Type | Description |
|---|---|---|
p |
group | Pane - split, navigate, zoom, swap, resize, and more |
w |
group | Window - create, kill, rename, find, navigate, move |
s |
group | Session - create, detach, choose, rename, kill, switch |
b |
group | Buffer - list, paste, choose, save/load, copy mode |
l |
group | Layout - cycle layouts and select presets |
C |
group | Client - list, choose, detach, refresh, lock |
o |
group | Options - show/set options, environment, messages |
g |
group | Git - status, diff, log, push, pull, branches, fetch, add, commit, rebase |
: |
tmux | Command prompt |
r |
tmux | Reload tmux config |
? |
tmux | List all keybindings |
c |
action | Clear screen |
t |
tmux | Clock mode |
d |
tmux | Display panes |
| Key | Description | Key | Description |
|---|---|---|---|
v |
Split vertical | s |
Split horizontal |
h/j/k/l |
Navigate panes | z |
Zoom toggle |
x |
Kill pane | o |
Last pane |
! |
Break to window | J |
Join pane |
m/M |
Mark/unmark pane | {/} |
Swap up/down |
c |
Clear history | q |
Capture to buffer |
p |
Respawn pane | r |
+Resize (subgroup) |
| Key | Description | Key | Description |
|---|---|---|---|
n |
New window | x |
Kill window |
r |
Rename | f |
Find window |
l |
Last window | . |
Next window |
, |
Previous window | w |
Choose window |
m |
Move window | s |
Swap window |
R |
Rotate panes |
| Key | Description | Key | Description |
|---|---|---|---|
n |
New session | d |
Detach |
s |
Choose session | w |
Choose tree |
r |
Rename | k |
Kill session |
l |
List sessions | L |
Lock session |
( |
Previous session | ) |
Next session |
| Key | Description | Key | Description |
|---|---|---|---|
l |
List buffers | p |
Paste |
c |
Choose buffer | d |
Delete buffer |
s |
Save to file | L |
Load from file |
v |
Show buffer | y |
Copy mode |
C |
Capture pane |
| Key | Description | Key | Description |
|---|---|---|---|
n |
Next layout | p |
Previous layout |
1 |
Even horizontal | 2 |
Even vertical |
3 |
Main horizontal | 4 |
Main vertical |
5 |
Tiled |
| Key | Description | Key | Description |
|---|---|---|---|
l |
List clients | c |
Choose client |
d |
Detach | D |
Detach other |
r |
Refresh | s |
Suspend |
L |
Lock |
| Key | Description | Key | Description |
|---|---|---|---|
g |
Show global options | w |
Show window options |
e |
Show environment | s |
Set global option |
c |
Customize mode | m |
Show messages |
k |
List commands |
MIT
