Releases: junegunn/fzf
Releases Β· junegunn/fzf
Release list
0.74.2
- Performance optimizations for short queries
- Short queries scan the largest candidate sets, and the first keystroke scans the whole input
- Single-character queries are up to 2.4x faster
- Two-character queries are up to 1.4x faster
- Faster sorting of search results, skipping redundant radix passes
change-border-labelandtransform-border-labelnow work on the native border of a tmux or Zellij floating pane- Fixed Kitty graphics sequences from a preview command being taken by tmux as pane title requests
- Fixed an image at the top of the preview being torn by
--preview-window ~N - Fixed nondeterministic match highlight positions
- Fixed signal and resize handlers persisting after
Run()returns when fzf is used as a library - fzf now detects terminal resize on Windows in
--heightmode (#4790) (@Cyrus580529) - fish: fixed history command being affected by user initialization scripts, and improved timestamp colors in CTRL-R (#4862) (@bitraid)
- zsh: fixed CTRL-R not propagating the exit status of fzf when perl is available (#4871) (@LangLangBart, @Toliak)
- zsh: fixed
chpwdhook functions being called twice by ALT-C (#4879) (@LangLangBart, @lucc)
0.74.1
- The default separator on the info line is no longer shown when the input section is already visually separated from the list section by a border line
# No separator shown below the header border fzf --style full --input-border none --header foo # Separator shown; no border separates the input section from the list section fzf --style full --input-border none --header foo --no-header-border # No separator below the border of the preview window at 'next' position fzf --preview : --preview-window next # Conversely, separator is now shown when the input border does not draw # a line facing the list section fzf --input-border bottom
- Rendering improvements
- Each frame is now wrapped in synchronized update mode (mode 2026) to reduce flickering on supported terminals
- Reduced rendering output by 10-23% by skipping redundant SGR sequences
- Fixed ghost characters and misplaced colors inside Zellij by using CHA instead of CR + CUF for horizontal cursor movement (#4858, zellij-org/zellij#5370)
- Fixed cursor restoration on exit with
--height --no-clearinside Neovim terminal by using DECSC/DECRC instead ofCSI s/CSI u
- nushell: fixed deprecation error of
str downcaseon nushell 0.114.0 or above (#4857) (@sim590) - Each release now includes
.debpackages for easy installation on Debian-based distros (#4859)
0.74.0
Release highlights: https://junegunn.github.io/fzf/releases/0.74.0/
- On tmux 3.7 or above,
--popupstarts fzf in a floating pane instead of a popup (#4850)- Unlike a popup, a floating pane is not modal; you can switch to other panes and windows while fzf is running, move and resize the pane with the mouse, zoom it to fullscreen, and use copy-mode in it
- A floating pane always has a native border, which is what makes the pane movable and resizable, so
border-nativeis implied - A popup is used instead when a border style is explicitly specified with
--border, so that the fzf-drawn border is the only border shown (noneandlineare treated as no border)fzf --popup --border
--border-labelis set as the title of the floating pane, and is displayed on the border ifpane-border-statusis enabled in tmuxfzf --popup --border-label ' fzf '
- On Zellij,
--popupuses the native border by default, consistent with tmux, so that the pane can be moved and resized with the mouse; fzf draws its own border when a border style is explicitly specified with--border--border-labelis set as the name of the pane, displayed on the native border
- Added
result-finalevent, a variant ofresultthat is not triggered while the input stream is still open (#4835)- Use it for one-shot, per-query actions that would otherwise re-fire on every intermediate snapshot during loading
# 'result' fires per intermediate snapshot (header keeps updating during load); # 'result-final' fires once after the stream closes (footer shows the final count) (seq 100; sleep 1; seq 100) | fzf --query 1 \ --bind 'result:transform-header(echo result: $FZF_MATCH_COUNT),result-final:transform-footer(echo final: $FZF_MATCH_COUNT)'
- Use it for one-shot, per-query actions that would otherwise re-fire on every intermediate snapshot during loading
- Added
waitaction to block subsequent actions until search completes (#4825)- Useful for chaining query-changing actions with motion actions to ensure operations on complete results
# Wait for search to complete before moving to the best match fzf --bind 'start:change-query(foo)+wait+best'
- The initial loading of the input is also considered a search in progress, so
start:waitcan be used to wait until the input is fully loaded# Move to the last item after the input is fully loaded (seq 1000; sleep 1; seq 1001 2000) | fzf --bind 'start:wait+last'
- Useful for chaining query-changing actions with motion actions to ensure operations on complete results
- Bound
alt-lefttobackward-wordandalt-righttoforward-wordby default (#4833) - Bug fixes and improvements
- Skip
$FZF_CURRENT_ITEMexport when the item is larger than 64 KB; a huge item can overflowARG_MAXand break preview and other child commands withE2BIG(#4806) transformandbg-transformnow allow a bareputaction in the output to insert the key that triggered the action# Insert the typed key ('a') into the query fzf --bind 'a:transform:echo put'
ALT-Cin zsh no longer resolves symbolic links when changing the directory, consistent with thecdbuiltin (#4816) (@silverneko)- Fixed horizontal mouse wheel events being treated as vertical scrolling (#4848) (@jason5122)
- Fixed
bwtheme not inheriting overridden colors - fish:
CTRL-Rnow works when$fish_color_normalor$fish_color_commentis empty or invalid (#4831) (@bitraid) - Fixed empty-shell detection in the install script (#4813)
- Fixed the install script writing nushell source lines into the config files of other shells (#4812)
- Skip
0.73.1
- Bug fixes
- Skip
$FZF_CURRENT_ITEMexport when the item contains a NUL byte;exec(2)rejects the env, breaking preview and other child commands (#4806) - Fixed O(n^2) HTTP body accumulation in
--listen; a single ~390 KB request could block the single-threaded server for ~8 s (Michal Majchrowicz, Marcin Wyczechowski, AFINE Team)
- Skip
0.73.0
Release highlights: https://junegunn.github.io/fzf/releases/0.73.0/
- Nushell integration via
fzf --nushelland the installer (#4630) (@sim590) - New
--preview-window=nextposition that places the preview adjacent to the input section, on the list side: above the input in the default layout, below it in--layout=reverse(#4798) - Timer-driven
every(N)event for--bind, whereNis seconds - Added
$FZF_IDLE_TIME(whole seconds) and$FZF_IDLE_TIME_MS(milliseconds), holding the elapsed time since the last user activity- Pair with
every(N)to build idle-based behavior such as auto-accept or auto-quit (#1211)# Live process list; --track --id-nth 2 keeps the cursor on the same PID across reloads fzf --header-lines 1 --track --id-nth 2 --bind 'start,every(2):reload-sync:ps -ef' # Auto-accept after 10 seconds of inactivity, with a countdown in the footer after 5s fzf --bind 'every(1):bg-transform: if [[ $FZF_IDLE_TIME -lt 5 ]]; then echo change-footer: elif [[ $FZF_IDLE_TIME -lt 10 ]]; then echo "change-footer:auto-accept in $((10 - FZF_IDLE_TIME))s" else echo accept fi'
- Pair with
- Added
$FZF_CURRENT_ITEMfor shells where quoting{}is awkward (#4802) - Bug fixes
- Scoring: non-word characters at the start of input or after a delimiter now receive the same boundary bonus as word characters (#4795)
change-preview-windowno longer resetswrap/wrap-wordstate set viatoggle-preview-wrap/toggle-preview-wrap-word(#4791)- Stripped UTF-8-encoded C1 control characters from rendered items to prevent terminal control-sequence injection
- Fixed integer-overflow panic in
FuzzyMatchV2on 32-bit builds (Michal Majchrowicz, Marcin Wyczechowski, AFINE Team) - Fixed
bg-transformreload/excludepayloads being dropped - Fixed rendering glitch with preview window on the left combined with footer
0.72.0
Release highlights: https://junegunn.github.io/fzf/releases/0.72.0/
--header-border,--header-lines-border, and--footer-bordernow accept a newinlinestyle that embeds the section inside the list frame, separated from the list content by a horizontal line. When the list border has side segments, the separator joins them as T-junctions.- Requires a
--list-bordershape that has both top and bottom segments (rounded,sharp,bold,double,block,thinblock, orhorizontal); falls back tolineotherwise.horizontalhas no side borders, so the separator is drawn without T-junction endpoints. - Sections stack. Example combining all three:
ps -ef | fzf --reverse --style full \ --header 'Select a process' --header-lines 1 \ --bind 'load:transform-footer:echo $FZF_TOTAL_COUNT processes' \ --header-border dashed --header-first \ --header-lines-border inline --footer-border inline
--header-labeland--footer-labelrender on their respective separator row.- The separator inherits
--color list-borderwhen the section's own border color is not explicitly set. inlinetakes precedence over--header-first: the inline section stays inside the list frame.--header-border=inlinerequires--header-lines-borderto beinlineor unset.
- Requires a
- New
dashedborder style with dashed edges (βΆ/β) and rounded corners.--border=dashed,--list-border=dashed, etc.- Works with inline sections (T-junctions render correctly).
- [vim] Move and resize popup window when detecting
VimResizedevent (#4778) (@Vulcalien) - Bug fixes
0.71.0
Release highlights: https://junegunn.github.io/fzf/releases/0.71.0/
- Added
--popupas a new name for--tmuxwith Zellij support--popupstarts fzf in a tmux popup or a Zellij floating pane--tmuxis now an alias for--popup- Requires tmux 3.3+ or Zellij 0.44+
- Cross-reload item identity with
--id-nth- Added
--id-nth=NTHto define item identity fields for cross-reload operations - When a
reloadis triggered with tracking enabled, fzf searches for the tracked item by its identity fields in the new list.--track --id-nth ..tracks by the entire line--track --id-nth 1tracks by the first field--trackwithout--id-nthretains the existing index-based tracking behavior- The UI is temporarily blocked (prompt dimmed, input disabled) until the item is found or loading completes.
- Press
EscapeorCtrl-Cto cancel the blocked state without quitting - Info line shows
+T*/+t*while searching
- Press
- With
--multi, selected items are preserved acrossreload-syncby matching their identity fields
- Added
- Performance improvements
- The search performance now scales linearly with the number of CPU cores, as we dropped static partitioning to allow better load balancing across threads.
=== query: 'linux' === [all] baseline: 21.95ms current: 17.47ms (1.26x) matches: 179966 (12.79%) [1T] baseline: 179.63ms current: 180.53ms (1.00x) matches: 179966 (12.79%) [2T] baseline: 97.38ms current: 90.05ms (1.08x) matches: 179966 (12.79%) [4T] baseline: 53.83ms current: 44.77ms (1.20x) matches: 179966 (12.79%) [8T] baseline: 41.66ms current: 22.58ms (1.84x) matches: 179966 (12.79%) - Improved the cache structure, reducing memory footprint per entry by 86x.
- With the reduced per-entry cost, the cache now has broader coverage.
- The search performance now scales linearly with the number of CPU cores, as we dropped static partitioning to allow better load balancing across threads.
- Shell integration improvements
GET /HTTP endpoint now includespositionsfield in each match entry, providing the indices of matched characters for external highlighting (#4726)- Allow adaptive height with negative value (
--height=~-HEIGHT) (#4682) - Bug fixes
--walker=followno longer follows symlinks whose target is an ancestor of the walker root, avoiding severe resource exhaustion when a symlink points outside the tree (e.g. Wine'sz:β/) (#4710)- Fixed AWK tokenizer not treating a new line character as whitespace
- Fixed
--{accept,with}-nthremoving trailing whitespaces with a non-default--delimiter - Fixed OSC8 hyperlinks being mangled when the URL contains unicode characters (#4707)
- Fixed
--with-shellnot handling quoted arguments correctly (#4709) - Fixed child processes not being terminated on Windows (#4723) (@pjeby)
- Fixed preview scrollbar not rendered after
toggle-preview - Fixed preview follow/scroll with long wrapped lines
- Fixed tab width when
--frozen-leftis used - Fixed preview mouse events being processed when no preview window exists
- zsh: Fixed history widget when
sh_globoption is on (#4714) (@EvanHahn)
0.70.0
Demo: change-with-nth
change-with-nth.mp4
Summary
- Added
change-with-nthaction for dynamically changing the--with-nthoption.- Requires
--with-nthto be set initially. - Multiple options separated by
|can be given to cycle through.
echo -e "a b c\nd e f\ng h i" | fzf --with-nth .. \ --bind 'space:change-with-nth(1|2|3|1,3|2,3|)'
- Requires
- Added
change-header-linesaction for dynamically changing the--header-linesoption - Performance improvements (1.3x to 1.9x faster filtering depending on query)
=== query: 'l' === [all] baseline: 168.87ms current: 95.21ms (1.77x) matches: 5069891 (94.78%) [1T] baseline: 1652.22ms current: 841.40ms (1.96x) matches: 5069891 (94.78%) === query: 'lin' === [all] baseline: 343.27ms current: 252.59ms (1.36x) matches: 3516507 (65.74%) [1T] baseline: 3199.89ms current: 2230.64ms (1.43x) matches: 3516507 (65.74%) === query: 'linux' === [all] baseline: 85.47ms current: 63.72ms (1.34x) matches: 307229 (5.74%) [1T] baseline: 774.64ms current: 589.32ms (1.31x) matches: 307229 (5.74%) === query: 'linuxlinux' === [all] baseline: 55.13ms current: 35.67ms (1.55x) matches: 12230 (0.23%) [1T] baseline: 461.99ms current: 332.38ms (1.39x) matches: 12230 (0.23%) === query: 'linuxlinuxlinux' === [all] baseline: 51.77ms current: 32.53ms (1.59x) matches: 865 (0.02%) [1T] baseline: 409.99ms current: 296.33ms (1.38x) matches: 865 (0.02%) - Fixed
nthattribute merge order to respect precedence hierarchy (#4697) - bash: Replaced
printfwith builtinprintfto bypass local indirections (#4684) (@DarrenBishop)
0.68.0
preview-wrap-word.mp4
- Implemented word wrapping in the list section
- Added
--wrap=word(or--wrap-word) option andtoggle-wrap-wordaction for word-level line wrapping in the list section - Changed default binding of
ctrl-/andalt-/fromtoggle-wraptotoggle-wrap-word
fzf --wrap=word
- Added
- Implemented word wrapping in the preview window
- Added
wrap-wordflag for--preview-windowto enable word-level wrapping - Added
toggle-preview-wrap-wordaction
fzf --preview 'bat --style=plain --color=always {}' \ --preview-window wrap-word \ --bind space:toggle-preview-wrap-word - Added
- Added support for underline style variants in
--color:underline-double,underline-curly,underline-dotted,underline-dashedfzf --color 'fg:underline-curly,current-fg:underline-dashed' - Added support for underline styles (
4:N) and underline colors (SGR 58/59)# In the list section printf '\e[4:3;58;2;255;0;0mRed curly underline\e[0m\n' | fzf --ansi # In the preview window fzf --preview "printf '\e[4:3;58;2;255;0;0mRed curly underline\e[0m\n'"
- Added
--preview-wrap-signto set a different wrap indicator for the preview window - Added
alt-guttercolor option (#4602) (@hedgieinsocks) - Added
$FZF_WRAPenvironment variable to child processes (charorwordwhen wrapping is enabled) (#4672) (@bitraid) - fish: Improved command history (CTRL-R) (#4672) (@bitraid)
- Enabled syntax highlighting in the list on fish 4.3.3+
- Added syntax-highlighted preview window that auto-shows for long or multi-line commands
- Added
ALT-ENTERto reformat and insert selected commands - Improved handling of bulk deletion of selected history entries (
SHIFT-DELETE)
- Added fish completion support (#4605) (@lalvarezt)
- zsh: Handle multi-line history selection (#4595) (@LangLangBart)
- Bug fixes
- Fixed
_fzf_compgen_{path,dir}to respectFZF_COMPLETION_{PATH,DIR}_OPTS(#4592) (@shtse8, @LangLangBart) - Fixed
--preview-window follownot working correctly with wrapping (#3243, #4258) - Fixed symlinks to directories being returned as files (#4676) (@skk64)
- Fixed SIGHUP signal handling (#4668) (@LangLangBart)
- Fixed preview process not killed on exit (#4667)
- Fixed coloring of items with zero-width characters (#4620)
- Fixed
track-currentunset after a combined movement action (#4649) - Fixed
--accept-nthbeing ignored in filter mode (#4636) (@charemma) - Fixed display width calculation with
maxWidth(#4596) (@LangLangBart) - Fixed clearing of the rest of the current line on start (#4652)
- Fixed
x-api-keyheader not required for GET requests (#4627) - Fixed key reading not cancelled when
executetriggered via a server request (#4653) - Fixed rebind of readline command
redraw-current-line(#4635) (@jameslazo) - Fixed
fzf-tmuxTERMquoting and addedmktempusage (#4664) (@Goofygiraffe06) - Do not allow very long queries in
FuzzyMatchV2(#4608)
- Fixed
0.67.0
- Added
--freeze-left=Noption to keep the leftmost N columns always visible.# Keep the file name column fixed and always visible git grep --line-number --color=always -- '' | fzf --ansi --delimiter : --freeze-left 1 # Can be used with --keep-right git grep --line-number --color=always -- '' | fzf --ansi --delimiter : --freeze-left 1 --keep-right
- Also added
--freeze-right=Noption to keep the rightmost N columns always visible.# Stronger version of --keep-right that always keeps the right-end visible fd | fzf --freeze-right 1 # Keep the base name always visible fd | fzf --freeze-right 1 --delimiter / # Keep both leftmost and rightmost components visible fd | fzf --freeze-left 1 --freeze-right 1 --delimiter /
- Updated
--info=inlineto print the spinner (load indicator). - Bug fixes