I’ve been getting into fzf recently. In case what it does isn’t immediately obvious to you (it wasn’t to me), here’s what it does:

  1. You send a bunch of things to fzf, one per line.
  2. fzf lets you pick one (or more!) of the things that was sent to it.
  3. fzf prints, to standard output, that thing or those things that you picked.

This has a couple obvious use cases:

If you install fzf by hand, you’ll get an opportunity to let it install its own things into your shell’s configuration. If you let it, it’ll set up C-t, C-r, and M-c so that they run a “file widget”, “history widget”, and a “cd widget”, respectively. Pretty handy, but:

I then tried to see if I could get 95% of what I wanted with 0% of the invasive code in my ~/.config/fish/.

Searching through history

Normally, when I want to search through my history, I run hgrep foo, where hgrep is short for history | grep.

I ended up with this:

function hfzf
    set -l to_run (history | fzf)
    if test -n "$to_run"
        echo "$to_run"
        eval "$to_run"

Note that fish won’t let you just run (history | fzf). It’ll give you an error of fish: Command substitutions not allowed. I’m not sure, but I think this is to keep fish users from shooting themselves in the foot. However, if you explicitly set that command to a variable and then run eval on it, fish will let you do what you want.

The echo line is there because it feels weird to run a command that hasn’t been printed to the console in some form. bash will print out lines that have had command-substitution magic (!!, etc.) applied to them; I wanted the same thing in fish with fzf.

Running it is easy. I just type hfzf, pick the history item from the list, and then hit Enter to run it.

Changing directories

fish already has cdh for “change to a recently-visited directory”, so what about cdf for “fuzzy cd”?

function cdf
    set -l whither
    if command -sq fd
        set whither (fd --type d | fzf)
        set whither (find . -type d | fzf)
    test -n "$whither"; and cd "$whither"

After declaring a local variable, this tests to see if fd is installed. fd is a Rust-based reimplementation of find. Most importantly, it ignores hidden files by default, so it won’t waste time and disk reads by trawling through .git/objects/ directories looking for directories to change to.

I don’t have fd installed on all my machines, so I have a fallback case that uses find.

The final interesting line tests to make sure $whither actually has something in it before changing directories. If I quit out of fzf without picking anything, I don’t want to run cd with no arguments. That’ll just drag me back to my home directory, which likely isn’t what I want.


Two functions in two files gives me most of what I want out of fzf without deeply integrating it into my shell configuration in weird ways. If you dislike it when your utilities get their hooks into your shell, maybe you’ll find all this useful.