tmenu is a minimal X11 menu launcher written in POSIX C99. It reads a newline-delimited list of items from stdin, lets you filter by typing, and executes the selected entry via /bin/sh -c.
The entire implementation fits in a single source file and under 250 lines. The only runtime dependency is Xlib.
- Overview
- Requirements
- Installation
- Usage
- Key Bindings
- Configuration
- Contributing
- Related Projects
- License
tmenu follows the suckless philosophy: small, auditable, compile-time configured. There is no config file parser, no IPC, no scripting layer, and no hidden complexity. Read the source - understand the program.
Key properties:
- Single source file, under 250 lines of C99
- Pure Xlib - no Xft, no Xinerama, no fontconfig
- All settings defined at the top of
tmenu.c, applied at compile time - Keyboard focus on launch — start typing immediately
- Executes the selected item or typed text directly via
/bin/sh -c
Compared to dmenu: no external launcher wrapper required, smaller codebase, no Xft dependency.
Supported platforms: Linux (Arch, Void, Debian), OpenBSD, FreeBSD, NetBSD, macOS (XQuartz), and any POSIX system with X11.
| Dependency | Arch Linux | Debian / Ubuntu |
|---|---|---|
| Xlib | libx11 |
libx11-dev |
| C compiler | gcc |
build-essential |
No other libraries are needed at runtime.
git clone https://github.com/tinyopsec/tmenu
cd tmenu
make
sudo make installInstalls to /usr/local/bin/tmenu. To change the install prefix:
sudo make install PREFIX=/usryay -S tmenusudo make uninstalltmenu reads newline-delimited items from stdin, filters them interactively, and executes the selected entry via /bin/sh -c.
Use the bundled launcher:
tmenu_runOr provide input manually:
printf "st\nfirefox\nhtop\n" | tmenuSelect an item with arrow keys and press Enter to execute.
If the input does not match any item, the typed text is executed directly as a shell command.
tmenu is typically used as an application launcher.
In your config (e.g. swm.h, dwm/config.h):
static const char *dmenucmd[] = { "tmenu_run", NULL };Recompile your WM:
make && sudo make installAfter this, your launcher keybinding (usually Mod + d) will invoke tmenu_run.
If tmenu_run is installed in ~/.local/bin:
export PATH="$HOME/.local/bin:$PATH"Ensure this is set before your window manager starts (e.g. in .xinitrc), otherwise the launcher will fail silently.
# optional: extend PATH for local binaries
export PATH="$HOME/.local/bin:$PATH"
# background services
picom &
feh --bg-scale ~/wallpaper.png &
exec swm| Option | Description |
|---|---|
-b |
Show menu at the bottom (default: top) |
-l N |
Vertical list with N visible lines |
-p text |
Prompt displayed to the left of the input field |
Vertical launcher with prompt:
printf "st\nfirefox\nthunderbird\n" | tmenu -l 5 -p "run: "Power menu:
printf "suspend\nreboot\npoweroff\n" | tmenu -p "power: "Bottom-aligned menu:
printf "lock\nlogout\n" | tmenu -b -p "session: "Check that the launcher is available:
which tmenu_runRun directly:
tmenu_runIf nothing happens on keybind — verify:
$PATH- WM config (
dmenucmd) - binary permissions (
chmod +x)
- Input source:
stdin - Selection: keyboard (filter + navigation)
- Execution:
/bin/sh -c - Fallback: executes raw input if no match
Navigate with arrow keys or filter by typing. Press Enter to execute the selected item. If the typed text does not match any item, Enter executes it directly as a shell command.
| Option | Description |
|---|---|
-b |
Show menu at the bottom of the screen (default: top) |
-l N |
Show a vertical list with N visible lines |
-p text |
Display a prompt to the left of the input field |
Vertical list with a prompt:
printf "st\nfirefox\nthunderbird\n" | tmenu -p "run: " -l 5Bottom-aligned horizontal menu:
printf "suspend\nreboot\npoweroff\n" | tmenu -b -p "power: "| Key | Action |
|---|---|
Enter / KP_Enter |
Execute selected item or typed text |
Escape |
Exit without executing |
BackSpace |
Delete character left of cursor |
Up / Left |
Move selection up or left |
Down / Right |
Move selection down or right |
Ctrl+U |
Clear entire input field |
Ctrl+W |
Delete one word left of cursor |
Ctrl+K |
Select next item (vertical list) |
Ctrl+J |
Select previous item (vertical list) |
Key handling is a straightforward switch in tmenu.c. To remap keys, edit the source and recompile.
tmenu has no runtime configuration file. All settings are defined as macros at the top of tmenu.c and take effect after recompilation:
$EDITOR tmenu.c
make && sudo make install| Setting | Default | Description |
|---|---|---|
FONT |
"-*-fixed-medium-r-*-*-13-*-*-*-*-*-*-*" |
X11 core font string |
FGNORM |
"#bbbbbb" |
Normal item foreground color |
BGNORM |
"#222222" |
Normal item background color |
FGSEL |
"#eeeeee" |
Selected item foreground color |
BGSEL |
"#005577" |
Selected item background color |
TOP |
1 |
1 = top of screen, 0 = bottom |
LINES |
0 |
Default line count (0 = horizontal) |
PROMPT |
NULL |
Default prompt string |
To increase the maximum number of items or input length, adjust MAXITEMS and MAXTEXT in tmenu.c.
Bug reports and patches are welcome via GitHub issues and pull requests.
- No comments in production code
- No external dependencies beyond Xlib
- No unnecessary abstraction
- Compiles clean:
gcc -std=c99 -pedantic -Wall -Wextra - Total source must remain under 300 lines
Features are added by patching the source, not by adding runtime options. Changes that require a config file or a new library dependency will not be accepted.
| Project | Description | Link |
|---|---|---|
| dmenu | The original dynamic menu for X | suckless.org |
| suckless.org | Philosophy and tooling behind tmenu | suckless.org |
| Xlib manual | Reference for X11 programming | x.org |
MIT. See LICENSE for details.
