fzf cheat sheet
replacesCtrl-R / history|grepFuzzy-find anything — files, shell history, processes, git branches.
Core Usage
fzf | Launch 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=reverse | Show input list below the prompt (top-down), instead of the default bottom-up layout |
fzf --layout=reverse-list | Reverse-list layout: prompt at top, list in reverse order |
fzf --popup | Open fzf as a centered popup window (requires tmux 3.3+ or Zellij 0.44+) |
fzf --border | Draw 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=full | Apply 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 -1 | Automatically accept without launching the UI when there is exactly one match |
fzf -0 | Exit 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-query | Print the final query string as the first line of output before the selection |
fzf --expect=ctrl-v,ctrl-t | Accept fzf with specific extra keys; fzf prints the triggering key on the first output line |
Search Modes & Query Syntax
sbtrkt | Fuzzy match (default): matches characters in order with gaps allowed, e.g. 'sbtrkt' matches 'subterranean' |
'exact | Exact 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 |
^prefix | Anchored prefix match: only matches lines that start with the given string |
suffix$ | Anchored suffix match: only matches lines that end with the given string |
!inverse | Negation: exclude lines containing this exact term from results |
!^prefix | Inverse prefix match: exclude lines starting with the given string |
!suffix$ | Inverse suffix match: exclude lines ending with the given string |
term1 | term2 | OR operator: match lines satisfying term1 OR term2 (pipe character surrounded by spaces) |
term1 term2 | AND (implicit): space-separated terms are all required; each can use any modifier independently |
fzf -e | Enable exact-match mode globally: all terms are exact-match by default, no fuzzy |
fzf -i | Force case-insensitive matching (default is smart-case: case-insensitive unless query has uppercase) |
fzf +i | Force case-sensitive matching |
fzf --smart-case | Smart-case match (default): case-insensitive until the query contains an uppercase letter |
fzf --scheme=path | Use path-optimized scoring: bonus points for characters after path separators; sets --tiebreak=pathname,length |
fzf --scheme=history | Use history-optimized scoring: no extra bonuses, so chronological order (index tiebreak) dominates |
fzf --algo=v1 | Use the faster but non-optimal v1 fuzzy matching algorithm (default: v2, optimal) |
Key Bindings Inside the Finder
Enter | Accept the current selection and exit |
Ctrl-C / Ctrl-G / Ctrl-Q / Esc | Abort and exit fzf without output |
Ctrl-K / Up | Move cursor up one item in the list |
Ctrl-J / Down | Move cursor down one item in the list |
Ctrl-P / Alt-Up | Move to the match above the cursor (up-match) |
Ctrl-N / Alt-Down | Move to the match below the cursor (down-match) |
Tab | Toggle selection and move down (multi-select mode: marks/unmarks current item) |
Shift-Tab | Toggle selection and move up (multi-select mode) |
Ctrl-A / Home | Move cursor to the beginning of the query input line |
Ctrl-E / End | Move cursor to the end of the query input line |
Ctrl-B / Left | Move query cursor one character backward |
Ctrl-F / Right | Move query cursor one character forward |
Alt-B / Shift-Left | Move query cursor one word backward |
Alt-F / Shift-Right | Move query cursor one word forward |
Ctrl-H / Ctrl-Backspace / Backspace | Delete the character before the query cursor |
Del | Delete the character under the query cursor |
Ctrl-D | Delete character under cursor; abort fzf if query is empty (delete-char/eof) |
Ctrl-U | Delete from start of query to cursor (unix-line-discard) |
Ctrl-W | Delete word before cursor (unix-word-rubout) |
Alt-D | Delete word after cursor (kill-word) |
Alt-Backspace | Delete word before cursor (backward-kill-word) |
Ctrl-Y | Yank (paste) previously deleted text back into the query |
Ctrl-L | Redraw / clear screen |
Ctrl-/ | Toggle line wrapping (also Alt-/) |
Page-Up / Page-Down | Scroll the list one page up or down |
Shift-Up / Shift-Down | Scroll the preview window up or down by one line |
Double-click | Accept the clicked item (same as Enter) |
Right-click | Toggle selection of the clicked item (toggle action) |
Scroll (mouse wheel) | Scroll the list; shift+scroll scrolls the preview window |
Multi-select
fzf -m | Enable multi-select mode: Tab/Shift-Tab mark items; Enter outputs all marked items |
fzf --multi=5 | Enable 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-click | Toggle 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:wrap | Preview at bottom, 10 lines tall, with line wrapping enabled |
fzf --preview-window=hidden | Hide the preview window initially; use a key binding to toggle it on demand |
fzf --preview-window=~3 | Pin 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 | fzf | Pipe any command's output into fzf as the item list |
fzf < file.txt | Read 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 --read0 | Read 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 --ansi | Process ANSI color codes in the input so colored output renders correctly |
fzf +s | Disable sorting of results; output matches in original input order |
fzf --tac | Reverse the order of input before displaying (mirrors tac command behavior) |
fzf --tiebreak=length,begin | Set comma-separated tiebreak criteria applied when match scores are equal (length|chunk|pathname|begin|end|index) |
fzf -n 2,3 | Limit 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=2 | On 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=1000 | Keep only the last N items in memory when input is very large (sliding window) |
fzf --sync | Synchronous 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-preview | Show 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) |
jump | Activate 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 / last | Jump to the first or last matched item |
toggle-sort | Toggle sorting of results on/off at runtime |
toggle-search | Enable or disable fzf's search filtering at runtime |
replace-query | Replace 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
start | Fires once when fzf launches (before input is fully loaded; use --sync for full list access) |
load | Fires once when the full input stream has been read and processed |
change | Fires whenever the query string changes; ideal for live-reload patterns |
focus | Fires when the highlighted item changes due to cursor movement or result updates |
result | Fires when filtering for the current query completes and the result list is ready |
one | Fires when exactly one item matches (runtime equivalent of --select-1) |
zero | Fires when no items match (runtime equivalent of --exit-0) |
backward-eof | Fires 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 |
resize | Fires 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 | source | Add 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=~/.fzfrc | Point 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,hidden | Control the built-in walker: include files, dirs, symlink-following, and hidden entries |
fzf --walker-root=~/projects | Set the root directory for the built-in walker instead of the current directory |
fzf --walker-skip=.git,node_modules,target | Skip 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=1 | Add padding inside the border of the fzf window |
fzf --info=inline | Display the match count inline after the prompt instead of on a separate line |
fzf --info=hidden | Hide 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=1 | Treat the first N lines of input as a sticky header (displayed but not selectable) |
fzf --header-first | Print the header before the prompt line instead of after it |
fzf --highlight-line | Highlight the entire current line (not just the matched characters) |
fzf --cycle | Enable cyclic scrolling: wrap from the last item back to the first and vice versa |
fzf --wrap | Enable line wrapping for long items in the list |
fzf --color=dark | Set the base color scheme. Options: dark, light, base16, bw. Extend with custom color specs. |
fzf --no-bold | Disable bold text in fzf's UI |
fzf --track | Track the focused item when the result list is updated (useful for live-reloading logs) |
fzf --gap | Render empty lines between each item in the list for visual separation |
fzf --scroll-off=5 | Keep N lines of context visible above/below the cursor when scrolling (like vim's scrolloff) |
Scripting & Automation
fzf --history=~/.fzf_history | Save fzf search queries to a file; navigate with Ctrl-N/Ctrl-P inside fzf |
fzf --history-size=1000 | Maximum number of query entries to persist in the fzf history file (default: 1000) |
fzf --disabled | Disable filtering entirely; use fzf as a selector/browser without fuzzy search active |
fzf --listen=6266 | Start 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-mouse | Disable all mouse support inside fzf |
fzf --no-unicode | Use 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 --ansi | Use 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.