Skip to content

fzf - Street-Level Ops

Real-world workflows for interactive selection and filtering in DevOps tasks.

Quick Interactive File Finder

# Pick a file from the project and open it
vim $(fd -t f | fzf)

# Pick a file with preview (requires bat or cat)
fd -t f | fzf --preview 'head -40 {}'

# Pick a file with syntax-highlighted preview
fd -t f | fzf --preview 'bat --color=always --line-range :40 {}'

Gotcha: If fzf shows no results, the input pipe is empty. fd excludes .git/ and respects .gitignore by default — use fd -H (hidden) or fd -I (no-ignore) if you need those files. Plain find works too: find . -type f | fzf.

Kubernetes Operations

# Switch namespace interactively
kubectl config set-context --current --namespace \
  $(kubectl get ns -o name | sed 's|namespace/||' | fzf)

# Tail logs from a selected pod
kubectl get pods -o name | fzf | xargs -I{} kubectl logs -f {}

# Exec into a selected pod
kubectl get pods -o name | fzf --preview 'kubectl describe {}' | \
  xargs -I{} kubectl exec -it {} -- sh

# Delete a selected pod (with confirmation preview)
kubectl get pods | fzf --header-lines=1 | awk '{print $1}' | \
  xargs -p kubectl delete pod

# Describe a selected deployment
kubectl get deployments -o name | fzf --preview 'kubectl get {} -o yaml' | \
  xargs kubectl describe

# Select multiple pods to restart
kubectl get pods -o name | fzf -m | xargs kubectl delete

Remember: Tab selects/deselects in multi-mode (-m). Shift+Tab deselects. Ctrl+A selects all (if you add --bind 'ctrl-a:select-all'). These keybindings turn fzf from "pick one thing" into "batch operations on chosen items."

Default trap: fzf without input falls back to find . which can be extremely slow in large repos or directories with node_modules. Always set FZF_DEFAULT_COMMAND='fd --type f --hidden --follow --exclude .git' in your shell profile — fd respects .gitignore and is 10-50x faster than find.

Git Operations

# Checkout a branch interactively
git branch -a | sed 's/^\*//' | fzf | xargs git checkout

# Browse git log and preview commits
git log --oneline --all | fzf --preview 'git show --stat {1}'

# Stage files interactively (multi-select with Tab)
git diff --name-only | fzf -m | xargs git add

# View a specific commit's diff
git log --oneline | fzf --preview 'git diff {1}^..{1}' | awk '{print $1}'

# Cherry-pick from another branch
git log --oneline other-branch | fzf | awk '{print $1}' | xargs git cherry-pick

Docker Operations

# Exec into a running container
docker exec -it $(docker ps --format '{{.Names}}' | fzf) bash

# View logs from a selected container
docker ps --format '{{.Names}}' | fzf | xargs docker logs -f

# Remove stopped containers interactively
docker ps -a --format '{{.Names}} ({{.Status}})' | fzf -m | \
  awk '{print $1}' | xargs docker rm

# Select an image to inspect
docker images --format '{{.Repository}}:{{.Tag}}' | fzf | xargs docker inspect

One-liner: Interactive git stash browser: git stash list | fzf --preview 'git stash show -p {1}' | awk -F: '{print $1}' | xargs git stash apply — preview each stash diff, select one, and apply it.

Log and Process Investigation

# Search environment variables
env | fzf

# Filter and kill a process (use -9 only as last resort)
kill $(ps aux | fzf --header-lines=1 | awk '{print $2}')

# Select from grep results and open in editor
rg -n "ERROR" /var/log/app/ | fzf --delimiter=: --preview 'bat --color=always {1} --highlight-line {2}'

# Browse systemd units
systemctl list-units --type=service | fzf --header-lines=1 | awk '{print $1}' | \
  xargs systemctl status

SSH Host Selection

# Pick an SSH host from config
grep '^Host ' ~/.ssh/config | awk '{print $2}' | fzf | xargs ssh

# Pick a host from /etc/hosts or an inventory file
cat inventory.txt | fzf | xargs ssh

# Pick a host and run a command
HOST=$(cat inventory.txt | fzf)
ssh "${HOST}" 'uptime && df -h / && free -m'

Combining fzf with fd and rg

# fd + fzf: find and select files by type
fd -e yaml | fzf -m --preview 'bat --color=always {}'

# rg + fzf: search, select, and open result
rg --color=always --line-number "TODO" | \
  fzf --ansi --delimiter=: \
  --preview 'bat --color=always {1} --highlight-line {2} --line-range {2}:'

# fd + fzf + editor: find, preview, edit
EDITOR=${EDITOR:-vim}
${EDITOR} $(fd -t f | fzf --preview 'bat --color=always {}')

Multi-Select Workflows

# Select multiple files to delete (Tab to select, Enter to confirm)
fd -t f -e bak -e tmp | fzf -m | xargs rm -v

# Select multiple Kubernetes resources to describe
kubectl get all -o name | fzf -m | xargs -I{} kubectl describe {}

# Select multiple git branches to delete
git branch | fzf -m | xargs git branch -d

Shell Setup for Maximum Productivity

# Add to ~/.bashrc or ~/.zshrc
eval "$(fzf --bash)"    # bash (enables Ctrl-R, Ctrl-T, Alt-C)
# eval "$(fzf --zsh)"   # zsh

# Use fd instead of find (much faster)
export FZF_DEFAULT_COMMAND='fd --type f --hidden --follow --exclude .git'
export FZF_DEFAULT_OPTS='--height 40% --layout=reverse --border --info=inline'

# Pro tip: add --bind 'ctrl-/:toggle-preview' to toggle previews with Ctrl-/
export FZF_CTRL_T_COMMAND="${FZF_DEFAULT_COMMAND}"
export FZF_ALT_C_COMMAND='fd --type d --hidden --follow --exclude .git'

# Ctrl-R: fuzzy search command history (built-in after eval)
# Ctrl-T: fuzzy file finder, inserts path at cursor
# Alt-C: fuzzy cd into a directory

Under the hood: eval "$(fzf --bash)" installs three shell functions that override Ctrl-R, Ctrl-T, and Alt-C. The FZF_*_COMMAND variables control what each binding searches. If you use fd as the default command, Ctrl-T becomes blazingly fast even in repos with millions of files.

One-liner: Fastest way to find and edit a file containing a pattern: vim $(rg -l "TODO" | fzf --preview 'rg --color=always "TODO" {}') — search, preview matches, then open.

# Custom keybinding: Ctrl-G to select a git branch
bind '"\C-g": "$(git branch -a | sed s/^..// | fzf)\e\C-e"'

Gotcha: When running fzf inside tmux, use the --tmux flag (fzf 0.48+) to render in a tmux popup instead of taking over the terminal. The flag is silently ignored outside tmux, making it safe to hardcode in shell aliases: alias fzfp='fzf --tmux center,80%'.

Preview Window Customization

# Right-side preview, 60% width
fd -t f | fzf --preview 'bat --color=always {}' --preview-window=right:60%:wrap

# Hidden preview, toggle with ?
fd -t f | fzf --preview 'bat --color=always {}' --preview-window=hidden --bind '?:toggle-preview'

# Top preview for wide terminals
fd -t f | fzf --preview 'head -20 {}' --preview-window=up:40%