Skip to main content

Custom Shell Completions

Beyond the built-in ** completion trigger for standard commands, you can create fully custom fzf completions for any command.

How Shell Completion Works with fzf

When you press <Tab> after **, fzf intercepts the completion event and calls your custom _fzf_complete_COMMAND function.

Writing a Custom Completion

Bash Completion Function

~/.bashrc
# Custom completion for a command called 'deploy'
_fzf_complete_deploy() {
# $@ contains the current command line tokens
_fzf_complete --multi --prompt="Environment> " -- "$@" < <(
# Produce the list of completions
echo "development"
echo "staging"
echo "production-us-east"
echo "production-eu-west"
)
}

# Register the completion
complete -F _fzf_complete_deploy deploy

Post-process the Selection

# The _fzf_complete_deploy_post function transforms the selected value
_fzf_complete_deploy_post() {
# Read from stdin, transform, write to stdout
awk '{print $1}' # take only first column
}

Real-World: kubectl Completion

~/.bashrc
# Pick kubernetes contexts with fzf
_fzf_complete_kubectl() {
if [[ $COMP_LINE == *"kubectl config use-context"* ]]; then
_fzf_complete --prompt="Context> " -- "$@" < <(
kubectl config get-contexts -o name 2>/dev/null
)
else
_fzf_complete -- "$@" < <(
kubectl get all --all-namespaces 2>/dev/null | awk '{print $1"/"$2}'
)
fi
}
complete -F _fzf_complete_kubectl kubectl

Real-World: SSH Completion Enhanced

~/.bashrc
_fzf_complete_ssh() {
_fzf_complete --prompt="Host> " -- "$@" < <(
{
# From known_hosts
cat ~/.ssh/known_hosts 2>/dev/null | awk '{print $1}' | tr ',' '\n'
# From config hosts
grep -E "^Host " ~/.ssh/config 2>/dev/null | awk '{print $2}'
} | grep -v '\*' | sort -u
)
}
complete -F _fzf_complete_ssh ssh

Real-World: Git Branch Completion

~/.bashrc
_fzf_complete_git() {
local subcommand="${COMP_WORDS[1]}"
case "$subcommand" in
checkout|co|switch|merge|rebase|cherry-pick|branch)
_fzf_complete --prompt="Branch> " -- "$@" < <(
git branch --all 2>/dev/null | grep -v HEAD | sed 's/^[* ]*//' | sed 's#remotes/origin/##' | sort -u
)
;;
*)
_fzf_complete_git_default "$@"
;;
esac
}
complete -F _fzf_complete_git git

Zsh Custom Completions

~/.zshrc
# Zsh: override completion for 'deploy'
_fzf_complete_deploy() {
_fzf_complete -- "$@" < <(
print -l development staging production
)
}

Triggering Custom Completion

By default, **<Tab> triggers fzf completion. Override the trigger:

~/.bashrc
export FZF_COMPLETION_TRIGGER='~~'   # Use ~~ instead of **
# Now: vim ~~<Tab> triggers fzf

What's Next