:cherry_blossom: A command-line fuzzy finder
(Experimental) Sixel image support in preview window (not available on Windows)
fzf --preview='fzf-preview.sh {}'
(Experimental) iTerm2 inline image protocol support in preview window (not available on Windows)
# Using https://iterm2.com/utilities/imgcat
fzf --preview 'imgcat -W $FZF_PREVIEW_COLUMNS -H $FZF_PREVIEW_LINES {}'
HTTP server can be configured to accept remote connections
# FZF_API_KEY is required for a non-localhost listen address
export FZF_API_KEY="$(head -c 32 /dev/urandom | base64)"
fzf --listen 0.0.0.0:6266
--listen-unsafe
instead
(execute*
, reload*
, become
, preview
, change-preview
, transform-*
)
fzf --listen-unsafe 0.0.0.0:6266
Bug fixes
(Experimental) Added support for Kitty image protocol in the preview window (currently not supported on Windows)
fzf --preview='
if file --mime-type {} | grep -qF image/; then
# --transfer-mode=memory is the fastest option but if you want fzf to be able
# to redraw the image on terminal resize or on "change-preview-window",
# you need to use --transfer-mode=stream.
kitty icat --clear --transfer-mode=memory --stdin=no --place=${FZF_PREVIEW_COLUMNS}x${FZF_PREVIEW_LINES}@0x0 {} | sed \$d
else
bat --color=always {}
fi
'
(Experimental) --listen
server can report program state in JSON format (GET /
)
# fzf server started in "headless" mode
fzf --listen 6266 2> /dev/null
# Get program state
curl localhost:6266 | jq .
# Increase the number of items returned (default: 100)
curl localhost:6266?limit=1000 | jq .
--listen
server can be secured by setting $FZF_API_KEY
environment
variable.
export FZF_API_KEY="$(head -c 32 /dev/urandom | base64)"
# Server
fzf --listen 6266
# Client
curl localhost:6266 -H "x-api-key: $FZF_API_KEY" -d 'change-query(yo)'
Added toggle-header
action
Added mouse events for --bind
scroll-up
(bound to up
)scroll-down
(bound to down
)shift-scroll-up
(bound to toggle+up
)shift-scroll-down
(bound to toggle+down
)shift-left-click
(bound to toggle
)shift-right-click
(bound to toggle
)preview-scroll-up
(bound to preview-up
)preview-scroll-down
(bound to preview-down
)# Twice faster scrolling both in the main window and the preview window
fzf --bind 'scroll-up:up+up,scroll-down:down+down' \
--bind 'preview-scroll-up:preview-up+preview-up' \
--bind 'preview-scroll-down:preview-down+preview-down' \
--preview 'cat {}'
Added offset-up
and offset-down
actions
# Scrolling will behave similarly to CTRL-E and CTRL-Y of vim
fzf --bind scroll-up:offset-up,scroll-down:offset-down \
--bind ctrl-y:offset-up,ctrl-e:offset-down \
--scroll-off=5
Shell extensions
--scheme=path
for better ordering of the resultBug fixes and improvements
--info=right
--info=inline-right
thinblock
which uses symbols for legacy computing one eighth block elements
block
, this style is suitable when using a different background color because the window is completely contained within the border.thinblock
BAT_THEME=GitHub fzf --info=right --border=thinblock --preview-window=border-thinblock \
--margin=3 --scrollbar=▏▕ --preview='bat --color=always --style=numbers {}' \
--color=light,query:238,fg:238,bg:251,bg+:249,gutter:251,border:248,preview-bg:253
block
BAT_THEME=GitHub fzf --info=right --border=block --preview-window=border-block \
--margin=3 --scrollbar=▌▐ --separator=━ --preview='bat --color=always --style=numbers {}' \
--color=light,query:238,fg:238,bg:251,bg+:249,gutter:251,border:248,preview-bg:253,preview-border:252
--disabled
is set and
a reload is triggered by change:reload
bindingAdded color name preview-border
and preview-scrollbar
Added new border style block
which uses block elements
--scrollbar
can take two characters, one for the main window, the other
for the preview window
Putting it altogether:
fzf-tmux -p 80% --padding 1,2 --preview 'bat --style=plain --color=always {}' \
--color 'bg:237,bg+:235,gutter:237,border:238,scrollbar:236' \
--color 'preview-bg:235,preview-border:236,preview-scrollbar:234' \
--preview-window 'border-block' --border block --scrollbar '▌▐'
Bug fixes and improvements
zero
event that is triggered when there's no matchtrack
action which makes fzf track the current item when the
search result is updated. If the user manually moves the cursor, or the
item is not in the updated search result, tracking is automatically
disabled. Tracking is useful when you want to see the surrounding items
by deleting the query string.
# Narrow down the list with a query, point to a command,
# and hit CTRL-T to see its surrounding commands.
export FZF_CTRL_R_OPTS="
--preview 'echo {}' --preview-window up:3:hidden:wrap
--bind 'ctrl-/:toggle-preview'
--bind 'ctrl-t:track+clear-query'
--bind 'ctrl-y:execute-silent(echo -n {2..} | pbcopy)+abort'
--color header:italic
--header 'Press CTRL-Y to copy command into clipboard'"
change-header(...)
transform-header(...)
toggle-track
action--track
behavior when used with --tac
--track
with --tac
is not recommended. The resulting
behavior can be very confusing.one
event that is triggered when there's only one match
# Automatically select the only match
seq 10 | fzf --bind one:accept
--track
option that makes fzf track the current selection when the
result list is updated. This can be useful when browsing logs using fzf with
sorting disabled.
git log --oneline --graph --color=always | nl |
fzf --ansi --track --no-sort --layout=reverse-list
--listen
option without a port number fzf will automatically
allocate an available port and export it as $FZF_PORT
environment
variable.
# Automatic port assignment
fzf --listen --bind 'start:execute-silent:echo $FZF_PORT > /tmp/fzf-port'
# Say hello
curl "localhost:$(cat /tmp/fzf-port)" -d 'preview:echo Hello, fzf is listening on $FZF_PORT.'
printf "foo\rbar\nbaz" | fzf --read0 --preview 'echo {}'
fzf --preview 'head -1000 /dev/random'
become(...)
- Replace the current fzf process with the specified command using execve(2)
system call.
See https://github.com/junegunn/fzf#turning-into-a-different-process for more information.
# Open selected files in Vim
fzf --multi --bind 'enter:become(vim {+})'
# Open the file in Vim and go to the line
git grep --line-number . |
fzf --delimiter : --nth 3.. --bind 'enter:become(vim {1} +{2})'
show-preview
hide-preview
--preview-window 0,hidden
should not execute the preview command until toggle-preview
action is triggeredfzf --info 'inline: ╱ ' --prompt '╱ ' --color prompt:bright-yellow
focus
- Triggered when the focus changes due to a vertical cursor
movement or a search result update
fzf --bind 'focus:transform-preview-label:echo [ {} ]' --preview 'cat {}'
# Any action bound to the event runs synchronously and thus can make the interface sluggish
# e.g. lolcat isn't one of the fastest programs, and every cursor movement in
# fzf will be noticeably affected by its execution time
fzf --bind 'focus:transform-preview-label:echo [ {} ] | lolcat -f' --preview 'cat {}'
# Beware not to introduce an infinite loop
seq 10 | fzf --bind 'focus:up' --cycle
change-border-label
change-preview-label
transform-border-label
transform-preview-label
--listen=HTTP_PORT
option to start HTTP server. It allows external
processes to send actions to perform via POST method.
# Start HTTP server on port 6266
fzf --listen 6266
# Send actions to the server
curl localhost:6266 -d 'reload(seq 100)+change-prompt(hundred> )'
# Hide scrollbar
fzf --no-scrollbar
# Customize scrollbar
fzf --scrollbar ┆ --color scrollbar:blue
load
event that is triggered when the input stream is complete
and the initial processing of the list is complete.
# Change the prompt to "loaded" when the input stream is complete
(seq 10; sleep 1; seq 11 20) | fzf --prompt 'Loading> ' --bind 'load:change-prompt:Loaded> '
# You can use it instead of 'start' event without `--sync` if asynchronous
# trigger is not an issue.
(seq 10; sleep 1; seq 11 20) | fzf --bind 'load:last'
pos(...)
action to move the cursor to the numeric position
first
and last
are equivalent to pos(1)
and pos(-1)
respectively# Put the cursor on the 10th item
seq 100 | fzf --sync --bind 'start:pos(10)'
# Put the cursor on the 10th to last item
seq 100 | fzf --sync --bind 'start:pos(-10)'
reload-sync(...)
action which replaces the current list only after
the reload process is complete. This is useful when the command takes
a while to produce the initial output and you don't want fzf to run against
an empty list while the command is running.
# You can still filter and select entries from the initial list for 3 seconds
seq 100 | fzf --bind 'load:reload-sync(sleep 3; seq 1000)+unbind(load)'
next-selected
and prev-selected
actions to move between selected
items
# `next-selected` will move the pointer to the next selected item below the current line
# `prev-selected` will move the pointer to the previous selected item above the current line
seq 10 | fzf --multi --bind ctrl-n:next-selected,ctrl-p:prev-selected
# Both actions respect --layout option
seq 10 | fzf --multi --bind ctrl-n:next-selected,ctrl-p:prev-selected --layout reverse
change-query(...)
action that simply changes the query string to the
given static string. This can be useful when used with --listen
.
curl localhost:6266 -d "change-query:$(date)"
transform-prompt(...)
action for transforming the prompt string
using an external command
# Press space to change the prompt string using an external command
# (only the first line of the output is taken)
fzf --bind 'space:reload(ls),load:transform-prompt(printf "%s> " "$(date)")'
transform-query(...)
action for transforming the query string using
an external command
# Press space to convert the query to uppercase letters
fzf --bind 'space:transform-query(tr "[:lower:]" "[:upper:]" <<< {q})'
# Bind it to 'change' event for automatic conversion
fzf --bind 'change:transform-query(tr "[:lower:]" "[:upper:]" <<< {q})'
# Can only type numbers
fzf --bind 'change:transform-query(sed "s/[^0-9]//g" <<< {q})'
put
action can optionally take an argument string
# a will put 'alpha' on the prompt, ctrl-b will put 'bravo'
fzf --bind 'a:put+put(lpha),ctrl-b:put(bravo)'
preview-label
for --preview-label
(defaults to label
for --border-label
)RUNEWIDTH_EASTASIAN
environment variable to 1
.
&ambiwidth
is double
{q}
even when it's empty. If you prefer the old behavior,
you'll have to check if {q}
is empty in your command.
# This will show // even when the query is empty
: | fzf --preview 'echo /{q}/'
# But if you don't want it,
: | fzf --preview '[ -n {q} ] || exit; echo /{q}/'
double-click
will behave the same as enter
unless otherwise specified,
so you don't have to repeat the same action twice in --bind
in most cases.
# No need to bind 'double-click' to the same action
fzf --bind 'enter:execute:less {}' # --bind 'double-click:execute:less {}'
separator
is not specified, it will default to the
color for border
. Same holds true for scrollbar
. This is to reduce
the number of configuration items required to achieve a consistent color
scheme.follow
flag is specified in --preview-window
option, fzf will
automatically scroll to the bottom of the streaming preview output. But
when the user manually scrolls the window, the following stops. With
this version, fzf will resume following if the user scrolls the window
to the bottom.sharp
because some
Windows terminals are not capable of displaying rounded
border
characters correctly.