DMenu tutorial
- Published on
- 9 min read
- Authors
- Name
- Robin te Hofstee
- @Robin_teHofstee
dmenu Tutorial: Complete Guide
What is dmenu?
dmenu
is a dynamic menu for X, originally designed for dwm. It's a fast, lightweight, and keyboard-driven application launcher and general-purpose menu system. dmenu reads a list of items from stdin and displays them as a menu, allowing you to select one using keyboard input.
Key Features
- Extremely fast and lightweight (less than 2000 lines of code)
- Keyboard-driven for efficient workflow
- Flexible input - accepts any list via stdin
- Fuzzy matching for quick filtering
- Highly customizable appearance and behavior
- Scriptable - can be used in shell scripts for interactive menus
Installation
From Source (Suckless Way)
# Clone the repository
git clone https://git.suckless.org/dmenu
# Navigate to directory
cd dmenu
# Edit config.h to customize (optional)
vim config.h
# Compile and install
sudo make clean install
From Package Manager
# Debian/Ubuntu
sudo apt install dmenu
# Arch Linux
sudo pacman -S dmenu
# Fedora
sudo dnf install dmenu
Basic Usage
1. Launch dmenu as application launcher
dmenu_run
This shows all executables in your $PATH
and launches the selected one.
2. Basic dmenu syntax
echo -e "Option 1\nOption 2\nOption 3" | dmenu
Displays a menu with three options and returns the selected one.
3. Use dmenu output in a script
choice=$(echo -e "Yes\nNo" | dmenu -p "Continue?")
echo "You selected: $choice"
Command-Line Options
Option | Description |
---|---|
-b | Display at bottom of screen |
-f | Fast mode (grab keyboard before reading stdin) |
-i | Case-insensitive matching |
-l <lines> | Display as vertical list with specified lines |
-p <prompt> | Set prompt text |
-fn <font> | Set font |
-nb <color> | Normal background color |
-nf <color> | Normal foreground color |
-sb <color> | Selected background color |
-sf <color> | Selected foreground color |
-w <windowid> | Embed into window |
Example with options
echo -e "Red\nGreen\nBlue" | dmenu -i -p "Choose color:" -l 10
Keyboard Controls
While dmenu is open:
Key | Action |
---|---|
Type text | Filter items |
Enter | Select highlighted item |
Ctrl+j or Down | Move to next item |
Ctrl+k or Up | Move to previous item |
Ctrl+n | Move to next item (alternative) |
Ctrl+p | Move to previous item (alternative) |
Tab | Complete selection |
Shift+Tab | Complete selection (reverse) |
Ctrl+y | Paste from primary selection |
Ctrl+Y | Paste from clipboard |
Escape | Cancel/exit |
Ctrl+c | Cancel/exit |
Creating dmenu Scripts
Example 1: Simple Yes/No Prompt
#!/bin/bash
answer=$(echo -e "Yes\nNo" | dmenu -p "Are you sure?")
if [ "$answer" = "Yes" ]; then
echo "Confirmed!"
else
echo "Cancelled"
fi
Example 2: Application Launcher Menu
#!/bin/bash
choice=$(echo -e "Firefox\nTerminal\nFile Manager\nText Editor" | dmenu -i -p "Launch:")
case $choice in
"Firefox")
firefox &
;;
"Terminal")
kitty &
;;
"File Manager")
pcmanfm &
;;
"Text Editor")
gedit &
;;
esac
Example 3: Power Menu
#!/bin/bash
options="Shutdown\nReboot\nLogout\nSuspend\nLock"
chosen=$(echo -e "$options" | dmenu -i -p "Power Menu:")
case $chosen in
"Shutdown")
systemctl poweroff
;;
"Reboot")
systemctl reboot
;;
"Logout")
# For dwm
killall dwm
;;
"Suspend")
systemctl suspend
;;
"Lock")
slock
;;
esac
Example 4: WiFi Network Selector
#!/bin/bash
# Get list of WiFi networks
networks=$(nmcli -t -f SSID dev wifi list | sort -u)
# Show in dmenu
selected=$(echo "$networks" | dmenu -i -l 10 -p "Select WiFi:")
# Connect to selected network
if [ -n "$selected" ]; then
nmcli device wifi connect "$selected"
fi
Example 5: Bookmark Manager
#!/bin/bash
# File containing bookmarks (URL | Description format)
bookmarks="$HOME/.config/bookmarks.txt"
# Read bookmarks and select one
selection=$(cat "$bookmarks" | dmenu -i -l 20 -p "Bookmark:")
# Extract URL (before the |)
url=$(echo "$selection" | cut -d'|' -f1 | xargs)
# Open in browser
if [ -n "$url" ]; then
firefox "$url" &
fi
Bookmarks file format (~/.config/bookmarks.txt
):
https://github.com | GitHub
https://reddit.com | Reddit
https://youtube.com | YouTube
Example 6: File Browser
#!/bin/bash
# Start in home directory
dir="$HOME"
while true; do
# List directories and files
choice=$(ls -1p "$dir" | dmenu -i -l 20 -p "Browse: $dir")
# Exit if cancelled
[ -z "$choice" ] && exit
# Build full path
fullpath="$dir/$choice"
# If directory, cd into it
if [ -d "$fullpath" ]; then
dir="$fullpath"
# If file, open it
elif [ -f "$fullpath" ]; then
xdg-open "$fullpath"
exit
fi
done
Example 7: Clipboard History (with clipmenu)
#!/bin/bash
# Requires clipmenu package
# This is a pre-built solution that works with dmenu
# Store clipboard history
clipmenud &
# Show clipboard history
clipmenu
Example 8: Quick Notes
#!/bin/bash
notes_dir="$HOME/notes"
mkdir -p "$notes_dir"
action=$(echo -e "New Note\nView Note\nDelete Note" | dmenu -p "Notes:")
case $action in
"New Note")
note_name=$(echo "" | dmenu -p "Note name:")
[ -n "$note_name" ] && "$EDITOR" "$notes_dir/$note_name.txt"
;;
"View Note")
note=$(ls -1 "$notes_dir" | dmenu -l 20 -p "Select note:")
[ -n "$note" ] && "$EDITOR" "$notes_dir/$note"
;;
"Delete Note")
note=$(ls -1 "$notes_dir" | dmenu -l 20 -p "Delete note:")
[ -n "$note" ] && rm "$notes_dir/$note"
;;
esac
Example 9: Man Page Viewer
#!/bin/bash
# Get all man pages
man_page=$(man -k . | awk '{print $1}' | dmenu -i -l 20 -p "Man page:")
# Open selected man page in terminal
if [ -n "$man_page" ]; then
kitty -e man "$man_page"
fi
Example 10: Color Picker
#!/bin/bash
color=$(echo -e "#FF0000 Red\n#00FF00 Green\n#0000FF Blue\n#FFFF00 Yellow\n#FF00FF Magenta\n#00FFFF Cyan\n#000000 Black\n#FFFFFF White" | dmenu -i -l 10 -p "Pick color:")
# Copy color code to clipboard
color_code=$(echo "$color" | awk '{print $1}')
echo -n "$color_code" | xclip -selection clipboard
notify-send "Color copied: $color_code"
Integration with Window Managers
dwm Integration
dmenu is designed for dwm. In dwm's config.h
:
static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", dmenufont, "-nb", col_gray1, "-nf", col_gray3, "-sb", col_cyan, "-sf", col_gray4, NULL };
{ MODKEY, XK_p, spawn, {.v = dmenucmd } },
i3 Integration
Add to ~/.config/i3/config
:
bindsym $mod+d exec dmenu_run
bindsym $mod+Shift+d exec /path/to/your/dmenu-script.sh
General Keybinding (with sxhkd)
# In ~/.config/sxhkd/sxhkdrc
super + d
dmenu_run
super + shift + d
~/scripts/power-menu.sh
Advanced Tips
1. Custom dmenu_run Wrapper
Create ~/bin/mydmenu
:
#!/bin/bash
dmenu_run -i -fn "JetBrains Mono-12" -nb "#282828" -nf "#ebdbb2" -sb "#458588" -sf "#ebdbb2" -p "Run:"
2. Use with xargs for Batch Operations
# Select multiple files and delete them
ls | dmenu -l 20 | xargs rm
3. Dynamic Font Sizing
#!/bin/bash
# Get screen width
width=$(xrandr | grep '*' | awk '{print $1}' | cut -d'x' -f1 | head -1)
# Adjust font based on screen
if [ "$width" -gt 1920 ]; then
font_size=14
else
font_size=10
fi
dmenu_run -fn "monospace-$font_size"
4. Colorize Output Based on Selection
#!/bin/bash
choice=$(echo -e "Success\nWarning\nError" | dmenu -p "Type:")
case $choice in
"Success")
notify-send -u normal "✓ Success"
;;
"Warning")
notify-send -u normal "⚠ Warning"
;;
"Error")
notify-send -u critical "✗ Error"
;;
esac
Customization
Edit config.h Before Compiling
/* appearance */
static const char *fonts[] = { "monospace:size=10" };
static const char *prompt = NULL;
static const char *colors[SchemeLast][2] = {
/* fg bg */
[SchemeNorm] = { "#bbbbbb", "#222222" },
[SchemeSel] = { "#eeeeee", "#005577" },
[SchemeOut] = { "#000000", "#00ffff" },
};
/* -l option; if nonzero, dmenu uses vertical list with given number of lines */
static unsigned int lines = 0;
/* -b option; if 1, dmenu appears at bottom */
static int topbar = 1;
After editing, recompile:
sudo make clean install
Common Use Cases
1. Quick Launcher
dmenu_run -i -p "Run:"
2. Window Switcher (with wmctrl)
wmctrl -l | dmenu -l 10 | awk '{print $1}' | xargs wmctrl -ia
3. Process Killer
ps aux | dmenu -l 20 | awk '{print $2}' | xargs kill
4. SSH Connection Menu
host=$(cat ~/.ssh/config | grep "^Host " | cut -d' ' -f2 | dmenu -p "SSH to:")
[ -n "$host" ] && kitty -e ssh "$host"
5. Screenshot Tool
choice=$(echo -e "Fullscreen\nSelect Area\nCurrent Window" | dmenu -p "Screenshot:")
case $choice in
"Fullscreen")
scrot ~/Pictures/screenshot.png
;;
"Select Area")
scrot -s ~/Pictures/screenshot.png
;;
"Current Window")
scrot -u ~/Pictures/screenshot.png
;;
esac
Troubleshooting
dmenu not showing
- Check if X server is running:
echo $DISPLAY
- Try running with verbose errors:
dmenu 2>&1
Wrong colors
- Check your terminal color settings
- Verify color codes in config.h or command line
Items not appearing
- Check if stdin is properly formatted
- Try:
echo -e "test1\ntest2" | dmenu
Font not found
- Install the font specified in config.h
- Or change to an installed font:
fc-list
to see available fonts
Best Practices
- Keep scripts simple - dmenu is meant to be lightweight
- Use
-i
flag for case-insensitive matching - Test with echo before using in scripts
- Add error handling in scripts
- Use meaningful prompts with
-p
flag - Consider vertical layout (
-l
) for long lists - Make scripts executable:
chmod +x script.sh
- Store scripts in
~/bin
or~/.local/bin
Resources
- Official site: https://tools.suckless.org/dmenu
- Source code: https://git.suckless.org/dmenu
- Man page:
man dmenu
- dwm website: https://dwm.suckless.org
Pro Tip: dmenu is the Swiss Army knife of menus. Anything that outputs text can be turned into an interactive menu with dmenu!