Posting sporadically since 2007...

Vifm Fuzzy Find in tmux Popup Window with fzf and fd

Terminal tools

A few years ago I began to rely heavily on Vim and now I can’t think of ever going back to working with code/text files in permanent “Insert” mode (want to learn some Vim?).

After switching to Vim/Neovim, I started to spend more time in the terminal and eventually settled on this set of awesome console tools: tmux (sessions, windows, panes), fzf (fuzzy search), ripgrep (better grep), fd (better find), bat (better cat) and Vifm (file manager).

Out of these, Vifm is the most niche but if you enjoy Vim motions and like the classic left-right file manager layout, you should give it a try! The amount of features and depth of documentation are nothing short of amazing!

In this post, I’ll show a recipe for combining Vifm, tmux, fzf and fd for very quick and convenient fuzzy file search inside a terminal popup window.

Note: I’ve tested it in Zsh with Ubuntu 24.04 (standalone) and on Ubuntu 22.04 on Windows 11 (WSL) with Vifm 0.14.3, tmux 3.2a, fzf 0.67.0 and fd 10.2.0.

Version 3.2 of tmux introduced display-popup command, it lets you show a floating and resizable window on top of the current tmux window.

Here’s how you could show a list of files in current directory:

display-popup -E 'ping en.morzel.net'

Popup window in tmux. Click to enlarge...
Tip: To run a command in tmux you should type your prefix (by default it’s Ctrl+b but I prefer Ctrl+Space) and then type the command (you will notice : added when you switch to command mode). You can also achieve the same effect by running command tmux display-popup -E 'ping en.morzel.net' in shell.

Nothing beats the convenience of fuzzy find. Wouldn’t it be nice if you could use fzf to look for files within Vifm with the nice UX of modern TUI?

Keybind to invoke Vifm script

Vifm has a scripts directory intended for custom scripts, located in the same folder as the vifmrc configuration file (usually ~/.vifm/ or ~/.config/vifm).

This keybind executes a script from within Vifm, passing the current directory and server name:

nnoremap f :!~/.vifm/scripts/vifm_tmux_fzf_fd_search.sh "%d" <c-r>=fnameescape(v:servername)<cr> &<cr>

“Vifm server”, the what now? No worries, you don’t have to install anything - it’s just a way for Vifm to receive commands. You may have multiple instances of Vifm running and passing a server name ensures that the script for file search will return a value to the correct instance.

Script that combines tmux, fzf, fd and Vifm

The script below uses tmux display-popup, runs fzf on top of the fd command output (instead of the default find) and returns the result back to Vifm:

#!/usr/bin/zsh

readonly LOG_FILE="/tmp/vifm_tmux_fzf_fd_search.log"

{
  echo "--- Script started at $(date) ---"
  echo "Raw Arg 1 (Dir): ${1:-[MISSING]}"
  echo "Raw Arg 2 (Server): ${2:-[MISSING]}"
} > "$LOG_FILE"

TARGET_DIR="${1:?Error: Target directory (arg 1) is missing}"
TARGET_SERVER="${2:?Error: Vifm server name (arg 2) is missing}"

tmpfile=$(mktemp)
trap 'rm -f "$tmpfile"' EXIT

if [[ -n "${TMUX:-}" ]]; then
    echo "Environment: tmux popup" >> "$LOG_FILE"

    tmux display-popup -E -w 80% -h 80% -d "$TARGET_DIR" \
        "fd --type f --type d --hidden --exclude .git | fzf > $tmpfile"

    if [[ -s "$tmpfile" ]]; then
        selection=$(<"$tmpfile")
        echo "Selected: $selection" >> "$LOG_FILE"
        vifm --server-name "$TARGET_SERVER" --remote -c "goto \"$TARGET_DIR/$selection\"" >> "$LOG_FILE" 2>&1
    else
        echo "Status: No selection made or popup cancelled" >> "$LOG_FILE"
    fi
else
    echo "Error: TMUX environment variable not found. Script must be run inside a tmux session." >> "$LOG_FILE"
    echo "Script exiting: No tmux session detected." >&2
    exit 1
fi

Result

With the keybind and script, pressing the f key will give you such a nice popup window to pick a file or directory:

Vfim with tmux popup for fzf. Click to enlarge...

How does it work?

The keymap invokes a script passing the current location and name of Vifm server (thanks to xaizek for help with that).

Tip: You can list names of Vifm servers with vifm --server-list command in your shell or you can run echo v:servername command in Vifm to get current server name.

The Zsh script does these simple steps:

  • Take arguments passed from Vifm (command run from keybind)
  • Make a temporary file (it will be used to pass fzf choice back to Vifm).
  • First if checks if Vifm works inside tmux
  • Invoke tmux display-popup command to show results of running fzf on top of fd file/directory search result. The fd command is configured in such a way that hidden files (e.g. configs starting with dot) are included but .git directory is skipped (fd automatically skips files from .gitignore)
  • Second if block verifies if the file with choice from fzf was created and if so sends the choice back to the correct instance of Vifm thanks to --server-name and --remote arguments passed to vifm.

The ultimate result is that Vifm navigates to the item chosen in fzf and has it as active so you can invoke actions on it.

Logging

As you see, I didn’t put comments in the script, I usually prefer to add logging instead. Reading messages passed to echo is just as helpful as reading comments and if something goes wrong you will have a way to troubleshoot it. Here’s a sample /tmp/vifm_tmux_fzf_fd_search.log content for script execution that happened outside of tmux:

--- Script started at Mon Mar 30 22:33:21 CEST 2026 ---
Raw Arg 1 (Dir): /home/gby
Raw Arg 2 (Server): vifm2
Error: TMUX environment variable not found. Script must be run inside a tmux session.

Possible enhancements

  • You might want to invoke the cd command if the selected item is a directory to have it automatically opened (I prefer to just have it highlighted).
  • You could have a separate binding for searching folders and files.
  • Script could attempt to run fzf without popup if tmux is not detected, or you can have a separate binding that does a plain fzf run without tmux or external script.

Summary

We’ve learned how to use tmux popup windows, how to add key bindings in Vifm and how to invoke scripts that pass data back to the correct instance of Vifm. Not bad, this will come in handy.