Improve your Shell with FZF and Friends
If you spend lots of time in the terminal fuzzy searching can be an absolute game changer - at least it was for me. Tools like FZF, FZY, or Selecta allow you to interactively filter files, commands and - with some additional configuration - much, much more.
I’ve been using FZF for a couple of years now and in that time I’ve come to love a number of projects, tools, and little command line snippets that work together with FZF to improve the user experience on the terminal. Sure, fuzzy searching for files is great and all - but what else can you do with FZF?
I use ZSH together with Tmux , and FZF is my fuzzy finder of choice. So that is what I’ll focus on. If your setup deviates you may not be able to use some of the tools shown below. But keep on reading, you might still find something useful, who knows?
The Basics
A mentioned before, FZF allows you to interactively filter - well, anything really. Per default you can use Ctrl+T
to fuzzily search for files, or Ctrl+R
to fuzzily search through your history.
You can create your own fuzzy commands by piping some output to FZF:
# Search output of `ls`
ls | fzf
The command above will allow you to interactively filter the contents of the current directory. That is pretty nifty already, but you can make some adjustments to make it even niftier.
You can customize how your fuzzy finder looks by setting a number of environment variables. For example, to change the height of the interactive widget you can use something similar to this:
FZF_DEFAULT_OPTS='--height 50% --ansi'
Per default FZF uses grep
under to hood to filter strings. I recommend that you replace grep with ripgrep. While grep
is available on most platforms, ripgrep is a fair bit faster - which is quite noticeable when you filter many items.
To tell FZF to use ripgrep you need to modify FZF_DEFAULT_COMMAND
.
FZF_DEFAULT_COMMAND='rg --files --no-ignore --hidden --follow --glob "!.git/*"'
Completions
FZF provides tab completion for some commands out of the box. The readme lists a number of examples of which commands are supported.
# Select process
kill -9 <TAB>
# Select host names
ssh **<TAB>
You can create your own completions as well! I actually wrote my own tab completion for git a while ago. But I would not recommend that to be honest. Writing custom completions using the custom completion API provided by FZF is quite limiting and feels a bit clunky.
If you are using ZSH I have something way better for you.
fzf-tab uses the ZSH completion definitions of commands to provide fuzzy completion. In other words: Anything that provides tab completion now provides fuzzy completions. It works for arguments, options, anything.
As nice as the things that FZF provides per default are… this just knocks it out of the park. Forgot what that one option was called? Fuzzy search it. Can’t remember the exact name of some branch? Fuzzy search it. This plugin makes working in the command line much more fun.
But wait, there’s more…
Navigation
What about navigating through the file system? You might already use something like Autojump, Z or FASD. You can make those tools even better by integrating them with FZF. Have a look at these examples.
I personally enjoy enhancd, which aliases cd
and has some useful additional features. Definitely worth checking out.
Tmux
Tmux is a terminal multiplexer. It allows you to create multiple concurrent terminal sessions and also allows you to arrange terminals in tabs, windows and panes. It is a central part of my workflow.
If you too use Tmux a lot you may have also found navigation between different sessions, windows and panes a bit painful at times. Well, guess what? Fuzzy search to the rescue! 😉
The FZF wiki provides some examples of how to integrate Tmux with FZF. Make sure that the function you are trying to use is on your path (for example by creating an executable script), and then, in your tmux.conf
, bind a key of your choice to it.
With some basic scripting you can adapt the examples there to your needs. For example, to kill a session I use an adapted version of tmuxkillf
as a standalone executable. This will list all open sessions (except the current one) and allow you to multi-select with ones to kill.
#!/usr/bin/env bash
# Inspired and adapted from here: https://github.com/junegunn/fzf/wiki/Examples#tmux
tmuxkillf () {
local target_sessions current_session
current_session=$(tmux display-message -p '#S')
target_sessions=$(tmux ls | \
cut -d: -f1 | \
sed "/$current_session/d" | \
fzf --exit-0 --query="$1" --multi --exit-0) || return $?
for session in $target_sessions; do
session=${session%%:*}
tmux kill-session -t "$session"
done
}
tmuxkillf "$@"
To leverage the created functions bind them to a key in your .tmux.conf
:
bind-key C-x run "tmux split-window -l 15 'bash -ci tmuxkillf'"
Conclusion
The things outlined above are just the tip of the iceberg. I only covered tools that I personally use on the command line - obviously you can integrate FZF with your editor as well (for example using fzf-vim). There are tons of other more or less useful projects using FZF. Want to fuzzily search for emojis? EmojiCLI got your back!
If you want to know more the FZF wiki contains a list of projects related to FZF that I encourage you to skim. I personally want to highlight Forgit (a git wrapper using FZF) and Live REPL (an experimental live REPL) because both are projects that I feel really show what is possible with FZF.
If you haven’t given FZF (or other fuzzy filters) a try yet I hope this post inspired you to try it out yourself! And if you are already a FZF veteran: I hope you still learned something new. Feel free to share your best FZF hacks.