How to Use fzf with tmux Popup Windows via the --tmux Option

Use fzf --tmux to open the fuzzy finder inside a tmux popup window instead of taking over the entire terminal, specifying optional dimensions and position with a comma-separated spec like fzf --tmux=up,70%.

The junegunn/fzf command-line fuzzy finder traditionally occupies the full terminal screen, but starting with version 0.53.0, it supports embedding its interface directly inside tmux popup windows. This allows you to maintain your pane layout while using fzf, controlled via the --tmux command-line option that delegates UI rendering to tmux's display-popup command.

How the --tmux Option Works in fzf

When you append the --tmux flag, fzf bypasses its standard full-screen terminal UI and instead instructs tmux to create a temporary popup window. The implementation involves two main phases: parsing the user specification and constructing the tmux command.

Parsing Tmux Options

The command-line parser in src/options.go declares the --tmux flag and delegates value parsing to parseTmuxOptions in src/tmux.go (lines 15-88). This function populates a tmuxOptions struct that stores:

  • Width and height (as percentages or absolute values)
  • Screen position (up, down, left, right, or center)
  • Border preference (native tmux border or none)

If the --tmux flag is omitted, this struct remains nil and fzf executes its standard full-screen behavior.

Building the tmux display-popup Command

The runTmux function (also in src/tmux.go, lines 10-73) constructs the actual tmux command. It builds a slice of arguments for tmux display-popup based on the parsed options:

tmuxArgs := []string{"display-popup", "-E", "-d", dir}
if !opts.Tmux.border { tmuxArgs = append(tmuxArgs, "-B") }
switch opts.Tmux.position {
case posUp:    tmuxArgs = append(tmuxArgs, "-xC", "-y0")
case posDown:  tmuxArgs = append(tmuxArgs, "-xC", "-y9999")
case posLeft:  tmuxArgs = append(tmuxArgs, "-x0", "-yC")
case posRight: tmuxArgs = append(tmuxArgs, "-xR", "-yC")
case posCenter:tmuxArgs = append(tmuxArgs, "-xC", "-yC")
}
tmuxArgs = append(tmuxArgs,
    "-w"+opts.Tmux.width.String(),
    "-h"+opts.Tmux.height.String(),
)

The -E flag tells tmux to close the popup when the command exits, while -B disables the native border when border is set to native in the fzf options. The -x and -y coordinates position the popup relative to the screen or pane.

Because the popup provides an isolated environment, fzf automatically appends --no-tmux --no-height to its own arguments when executing inside the popup, preventing recursive tmux handling and full-screen layout conflicts.

Requirements for fzf tmux Popup Support

To use the --tmux option, your environment must meet these criteria:

  • tmux version 3.2 or later (popup support was introduced in tmux 3.2).
  • fzf version 0.53.0 or later (the --tmux flag was introduced in this release).
  • The tmux binary must be available in your $PATH when executing fzf.

Practical Examples: Using fzf --tmux

These commands demonstrate common usage patterns for opening fzf inside tmux popups:


# 1️⃣  Simple centered popup (default 50% of both dimensions)

fzf --tmux

# 2️⃣  Popup anchored at the top of the screen, 70% height, full width

fzf --tmux=up,100%,70%

# 3️⃣  Popup on the right side, 40% width, 60% height

fzf --tmux=right,40%,60%

# 4️⃣  Popup on the left, 30% width, native tmux border

fzf --tmux=left,30%,border-native

# 5️⃣  Split pane above the current pane (behaviour of the older fzf-tmux script)

fzf --tmux=up

# 6️⃣  Use a custom directory for the popup (relative to current working dir)

cd /var/log
fzf --tmux=down,80%   # opens in a popup showing files from /var/log

The comma-separated specification follows the format position,width,height,border where:

  • position: up, down, left, right, or center
  • width/height: percentages (e.g., 50%) or absolute cell counts
  • border: border-native to use tmux's native border, or omit for no border

Summary

  • The --tmux option in fzf 0.53.0+ opens the fuzzy finder inside a tmux popup rather than the full terminal.
  • The parseTmuxOptions function in src/tmux.go handles the comma-separated specification for position, size, and borders.
  • The runTmux function constructs a tmux display-popup command with coordinates calculated for up, down, left, right, or center placement.
  • Requirements include tmux 3.2+ and fzf 0.53.0+; the feature automatically disables fzf's internal tmux handling when running inside the popup.

Frequently Asked Questions

What tmux version is required for fzf --tmux?

You need tmux version 3.2 or later. The display-popup command that fzf relies on for the --tmux feature was introduced in tmux 3.2. Earlier versions will not recognize the popup syntax and the command will fail.

How do I position the fzf popup window in tmux?

Use the first component of the --tmux specification to set the position: up, down, left, right, or center. For example, fzf --tmux=up,100%,50% anchors the popup at the top of the screen with full width and half height. The runTmux function in src/tmux.go translates these keywords into -x and -y coordinates for the tmux display-popup command.

Can I use fzf --tmux without borders?

Yes. By default, fzf requests tmux to draw no border around the popup. If you want the native tmux border instead, add border-native to the specification: fzf --tmux=center,50%,50%,border-native. Internally, this omits the -B flag from the tmux display-popup arguments constructed in src/tmux.go.

What is the difference between fzf --tmux and the fzf-tmux script?

The fzf-tmux script located at bin/fzf-tmux is a legacy shell script that creates tmux split panes (horizontal or vertical) to run fzf. The --tmux option is a native Go implementation introduced in fzf 0.53.0 that uses tmux's display-popup feature instead of splits. Popups are temporary, floating windows that do not alter your pane layout, whereas splits permanently divide the screen until closed.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →