linuxkernel.com

fzf cheat sheet

replaces Ctrl-R / history|grep

Fuzzy-find anything — files, shell history, processes, git branches.

Covers fzf 0.73.1. Click any command for details & copy · press / to search.

Core Usage

fzfLaunch fzf in fullscreen mode, reading from stdin or built-in file walker
fzf --height 40%Open fzf in a panel below the cursor instead of fullscreen, at 40% terminal height
fzf --height ~100%Adaptive height: fzf sizes itself to fit the input list, up to 100% of terminal
fzf --layout=reverseShow input list below the prompt (top-down), instead of the default bottom-up layout
fzf --layout=reverse-listReverse-list layout: prompt at top, list in reverse order
fzf --popupOpen fzf as a centered popup window (requires tmux 3.3+ or Zellij 0.44+)
fzf --borderDraw a border around the finder window (default style: rounded)
fzf --border-label='My Files'Print a label on the border of the finder window
fzf --style=fullApply a style preset. Options: default, minimal, full[:BORDER_STYLE]
fzf -q 'query'Pre-fill the search prompt with an initial query string on startup
fzf -1Automatically accept without launching the UI when there is exactly one match
fzf -0Exit immediately with no output when there are zero matches
fzf -f 'query'Non-interactive filter mode: print matching lines for a query and exit (no UI)
fzf --print-queryPrint the final query string as the first line of output before the selection
fzf --expect=ctrl-v,ctrl-tAccept fzf with specific extra keys; fzf prints the triggering key on the first output line

Search Modes & Query Syntax

sbtrktFuzzy match (default): matches characters in order with gaps allowed, e.g. 'sbtrkt' matches 'subterranean'
'exactExact match: prefix with single-quote to require an exact substring match (no fuzzy)
'exact'Exact boundary match: both single-quoted ends require the term to appear at word boundaries
^prefixAnchored prefix match: only matches lines that start with the given string
suffix$Anchored suffix match: only matches lines that end with the given string
!inverseNegation: exclude lines containing this exact term from results
!^prefixInverse prefix match: exclude lines starting with the given string
!suffix$Inverse suffix match: exclude lines ending with the given string
term1 | term2OR operator: match lines satisfying term1 OR term2 (pipe character surrounded by spaces)
term1 term2AND (implicit): space-separated terms are all required; each can use any modifier independently
fzf -eEnable exact-match mode globally: all terms are exact-match by default, no fuzzy
fzf -iForce case-insensitive matching (default is smart-case: case-insensitive unless query has uppercase)
fzf +iForce case-sensitive matching
fzf --smart-caseSmart-case match (default): case-insensitive until the query contains an uppercase letter
fzf --scheme=pathUse path-optimized scoring: bonus points for characters after path separators; sets --tiebreak=pathname,length
fzf --scheme=historyUse history-optimized scoring: no extra bonuses, so chronological order (index tiebreak) dominates
fzf --algo=v1Use the faster but non-optimal v1 fuzzy matching algorithm (default: v2, optimal)

Key Bindings Inside the Finder

EnterAccept the current selection and exit
Ctrl-C / Ctrl-G / Ctrl-Q / EscAbort and exit fzf without output
Ctrl-K / UpMove cursor up one item in the list
Ctrl-J / DownMove cursor down one item in the list
Ctrl-P / Alt-UpMove to the match above the cursor (up-match)
Ctrl-N / Alt-DownMove to the match below the cursor (down-match)
TabToggle selection and move down (multi-select mode: marks/unmarks current item)
Shift-TabToggle selection and move up (multi-select mode)
Ctrl-A / HomeMove cursor to the beginning of the query input line
Ctrl-E / EndMove cursor to the end of the query input line
Ctrl-B / LeftMove query cursor one character backward
Ctrl-F / RightMove query cursor one character forward
Alt-B / Shift-LeftMove query cursor one word backward
Alt-F / Shift-RightMove query cursor one word forward
Ctrl-H / Ctrl-Backspace / BackspaceDelete the character before the query cursor
DelDelete the character under the query cursor
Ctrl-DDelete character under cursor; abort fzf if query is empty (delete-char/eof)
Ctrl-UDelete from start of query to cursor (unix-line-discard)
Ctrl-WDelete word before cursor (unix-word-rubout)
Alt-DDelete word after cursor (kill-word)
Alt-BackspaceDelete word before cursor (backward-kill-word)
Ctrl-YYank (paste) previously deleted text back into the query
Ctrl-LRedraw / clear screen
Ctrl-/Toggle line wrapping (also Alt-/)
Page-Up / Page-DownScroll the list one page up or down
Shift-Up / Shift-DownScroll the preview window up or down by one line
Double-clickAccept the clicked item (same as Enter)
Right-clickToggle selection of the clicked item (toggle action)
Scroll (mouse wheel)Scroll the list; shift+scroll scrolls the preview window

Multi-select

fzf -mEnable multi-select mode: Tab/Shift-Tab mark items; Enter outputs all marked items
fzf --multi=5Enable multi-select with a maximum of 5 items that can be selected
fzf -m --bind 'ctrl-a:select-all'Bind Ctrl-A to select all currently matched items at once
fzf -m --bind 'ctrl-a:select-all+accept'Select all matches and immediately accept (chain actions with +)
fzf -m --bind 'ctrl-d:deselect-all'Bind Ctrl-D to deselect all currently selected items
fzf -m --bind 'ctrl-t:toggle-all'Bind Ctrl-T to invert the selection state of all matched items
Shift-Left-clickToggle multi-select for the clicked item (mouse multi-select inside finder)
fzf -m --preview 'head -10 {+}'Use {+} placeholder to pass all selected items to the preview command

Preview Window

fzf --preview 'COMMAND {}'Run COMMAND with the highlighted item (via {} placeholder) and show output in a preview pane
fzf --preview 'bat --color=always {}'Preview files with syntax highlighting using bat (highly recommended)
fzf --preview-window=right:50%Position preview window on the right at 50% width (default layout)
fzf --preview-window=up:40%Position preview window at the top, 40% of the terminal height
fzf --preview-window=down:10:wrapPreview at bottom, 10 lines tall, with line wrapping enabled
fzf --preview-window=hiddenHide the preview window initially; use a key binding to toggle it on demand
fzf --preview-window=~3Pin the first 3 lines of the preview as a sticky header (they stay visible while scrolling)
fzf --preview-window='+{2}/2'Scroll preview to the line number extracted from field 2 of the selected item, centered
fzf --preview-window=right:50%:<80(up:50%)Responsive layout: use right:50% normally, switch to up:50% when terminal is narrower than 80 columns
fzf --preview-label='Preview'Print a label on the border of the preview window
--bind 'ctrl-/:toggle-preview'Toggle the preview window on/off with a key binding
--bind 'ctrl-/:change-preview-window(right|down|hidden)'Cycle through multiple preview window positions/states with repeated key presses
--bind '?:preview:cat {}'Use preview() action to show a different preview command on a specific key, independent of --preview
fzf --ansi --preview 'COMMAND'Enable ANSI color code processing so colorized preview output renders correctly

Piping, Filtering & Input/Output

COMMAND | fzfPipe any command's output into fzf as the item list
fzf < file.txtRead items from a file instead of stdin or the built-in walker
$(fzf)Use fzf's selected output inline in a shell command via command substitution
fzf --read0Read NUL-delimited input (safe for filenames with spaces or special characters)
fzf --print0 Output selected items delimited by NUL bytes (pipe to xargs -0)
fzf --ansiProcess ANSI color codes in the input so colored output renders correctly
fzf +sDisable sorting of results; output matches in original input order
fzf --tacReverse the order of input before displaying (mirrors tac command behavior)
fzf --tiebreak=length,beginSet comma-separated tiebreak criteria applied when match scores are equal (length|chunk|pathname|begin|end|index)
fzf -n 2,3Limit fuzzy search scope to fields 2 and 3 only (--nth); other fields still display
fzf --with-nth=2..Display only fields 2 onward; first field is hidden from view (but searchable via --nth)
fzf --accept-nth=2On accept, print only field 2 of the selected item instead of the full line
fzf -d ':'Set field delimiter for --nth, --with-nth, --accept-nth (default: AWK-style whitespace)
fzf --tail=1000Keep only the last N items in memory when input is very large (sliding window)
fzf --syncSynchronous mode: wait for all input before showing the finder (useful with --bind start:...)

Key/Event Bindings & Actions

fzf --bind 'KEY:ACTION'Bind a key to an action. Multiple bindings are comma-separated. Actions chain with +.
execute(...)Run an arbitrary command for the selected item without leaving fzf; fzf resumes after
execute-silent(...)Run a command silently in the background without switching screens; fzf stays responsive
become(...)Replace the fzf process entirely with the given command using execve (no shell wrapper overhead)
reload(...)Dynamically replace the item list by re-running a command (streaming, updates as data arrives)
reload-sync(...)Like reload but waits for the full command output before replacing the list
change-preview(...)Dynamically change the --preview command at runtime
change-preview-window(...)Cycle or change preview window layout at runtime; separate options with | to rotate
toggle-previewShow or hide the preview window
change-prompt(...)Change the input prompt text dynamically
change-query(...)Programmatically set the query string
transform(...)Run a shell command that outputs a sequence of fzf actions to perform (powerful meta-action)
jumpActivate EasyMotion-style 2-keystroke jump: press a label character to jump to that item
pos(N)Move cursor to position N in the list (negative counts from end)
first / lastJump to the first or last matched item
toggle-sortToggle sorting of results on/off at runtime
toggle-searchEnable or disable fzf's search filtering at runtime
replace-queryReplace the current query string with the text of the focused item
print(...)Queue a string for output on normal exit (without accepting from the list)
unbind(...) / rebind(...)Dynamically remove or restore key bindings at runtime

Events for --bind

startFires once when fzf launches (before input is fully loaded; use --sync for full list access)
loadFires once when the full input stream has been read and processed
changeFires whenever the query string changes; ideal for live-reload patterns
focusFires when the highlighted item changes due to cursor movement or result updates
resultFires when filtering for the current query completes and the result list is ready
oneFires when exactly one item matches (runtime equivalent of --select-1)
zeroFires when no items match (runtime equivalent of --exit-0)
backward-eofFires when the query is empty and you press backspace (useful to abort on empty)
every(N)Fires every N seconds (fractional values supported, minimum 0.01s); useful for live-updating lists
resizeFires when the terminal window is resized

Shell Integration (Ctrl-T, Ctrl-R, Alt-C)

eval "$(fzf --bash)"Add to ~/.bashrc to enable Ctrl-T, Ctrl-R, Alt-C shell key bindings and ** fuzzy completion
source <(fzf --zsh)Add to ~/.zshrc to enable fzf shell integration for Zsh
fzf --fish | sourceAdd to Fish config to enable fzf shell integration for Fish
Ctrl-T (shell)Fuzzy-find files and directories under the current directory; paste selection onto the command line
Ctrl-R (shell)Fuzzy search shell command history; paste the selected command onto the command line. Press Ctrl-R again inside fzf to toggle relevance sorting.
Shift-Delete (in Ctrl-R)Delete the selected history entry from the shell history file (bash/fish only)
Alt-C (shell)Fuzzy-find a directory and cd into it immediately; no typing required
COMMAND **<Tab>Trigger fuzzy completion for files/directories: type ** then Tab to launch fzf inline
kill -9 **<Tab>Fuzzy-select a process PID for kill using fzf completion (multi-select with Tab)
ssh **<Tab>Fuzzy-complete SSH hostnames from /etc/hosts and ~/.ssh/config
export FZF_DEFAULT_COMMAND='fd --type f --hidden --follow --exclude .git'Override the command used to generate fzf's default file list (when no stdin is piped)
export FZF_DEFAULT_OPTS='--layout=reverse --border --height=40%'Set global default flags applied to every fzf invocation
export FZF_DEFAULT_OPTS_FILE=~/.fzfrcPoint fzf to a file containing default options (one option per line or space-separated)
export FZF_CTRL_T_COMMAND='fd --type f'Override the command that generates the Ctrl-T file list
export FZF_CTRL_T_OPTS="--preview 'bat -n --color=always {}'"Set extra fzf options used only for the Ctrl-T binding
export FZF_CTRL_R_OPTS='--sort --exact'Set extra fzf options used only for the Ctrl-R history binding
export FZF_ALT_C_COMMAND='fd --type d'Override the command that generates the Alt-C directory list
export FZF_ALT_C_OPTS="--preview 'eza --tree --level=2 {}'"Set extra fzf options for the Alt-C binding (e.g. tree preview)
export FZF_COMPLETION_TRIGGER='~~'Change the trigger sequence for fuzzy ** completion (default: **)

Directory Walker (built-in)

fzf --walker=file,dir,follow,hiddenControl the built-in walker: include files, dirs, symlink-following, and hidden entries
fzf --walker-root=~/projectsSet the root directory for the built-in walker instead of the current directory
fzf --walker-skip=.git,node_modules,targetSkip specified directory names when walking (default: .git,node_modules)

Layout & Display Options

fzf --margin=5%Add screen margin around the fzf window (TRBL / TB,RL / T,RL,B / T,R,B,L format)
fzf --padding=1Add padding inside the border of the fzf window
fzf --info=inlineDisplay the match count inline after the prompt instead of on a separate line
fzf --info=hiddenHide the match count / info line entirely
fzf --prompt='Files> 'Customize the input prompt string
fzf --pointer='>'Customize the pointer character indicating the current item
fzf --marker='*'Customize the marker character shown on selected items in multi-select mode
fzf --header='Press ? for help'Display a static header string above (or below) the list
fzf --header-lines=1Treat the first N lines of input as a sticky header (displayed but not selectable)
fzf --header-firstPrint the header before the prompt line instead of after it
fzf --highlight-lineHighlight the entire current line (not just the matched characters)
fzf --cycleEnable cyclic scrolling: wrap from the last item back to the first and vice versa
fzf --wrapEnable line wrapping for long items in the list
fzf --color=darkSet the base color scheme. Options: dark, light, base16, bw. Extend with custom color specs.
fzf --no-boldDisable bold text in fzf's UI
fzf --trackTrack the focused item when the result list is updated (useful for live-reloading logs)
fzf --gapRender empty lines between each item in the list for visual separation
fzf --scroll-off=5Keep N lines of context visible above/below the cursor when scrolling (like vim's scrolloff)

Scripting & Automation

fzf --history=~/.fzf_historySave fzf search queries to a file; navigate with Ctrl-N/Ctrl-P inside fzf
fzf --history-size=1000Maximum number of query entries to persist in the fzf history file (default: 1000)
fzf --disabledDisable filtering entirely; use fzf as a selector/browser without fuzzy search active
fzf --listen=6266Start an HTTP server so external processes can send actions to fzf via POST requests
fzf --with-shell='bash -c'Override the shell used to execute preview/execute commands (default: $SHELL)
fzf --no-mouseDisable all mouse support inside fzf
fzf --no-unicodeUse plain ASCII characters instead of Unicode box-drawing characters for borders

rg / bat / eza / git Integrations

rg --files | fzf --preview 'bat --color=always {}'List files with ripgrep (respects .gitignore) and preview with bat syntax highlighting
rg --line-number '' | fzf -d ':' --preview 'bat --highlight-line {2} --color=always {1}'Search all lines with ripgrep, then fuzzy-filter results with per-line previews via bat
git log --oneline --color=always | fzf --ansi --preview 'git show --color=always {1}'Browse git log with fuzzy search; preview the full diff of each commit
git branch | fzf --preview 'git log --oneline --color=always {}'Fuzzy-pick a git branch with a commit log preview; pipe result to git checkout
git stash list | fzf --preview 'git stash show -p {1}'Browse git stash entries with a full diff preview of each stash
eza --all --long --color=always | fzf --header-lines=1 --ansiUse eza's long listing as fzf input with the header line (column names) pinned at the top
export FZF_ALT_C_OPTS="--preview 'eza --tree --color=always --level=2 {}'"Make Alt-C show a directory tree preview using eza when choosing a directory to cd into
export FZF_DEFAULT_COMMAND='rg --files --hidden --glob "!.git"'Use ripgrep as fzf's default file source (fast, .gitignore-aware, hidden files included)

Killer recipes

Live ripgrep search, open match in vim

RG_PREFIX='rg --column --line-number --no-heading --color=always --smart-case'
fzf --bind "change:reload:$RG_PREFIX {q} || true" \
    --bind 'enter:become(vim {1} +{2})' \
    --ansi --disabled --query '' --delimiter : \
    --preview 'bat --color=always --highlight-line {2} -- {1}' \
    --preview-window 'right:50%:+{2}/2'

As you type in fzf, ripgrep re-runs live across all files. Enter opens the file at the matched line in vim. Preview pane shows syntax-highlighted file with match scrolled into view. The foundational interactive grep workflow.

Fuzzy git branch checkout with log preview

git checkout $(git branch --all --color=always | grep -v HEAD \
  | fzf --ansi \
      --preview 'git log --oneline --graph --color=always $(echo {} | sed s/^..//) | head -50' \
      --preview-window right:60% \
  | sed 's|remotes/origin/||' | tr -d '[:space:]')

Browse all local and remote branches with a commit-graph preview. Selection is cleaned and passed to git checkout. Works for both local and remote branches.

Ctrl-T file picker with bat preview and fd backend

# In your shell profile:
export FZF_CTRL_T_COMMAND='fd --type f --hidden --follow --exclude .git --exclude node_modules'
export FZF_CTRL_T_OPTS="
  --preview 'bat -n --color=always --line-range :100 {}'
  --bind 'ctrl-/:change-preview-window(down|hidden|)'
  --walker-skip .git,node_modules,.venv"

Replaces the default Ctrl-T with fd (fast, .gitignore-aware). Preview shows first 100 lines of each file with syntax highlighting via bat. Ctrl-/ cycles preview position or hides it. Paste into shell profile.

Ctrl-R history with clipboard copy shortcut

# In your shell profile:
export FZF_CTRL_R_OPTS="
  --bind 'ctrl-y:execute-silent(echo -n {2..} | pbcopy)+abort'
  --bind 'ctrl-/:toggle-wrap'
  --color header:italic
  --header 'Ctrl-Y: copy to clipboard | Enter: run | Ctrl-/: wrap'"

Enhanced Ctrl-R: Ctrl-Y copies the selected command to the macOS clipboard without running it. Ctrl-/ toggles line wrap for long commands. Paste into shell profile.

Live-updating process list, kill on Enter

fzf --header-lines 1 --track --id-nth 2 \
    --bind 'start,every(2):reload-sync:ps -ef' \
    --bind 'enter:execute-silent(kill {2})+reload(ps -ef)' \
    --header 'Auto-refreshes every 2s | Enter to kill'

Auto-refreshes the process list every 2 seconds using fzf's every(N) event. --track --id-nth 2 keeps the cursor on the same PID across reloads. A lightweight interactive process browser.

Alt-C directory jump with eza tree preview

# In your shell profile:
export FZF_ALT_C_COMMAND='fd --type d --hidden --exclude .git'
export FZF_ALT_C_OPTS="
  --preview 'eza --tree --color=always --level=2 {}'
  --preview-window 'right:40%'"

Alt-C fuzzy cd backed by fd for speed and .gitignore awareness. Preview pane shows a 2-level directory tree rendered by eza. Paste into shell profile.

Notes & tips

SHELL INTEGRATION SETUP Add eval \"$(fzf --bash)\" to ~/.bashrc or source <(fzf --zsh) to ~/.zshrc. This enables Ctrl-T (file picker), Ctrl-R (history), Alt-C (cd), and ** fuzzy completion. Homebrew install does NOT auto-add these — you must add the eval/source line yourself.
FZF_DEFAULT_OPTS vs FZF_DEFAULT_OPTS_FILE Use FZF_DEFAULT_OPTS for a short list of flags. For complex configs, write one flag per line in ~/.fzfrc and set FZF_DEFAULT_OPTS_FILE=~/.fzfrc. Both are merged; FZF_DEFAULT_OPTS_FILE is read first.
PERFORMANCE --ansi slows initial input scanning — avoid it in FZF_DEFAULT_OPTS if your input is large. --nth and --with-nth require tokenization (small overhead). Use --algo=v1 for a speed boost at the cost of non-optimal match ranking.
PLACEHOLDER EXPRESSIONS in --preview and --bind actions {} = current item (single-quoted), {1},{2},... = specific fields, {+} = all selected items (space-separated, single-quoted), {q} = current query string, {n} = zero-based ordinal index, {+f} = selected items as a temp file path (one per line), {1..3} = field range.
ACTION CHAINING Use + to chain multiple actions: --bind 'ctrl-a:select-all+accept'. Any action after a terminal action (accept, abort) is ignored. Alternative argument delimiters: action-name[...], action-name{...}, or action-name:... (colon form needs no closing char and must be last in a comma list).
BECOME vs EXECUTE become() replaces the fzf process via execve(2) — no shell overhead, and the launched program inherits the terminal cleanly. execute() runs a command and returns to fzf. Prefer become() when opening an editor on the selected file.
EXIT CODES 0 = normal selection, 1 = no match, 2 = error, 130 = user aborted (Ctrl-C / Esc). Use these in scripts to detect cancellation vs. an empty result.
FUZZY COMPLETION TRIGGER Default is ** followed by Tab. Change with FZF_COMPLETION_TRIGGER. Works for file args to most commands, cd, kill -9, ssh, unset, export, and more.
TMUX/ZELLIJ POPUP --popup (alias: --tmux) opens fzf in a floating popup window. Requires tmux 3.3+ or Zellij 0.44+. Size and position: --popup center,80%,60% (center, 80% wide, 60% tall).
HTTP LISTEN SERVER --listen=PORT starts a local HTTP server. POST actions as plain text: curl -XPOST localhost:PORT -d 'reload(ls)+change-prompt(Files> )'. Secure with FZF_API_KEY env var (sent as X-API-Key header). Supports Unix domain sockets when path ends in .sock.