Rofi: a window switcher, application launcher and dmenu replacement

2021/03/14 by Paulo Pereira

~/categories/Linux #Linux #Arch Linux #i3-gaps #Rofi

Rofi is a window switcher, application launcher and dmenu replacement.

I’ve been using rofi with i3-gaps since early 2019. I had played with it before, but I’ve been using it daily the last couple of years.

I use it to launch applications, open ssh sessions, with pass and with a set of useful custom scripts.


You need to install the rofi package. I also installed rofi-dmenu for dmenu compatibility, rofi-pass to use with pass and the extra rofi-emoji and rofi-calc.

paru -S rofi rofi-dmenu rofi-pass rofi-emoji rofi-calc


You can run Rofi in different modes depending if you want to launch an application, open a ssh session, change windows or executing a command in the terminal.

Check Rofi at github and man rofi for more details.

In my setup, and using i3-gaps (learn more here) I use it to accomplish a series of tasks:

bindsym    $mod+d     exec --no-startup-id "rofi -modi combi -show combi -combi-modi drun,run"


bindsym    $mod+p    exec --no-startup-id rofi-pass


bindsym    $mod+s    exec --no-startup-id rofi -show ssh
bindsym    $mod+f    exec --no-startup-id websearch


Here’s my websearch script, inspired by ditrotube.

cat .local/bin/websearch

#!/usr/bin/env bash


declare -a options=(
"searx -"
"amazon -"
"kindlebooks -"
"youtube -"
"goodreads -"
"archaur -"
"archpkg -"
"archwiki -"
"audible -"
"duckduckgo -"
"github -"
"gitlab -"
"google -"
"reddit -"

while [ -z "$engine" ]; do
  enginelist=$(printf '%s\n' "${options[@]}" | rofi -dmenu -p 'Choose search engine:') || exit
  engineurl=$(echo "$enginelist" | awk '{print $NF}')
  engine=$(echo "$enginelist" | awk '{print $1}')

while [ -z "$query" ]; do
  if [[ "$engine" == "quit" ]]; then
    echo "Program terminated." && exit 0
    query=$(echo "$engine" | rofi -dmenu -p 'Enter search query:') || exit

$DMBROWSER "$engineurl""$query"



The rofi configuration file is located at .config/rofi/config.rasi.

cat .config/rofi/config.rasi

configuration {
    modi:                   "run,ssh,window,combi,drun,windowcd";
    matching:               "fuzzy";
    show-icons:             true;
    theme:                  "~/.config/rofi/themes/dmenu.rasi";
    font:                   "Cantarell Regular 11";
    icon-theme:             "oomox-gruvbox-dark";
    lines:                  7;
    separator-style:        "solid";
    hide-scrollbar:         true;
    kb-row-down:            "Control+j";
    kb-row-up:              "Control+k";
    kb-accept-entry:        "Return,KP_Enter";
    kb-remove-to-eol:       "";
    display-drun:           "Open";
    display-run:            "❯ sh";
    display-combi:          "";
    display-window:         "Change window";
    display-windowcd:       "Change window (same workspace)";
    terminal:               "/usr/bin/alacritty";
    ssh-command:            "{terminal} -e {ssh-client} {host}";

I’m using a theme to emulate dmenu, but I used a gruvbox inspired on until recently.

cat .config/rofi/themes/dmenu.rasi

* {
    background-color:   Black;
    border-color:       White;
    text-color:         White;
    font:               "Cantarell Regular 12";

#window {
    anchor:     north;
    location:   north;
    width:      100%;
    padding:    4px;
    children:   [ horibox ];

#horibox {
    orientation: horizontal;
    children:   [ prompt, entry, listview ];

#listview {
    layout:     horizontal;
    spacing:    5px;
    lines:      100;

#entry {
    expand:     false;
    width:      10em;

#element {
    padding: 0px 2px;
#element selected {
    background-color: SteelBlue;
cat .config/rofi/themes/

window {
    background-color: @background;
    border:           2;
    padding:          2;

mainbox {
    border:  0;
    padding: 0;

message {
    border:       2px 0 0;
    border-color: @separatorcolor;
    padding:      1px;

textbox {
    highlight:  @highlight;
    text-color: @foreground;

listview {
    border:       2px solid 0 0;
    padding:      2px 0 0;
    border-color: @separatorcolor;
    spacing:      2px;
    scrollbar:    @scrollbar;

element {
    border:  0;
    padding: 2px;

element.normal.normal {
    background-color: @normal-background;
    text-color:       @normal-foreground;

element.normal.urgent {
    background-color: @urgent-background;
    text-color:       @urgent-foreground;
} {
    background-color: @active-background;
    text-color:       @active-foreground;

element.selected.normal {
    background-color: @selected-normal-background;
    text-color:       @selected-normal-foreground;

element.selected.urgent {
    background-color: @selected-urgent-background;
    text-color:       @selected-urgent-foreground;
} {
    background-color: @selected-active-background;
    text-color:       @selected-active-foreground;

element.alternate.normal {
    background-color: @alternate-normal-background;
    text-color:       @alternate-normal-foreground;

element.alternate.urgent {
    background-color: @alternate-urgent-background;
    text-color:       @alternate-urgent-foreground;
} {
    background-color: @alternate-active-background;
    text-color:       @alternate-active-foreground;

scrollbar {
    width:        4px;
    border:       0;
    handle-color: @scrollbar-handle;
    handle-width: 8px;
    padding:      0;

sidebar {
    border:       2px 0 0;
    border-color: @separatorcolor;

inputbar {
    spacing:    0;
    text-color: @normal-foreground;
    padding:    2px;
    children:   [ prompt, textbox-prompt-sep, entry, case-indicator ];

button {
    spacing:    0;
    text-color: @normal-foreground;

button.selected {
    background-color: @selected-normal-background;
    text-color:       @selected-normal-foreground;

textbox-prompt-sep {
    expand:     false;
    str:        ":";
    text-color: @normal-foreground;
    margin:     0 0.3em 0 0;
cat .config/rofi/themes/gruvbox-dark.rasi

* {
    /* Theme settings */
    highlight: bold italic;
    scrollbar: true;

    /* Gruvbox dark colors */
    gruvbox-dark-bg0:          #282828;
    gruvbox-dark-bg0-soft:     #32302f;
    gruvbox-dark-bg3:          #665c54;
    gruvbox-dark-fg0:          #fbf1c7;
    gruvbox-dark-fg1:          #ebdbb2;
    gruvbox-dark-red-dark:     #cc241d;
    gruvbox-dark-red-light:    #fb4934;
    gruvbox-dark-yellow-dark:  #d79921;
    gruvbox-dark-yellow-light: #fabd2f;
    gruvbox-dark-gray:         #a89984;

    /* Theme colors */
    background:                  @gruvbox-dark-bg0;
    background-color:            @background;
    foreground:                  @gruvbox-dark-fg1;
    border-color:                @gruvbox-dark-gray;
    separatorcolor:              @border-color;
    scrollbar-handle:            @border-color;

    normal-background:           @background;
    normal-foreground:           @foreground;
    alternate-normal-background: @gruvbox-dark-bg0-soft;
    alternate-normal-foreground: @foreground;
    selected-normal-background:  @gruvbox-dark-bg3;
    selected-normal-foreground:  @gruvbox-dark-fg0;

    active-background:           @gruvbox-dark-yellow-dark;
    active-foreground:           @background;
    alternate-active-background: @active-background;
    alternate-active-foreground: @active-foreground;
    selected-active-background:  @gruvbox-dark-yellow-light;
    selected-active-foreground:  @active-foreground;

    urgent-background:           @gruvbox-dark-red-dark;
    urgent-foreground:           @background;
    alternate-urgent-background: @urgent-background;
    alternate-urgent-foreground: @urgent-foreground;
    selected-urgent-background:  @gruvbox-dark-red-light;
    selected-urgent-foreground:  @urgent-foreground;

@import ""