Mastering the preview window: turning it on with the preview option, setting the pane's position and size, using dynamic placeholders, and displaying file contents with bat, rich, images, and execute actions directly from fzf.

Episode 9 made fzf complete commands; episode 10 makes fzf explain. The preview window is a second pane beside the list that shows details of the currently highlighted item — file contents, metadata, images, even another command's output — in real time. A direct example: fzf --preview 'cat {}'.
This is the feature that turns fzf from a blind picker into an informed peek-a-boo viewer. Before selecting a file, you already see its contents; before running a process, you already see its relationship. Decisions are no longer guessed — they're verified first.
The preview window works on a simple principle: every time the pointer moves to a new item, fzf runs the preview command for that item and displays the result. This command is set with --preview, and the displayed content can come from anything a command can print.
fzf --preview 'bat --color=always --style=numbers {}'Here {} is a placeholder that gets replaced with the text of the currently highlighted item. When you move down a line, bat runs again for the file on that line. Because bat supports ANSI, combine it with --ansi from episode 6 so the colors show: fzf --ansi --preview 'bat --color=always {}'.
--preview OptionThe basic form is --preview 'command {}' — fzf executes the command through the shell for every active item. Three things to remember:
sh -c), so pipelines like cat {} | head -50 are valid.{} is replaced with the currently highlighted item, not the selected one.A directory metadata preview example using flags from episode 6:
fzf --preview 'ls -la {}'--preview-windowThe pane's position, size, and behavior are set with --preview-window. Its format: POSITION,SIZE,FLAG. Some of the most common combinations:
| Value | Effect |
|---|---|
right,50% | On the right, half width (default) |
up,30% | On top, 30% height |
down,10 | At the bottom, 10 lines |
left | On the left |
wrap | Wrap long lines (default: truncated) |
hidden | Hidden first, appears via toggle |
+{2} | Initial scroll follows the line number in field 2 |
fzf --preview 'cat {}' --preview-window 'down,30%,wrap'Tip
The CTRL-/ key (or F3) toggles the preview window by default: hiding and showing it again. With --preview-window 'right,50%,hidden', the preview takes no space until you need it — a comfortable combination for small screens.
Placeholders are the heart of the preview. Besides {}, fzf recognizes several forms:
| Placeholder | Meaning |
|---|---|
{} | The whole text of the currently highlighted item |
{1} | The item's first field (uses --delimiter) |
{q} | The query text being typed |
{n} | The item's sequence number (zero-based) |
{+} | All multi-selected items, space-separated |
{+n} | The sequence numbers of all selected items |
The most commonly used example is {q} to make the preview respond to the query — not just the active item. This is the foundation for building a file-content search (refined in episode 11):
fzf --preview 'rg --color=always -C 2 {q} {}' --ansiAs you type, rg searches that pattern in the currently highlighted file and shows the context around matches. With {+}, a multi-select preview can accept the whole selection as arguments:
fzf --multi --preview 'tail -5 {+}'Important
The {} and {q} placeholders are expanded by fzf, not by the shell. That's why you shouldn't quote them with single quotes inside the preview command, and why the --preview option must be quoted on the outside (e.g. --preview 'head {}') so fzf receives the intact string and then replaces its own placeholders.
bat and richFor code and Markdown files, the most productive preview has syntax highlighting. Two tools are commonly used:
| Tool | Advantage |
|---|---|
bat | Syntax highlighting, line numbers, git detection, line shortening |
rich | Text/Markdown preview with rich rendering and tables |
An example for code files:
fzf --preview 'bat --color=always --style=numbers --line-range=:200 {}'--line-range=:200 limits the preview to the first 200 lines so it stays fast on giant files. For Markdown, rich renders headings, lists, and code blocks with visual formatting:
fzf --preview 'rich {}'The preview window can also display images — depending on the protocol the terminal supports. Three common approaches:
| Method | Terminal | Command |
|---|---|---|
| Kitty graphics | Kitty | kitten icat --place={W}x{H}@0x0 {} |
| iTerm2 inline image | iTerm2 | imgcat {} |
| Chafa / Sixel | Common terminals | chafa {} |
The easiest example that works in many terminals is chafa (turning images into character blocks):
fzf --preview 'chafa {}'Note
Image support requires a terminal that speaks a graphics protocol (Kitty/Sixel). If the image doesn't appear, check that the preview runs in the same terminal as fzf, and remember: the terminal determines the method, fzf just runs the command. file {} can be a quick fallback for identifying binary files without a special protocol.
executeThe preview not only displays — it can become a trigger for actions. With --bind, you can execute a command when a key is pressed, and the result doesn't "break" the interface:
fzf --bind 'enter:execute(nvim {})'Pressing Enter opens nvim with the highlighted file — while fzf keeps running behind it until the editor closes. Important variations:
| Action | Behavior |
|---|---|
execute(cmd) | Run it, then show the output in place of fzf |
execute-silent(cmd) | Run it without showing output |
become(cmd) | Replace the fzf process with cmd (when done) |
A real become example for the "select then open" flow:
fzf --bind 'enter:become(nvim {})'The key difference: execute returns to fzf after the command finishes; become closes fzf and hands the terminal to the replacement command — a pattern that feels seamless for opening editors. The combination --preview + --bind 'enter:execute(...)' is the foundation of many interactive tools built on top of fzf.
Episode 10 gave you a second pair of eyes: turning on the preview with --preview, configuring the pane with --preview-window (position, size, wrap, hidden), dynamic placeholders ({}, {1}, {q}, {n}, {+}, {+n}), rich content with bat and rich, image preview via Kitty/iTerm2/chafa, and direct actions with execute, execute-silent, and become.
The key takeaways:
--preview 'command {}' runs a command for the highlighted item.--preview-window sets position, size, wrap, and hidden; CTRL-/ toggles it.{}, {q}, {+}, and {n} make the preview dynamic, following the item, query, and selection.bat/rich for code & Markdown; chafa/Kitty/iTerm2 for images; execute/become for actions.In episode 11, we will combine all of fzf's power with two tools from its ecosystem: fd for fast file search that respects .gitignore, and ripgrep for content search — producing the fastest search workflow you've ever had. See you in episode 11!