# How fzf Preview Window Rendering Works Across Different Terminal Emulators

> Discover how fzf preview window rendering works across diverse terminal emulators. Learn about pane creation, output drawing, and escape sequence forwarding.

- Repository: [Junegunn Choi/fzf](https://github.com/junegunn/fzf)
- Tags: internals
- Published: 2026-03-01

---

**fzf renders its preview window by creating a dedicated pane, executing the preview command, and drawing the output with ANSI-aware text wrapping, while transparently forwarding terminal-specific graphics escape sequences (Kitty, iTerm2, Sixel, tmux) to the underlying emulator.**

The `junegunn/fzf` command-line fuzzy finder uses a sophisticated three-stage pipeline to render preview content in any terminal emulator. Whether displaying plain text or rich graphics, fzf adapts to the capabilities of your terminal while maintaining its own UI layout integrity.

## How fzf Creates and Sizes the Preview Window

When fzf initializes its interface, it first determines whether a preview pane is required by checking the `needPreviewWindow` condition. If enabled, the `resizePreviewWindows` closure in **[`src/terminal.go`](https://github.com/junegunn/fzf/blob/main/src/terminal.go)** (lines [2318‑2376](https://github.com/junegunn/fzf/blob/master/src/terminal.go#L2318-L2376)) calculates the dimensions based on the `--preview-window` option stored in the `previewOpts` struct.

The sizing logic respects minimum height constraints through `minPreviewSize()` (lines [1962‑1974](https://github.com/junegunn/fzf/blob/master/src/terminal.go#L1962-L1974)), which enforces a `minHeight` of 3 lines while accounting for border styles. The function creates two distinct windows: `pborder` for the preview border (rendered with `ColPreviewBorder`) and `pwindow` for the content area (rendered with `ColPreview`).

## The Preview Rendering Pipeline

When the preview command produces output, the `util.Executor` streams stdout line-by-line into the `previewer.lines` buffer. During the UI redraw cycle, `printPreview()` determines whether the content has changed by comparing the `previewer.version` and `previewer.offset` against the previously rendered state (`t.previewed`).

If regeneration is necessary, `renderPreviewArea()` invokes `renderPreviewText()` (lines [80‑158](https://github.com/junegunn/fzf/blob/master/src/terminal.go#L80-L158)) to handle the actual drawing. This function manages:

- **ANSI-aware text wrapping** via `wordWrapAnsiLine()` (lines [11‑76](https://github.com/junegunn/fzf/blob/master/src/terminal.go#L11-L76)), which respects color codes while breaking lines at width boundaries
- **Continuation indicators** using the `--preview-wrap-sign` option (`t.previewWrapSign`) to mark wrapped lines
- **Line height calculation** through `previewLineHeight()` (lines [63‑99](https://github.com/junegunn/fzf/blob/master/src/terminal.go#L63-L99)) to determine how many terminal rows a given content line occupies

## Terminal-Specific Graphics Passthrough

fzf detects and forwards **terminal passthrough escape sequences** without interpretation, allowing the underlying emulator to render images directly. The detection regexes initialize in `init()` (lines [76‑90](https://github.com/junegunn/fzf/blob/master/src/terminal.go#L76-L90)):

```go
passThroughBeginRegex = regexp.MustCompile(`\x1bPtmux;\x1b\x1b|\x1b(_G|P[0-9;]*q)|\x1b]1337;`)
passThroughEndTmuxRegex = regexp.MustCompile(`[^\x1b]\x1b\\`)

```

During rendering, `extractPassThroughs()` (lines [17‑34](https://github.com/junegunn/fzf/blob/master/src/terminal.go#L17-L34)) isolates these sequences, and `t.tui.PassThrough()` forwards them to the terminal.

### Supported Protocols

| Protocol | Detection | Handling |
|----------|-----------|----------|
| **Kitty graphics** | `\x1b_G…\x1b\\` | Forwarded directly; terminal handles placement |
| **iTerm2 images** | `\x1b]1337;…\x07` or `\x1b]1337;…\x1b\\` | Detected via `isItermImage`; assumes full preview height |
| **Sixel** | `\x1bP…\x1b\\` | Detected via `isSixel`; calculates `requiredLines` using `t.termSize.PxHeight` and terminal pixel dimensions |
| **tmux passthrough** | `\x1bPtmux;\x1b\x1b…\x1b\\` | Outer wrapper stripped, inner sequence forwarded |

When images exceed available space, `renderPreviewText()` draws a **wireframe placeholder** using `t.makeImageBorder` and sets `wireframe = true` to indicate the content cannot fit.

## Scrolling and Follow Mode

The preview pane supports scrolling through `renderPreviewScrollbar()` (lines [82‑115](https://github.com/junegunn/fzf/blob/master/src/terminal.go#L82-L115)), which draws indicators in the `pborder` window. When using `--follow` with `--preview`, the `followOffset()` function (lines [36‑61](https://github.com/junegunn/fzf/blob/master/src/terminal.go#L36-L61)) calculates the correct line offset by accounting for wrapped line heights via `previewLineHeight()`.

## Practical Code Examples

### Basic Text Preview

```bash
fd -H --type f | fzf --preview 'head -n 20 {}'

```

The `head` command writes plain text to stdout. fzf stores this in `previewer.lines` and renders it through `renderPreviewText()` with standard ANSI-aware wrapping.

### Kitty Graphics Protocol

```bash
fd -H --type f | fzf \
    --preview 'kitty +kitten icat --transfer-mode file {}' \
    --preview-window right,70%,border-left

```

The `icat` kitten emits Kitty graphics escape sequences (`\x1b_G…\x1b\\`). fzf extracts these via `extractPassThroughs()` and forwards them through `t.tui.PassThrough()`, allowing the terminal to render the image directly in the preview pane.

### Sixel Image Preview

```bash
fd -H --type f | fzf \
    --preview 'catimg -w 80 {}' \
    --preview-window up,40%

```

The `catimg` utility outputs Sixel data (`\x1bP…\x1b\\`). fzf detects this via `isSixel` and calculates the required visual height using `t.termSize.PxHeight`. If the terminal reports pixel dimensions, fzf computes exact line requirements; otherwise, it assumes full-height rendering or draws a wireframe placeholder if space is insufficient.

### tmux Passthrough Mode

```bash
fzf --preview 'git diff {}' \
    --preview-window right,30% \
    --tmux

```

When running inside a tmux popup, graphic escape sequences are wrapped in tmux's passthrough format (`\x1bPtmux;\x1b\x1b…\x1b\\`). fzf's `passThroughBeginRegex` detects this wrapper, `extractPassThroughs()` strips the outer layer, and the inner sequence is forwarded to the underlying terminal emulator.

## Summary

- **Window Creation**: fzf builds the preview pane through `resizePreviewWindows()` in [`src/terminal.go`](https://github.com/junegunn/fzf/blob/main/src/terminal.go), creating separate windows for borders (`pborder`) and content (`pwindow`) based on `previewOpts` from `--preview-window`.

- **Text Rendering**: The `renderPreviewText()` function handles ANSI-aware wrapping via `wordWrapAnsiLine()`, calculates line heights with `previewLineHeight()`, and manages continuation indicators through `--preview-wrap-sign`.

- **Graphics Passthrough**: fzf detects Kitty, iTerm2, Sixel, and tmux escape sequences using `passThroughBeginRegex` and `extractPassThroughs()`, forwarding them unchanged via `t.tui.PassThrough()` while calculating visual height requirements for Sixel and iTerm2 images.

- **Scrolling**: Scrollbar rendering occurs in `renderPreviewScrollbar()`, with follow-mode support through `followOffset()` that accounts for wrapped line heights.

## Frequently Asked Questions

### How does fzf handle image previews in different terminal emulators?

fzf does not render images itself. Instead, it detects graphics escape sequences (Kitty protocol, iTerm2 inline images, or Sixel) in the preview command output and forwards them directly to the terminal via `t.tui.PassThrough()`. The terminal emulator handles the actual image rendering, while fzf manages the layout space and calculates whether the image fits within the preview window dimensions.

### What happens when a Sixel image is too large for the preview window?

When fzf detects Sixel data (`\x1bP…\x1b\\`) via `isSixel`, it calculates the required visual height using `t.termSize.PxHeight` and the terminal's pixel dimensions. If the image exceeds available space, `renderPreviewText()` draws a wireframe placeholder using `t.makeImageBorder` instead of the actual image, preventing layout corruption while indicating that image content is present but cannot be displayed.

### How does fzf support tmux pop-up windows with image previews?

When running inside tmux, graphic escape sequences are wrapped in tmux's passthrough format (`\x1bPtmux;\x1b\x1b…\x1b\\`). fzf's `passThroughBeginRegex` detects this wrapper in `init()`, and `extractPassThroughs()` strips the outer layer during rendering. The inner sequence is then forwarded via `t.tui.PassThrough()`, allowing the underlying terminal emulator to receive the graphics commands even when fzf runs inside a tmux popup.

### Can fzf preview window rendering impact the main list pane layout?

Yes. When the preview window is positioned on the right or left, `resizePreviewWindows()` adjusts the available width for the main list. The code may add margin columns (`innerWidth++`) and relocate the scrollbar through `listStickToRight` adjustments to accommodate the preview pane dimensions. If the preview is hidden or the command returns no output, the UI clears the preview area and reclaims the space for the main list.