← Back to articles

Configuring FZF_DEFAULT_COMMAND

Path: Computer Tech/Terminal/fzf/Configuring FZF_DEFAULT_COMMAND.mdUpdated: 2/3/2026

Configuring FZF_DEFAULT_COMMAND

Should you configure FZF_DEFAULT_COMMAND to use ripgrep instead of fzf's built-in walker? It depends on your use case. Here's the complete breakdown.

TL;DR Recommendation

For most developers working in Git repositories:

bash
export FZF_DEFAULT_COMMAND='rg --files --hidden --follow --glob "!.git/*"'

Why: Respects .gitignore automatically, which is usually what you want when fuzzy-finding files in your projects.

Performance Comparison

TL;DR: Performance is essentially identical for interactive use (~0.01-0.02s difference).

Tested on ~/Code/github.com/theslyprofessor directory:

MethodTime to Interactive UINotes
fzf built-in walker~0.011sMarginally faster
ripgrep | fzf~0.015sNegligible difference

The performance difference is ~4 milliseconds - completely imperceptible to humans.

Why You Might Have Heard "ripgrep is slower"

When benchmarking file listing (not fzf usage), ripgrep must:

  1. Walk the directory tree
  2. Check .gitignore rules for each file
  3. Pipe all results to stdout

This takes ~0.2s for 30,000+ files. But in interactive fzf usage, both methods start showing results almost instantly because:

  • fzf's walker streams results internally (no IPC overhead)
  • ripgrep pipes to fzf as results are found (streaming, not batch)
  • You see the UI in ~10ms either way

Feature Comparison

fzf Built-in Walker

Pros:

  • βœ… Marginally faster (~4ms difference, imperceptible)
  • βœ… Works out-of-the-box (no dependencies)
  • βœ… Cross-platform consistency (Windows/macOS/Linux)
  • βœ… Configurable via --walker-skip for basic exclusions

Cons:

  • ❌ Does NOT respect .gitignore
  • ❌ Less flexible filtering options
  • ❌ Can't leverage advanced ignore patterns (like .fdignore, .rgignore)

Default behavior:

bash
# Skips these directories by default:
--walker-skip .git,node_modules

# Lists:
# - All files (including hidden)
# - Follows symlinks
# - Hidden files included

ripgrep (rg --files)

Pros:

  • βœ… Respects .gitignore by default (huge win for Git repos)
  • βœ… Respects .ignore, .rgignore files
  • βœ… Extremely fast (Rust-based)
  • βœ… Flexible ignore patterns via --glob
  • βœ… Can show git-ignored files with --no-ignore

Cons:

  • ❌ Theoretically slower (~4ms), but imperceptible in practice
  • ❌ Requires ripgrep to be installed
  • ❌ Process spawning overhead

Common configuration:

bash
export FZF_DEFAULT_COMMAND='rg --files --hidden --follow --glob "!.git/*"'

fd (Modern Alternative)

Pros:

  • βœ… Respects .gitignore by default
  • βœ… User-friendly syntax
  • βœ… Fast (Rust-based, like ripgrep)
  • βœ… Colorized output

Cons:

  • ❌ Requires fd to be installed
  • ❌ Slower than fzf built-in walker

Common configuration:

bash
export FZF_DEFAULT_COMMAND='fd --type f --hidden --follow --exclude .git'

Real-World File Count Comparison

Testing on midimaze vault (development repository):

MethodFiles FoundWhat's Included
find13,365Everything (including .obsidian, .DS_Store, etc.)
rg --files --no-ignore6,082Everything except .git
rg --files4,936Respects .gitignore βœ…
fzf walkerSimilar to findNo .gitignore support

Key insight: .gitignore excluded ~1,146 files (mostly in _Nakul/ private directory).

Decision Matrix

Use fzf Built-in Walker When:

βœ… Working in non-Git directories

bash
# No configuration needed - just use fzf
fzf

βœ… Maximum speed is critical (large monorepos, instant response needed)

βœ… You want to see ALL files (including gitignored ones)

bash
# Useful for debugging .gitignore issues
fzf --walker file,hidden --walker-skip .git

βœ… Minimal dependencies (e.g., fresh server installs)

Use ripgrep When:

βœ… Working in Git repositories (most common use case)

bash
export FZF_DEFAULT_COMMAND='rg --files --hidden --follow --glob "!.git/*"'

βœ… You want to respect .gitignore (don't waste time selecting ignored files)

βœ… Advanced filtering needs

bash
# Example: Exclude multiple patterns
export FZF_DEFAULT_COMMAND='rg --files --hidden --follow \
  --glob "!.git/*" \
  --glob "!node_modules/*" \
  --glob "!target/*" \
  --glob "!*.pyc"'

βœ… Cross-project consistency (same ignore rules as your editor, grep, etc.)

Use fd When:

βœ… You prefer user-friendly syntax

bash
export FZF_DEFAULT_COMMAND='fd --type f --hidden --follow --exclude .git'

βœ… You want colorized file type indicators (less relevant for fzf)

βœ… Already using fd for other tasks (consistency)

Recommended Configurations

Option 1: Git-Aware Developer (Recommended for Most)

bash
# .zshrc or .bashrc
export FZF_DEFAULT_COMMAND='rg --files --hidden --follow --glob "!.git/*"'
export FZF_DEFAULT_OPTS='--height 40% --layout reverse --border'

Why: Respects your .gitignore, which is usually what you want. Speed difference (~0.15s) is negligible for human interaction.

Option 2: Maximum Speed Purist

bash
# No FZF_DEFAULT_COMMAND needed - use built-in walker
export FZF_DEFAULT_OPTS='--walker file,follow,hidden --walker-skip .git,node_modules,target --height 40% --layout reverse --border'

Why: Absolute fastest. Good for large codebases where 0.15s adds up.

Option 3: Hybrid Approach

bash
# Use built-in walker by default (fast)
# Override for shell integration (git-aware)
export FZF_CTRL_T_COMMAND='rg --files --hidden --follow --glob "!.git/*"'
export FZF_ALT_C_COMMAND='fd --type d --hidden --follow --exclude .git'

Why: Best of both worlds - bare fzf is fast, CTRL-T respects .gitignore.

Testing Your Configuration

Check what fzf uses:

bash
# See if FZF_DEFAULT_COMMAND is set
echo $FZF_DEFAULT_COMMAND

# Test file discovery (first 10 files)
fzf --print0 < /dev/null 2>/dev/null | head -c 1000 | tr '\0' '\n'

Compare file counts:

bash
# Built-in walker
fzf --walker file --walker-root . --print-query <<< "" 2>/dev/null | wc -l

# ripgrep
rg --files | wc -l

# ripgrep (no .gitignore)
rg --files --no-ignore | wc -l

Performance benchmark:

bash
# Time built-in walker
time bash -c 'fzf --walker file --print-query <<< "" > /dev/null 2>&1'

# Time ripgrep
time bash -c 'rg --files | fzf --filter "" > /dev/null 2>&1'

Special Cases

Working with Private/Ignored Files

Sometimes you WANT to see gitignored files:

bash
# Temporarily override to see everything
FZF_DEFAULT_COMMAND='rg --files --no-ignore --hidden' fzf

# Or use fzf built-in walker
fzf --walker file,hidden --walker-skip .git

Excluding Specific Directories Beyond .gitignore

bash
# ripgrep with custom exclusions
export FZF_DEFAULT_COMMAND='rg --files --hidden --follow \
  --glob "!.git/*" \
  --glob "!node_modules/*" \
  --glob "!*.min.js" \
  --glob "!dist/*"'

# fzf walker
export FZF_DEFAULT_OPTS='--walker-skip .git,node_modules,dist,target,__pycache__'

Multi-Repo Workspaces

If you work across Git and non-Git directories:

bash
# Smart detection (use ripgrep if .git exists)
export FZF_DEFAULT_COMMAND='
  if [ -d .git ]; then
    rg --files --hidden --follow --glob "!.git/*"
  else
    fzf --walker file,hidden --walker-skip .git
  fi
'

Shell Integration Variables

Important: FZF_DEFAULT_COMMAND is NOT used by shell integration!

BindingVariableDefault
fzf (bare command)FZF_DEFAULT_COMMANDBuilt-in walker
CTRL-TFZF_CTRL_T_COMMAND--walker file,dir,follow,hidden
ALT-CFZF_ALT_C_COMMAND--walker dir,follow,hidden
CTRL-RN/A (uses shell history)N/A

To configure shell integration:

bash
# Override CTRL-T to use ripgrep
export FZF_CTRL_T_COMMAND='rg --files --hidden --follow --glob "!.git/*"'

# Or use --walker options
export FZF_CTRL_T_OPTS='--walker-skip .git,node_modules'

My Personal Setup

bash
# shell-config/zsh/environment.zsh
# Use ripgrep for FZF_DEFAULT_COMMAND (most common use case)
export FZF_DEFAULT_COMMAND='rg --files --hidden --follow --glob "!.git/*"'

# CTRL-T uses same command
export FZF_CTRL_T_COMMAND="$FZF_DEFAULT_COMMAND"

# Global fzf options
export FZF_DEFAULT_OPTS='
  --height 40%
  --layout reverse
  --border
  --preview "bat --color=always --style=numbers --line-range=:500 {}"
  --preview-window "~3"
'
bash
# shell-config/zsh/aliases.zsh
# Interactive ripgrep -> fzf -> nvim (rfv function)
# Usage: rfv [search query]
rfv() (
  RELOAD='reload:rg --column --color=always --smart-case {q} || :'
  OPENER='if <span class="wikilink-broken" title="Page not found:  $FZF_SELECT_COUNT -eq 0 "> $FZF_SELECT_COUNT -eq 0 </span>; then
            nvim {1} +{2}     # No selection. Open the current line in Neovim.
          else
            nvim +cw -q {+f}  # Build quickfix list for the selected items.
          fi'
  fzf --disabled --ansi --multi \
      --bind "start:$RELOAD" --bind "change:$RELOAD" \
      --bind "enter:become:$OPENER" \
      --bind "ctrl-o:execute:$OPENER" \
      --bind 'alt-a:select-all,alt-d:deselect-all,ctrl-/:toggle-preview' \
      --delimiter : \
      --preview 'bat --style=full --color=always --highlight-line {2} {1}' \
      --preview-window '~4,+{2}+4/3,<80(up)' \
      --query "$*"
)

Why this setup:

  • Respects .gitignore (avoids selecting files I don't care about)
  • Fast enough for my workflows (~4ms difference is imperceptible)
  • Consistent with my editor's file search behavior
  • Preview window with syntax highlighting (bat)
  • rfv function for interactive code search (live ripgrep + preview)

Usage examples:

bash
# File navigation
fzf              # Browse files (respects .gitignore)
vim $(fzf)       # Open file in vim

# Interactive code search
rfv TODO         # Search for "TODO" in current directory
rfv "export.*FZF"  # Regex search for FZF exports
# Type to refine search, TAB to multi-select, Enter to open

Conclusion

Should you configure FZF_DEFAULT_COMMAND?

Yes, if you work in Git repositories β†’ Use ripgrep

bash
export FZF_DEFAULT_COMMAND='rg --files --hidden --follow --glob "!.git/*"'

Maybe not, if:

  • You work in non-Git directories
  • You need absolute maximum speed
  • You want to see ALL files (including gitignored)

The ~0.15s speed difference is negligible for interactive use, and respecting .gitignore is usually the right behavior for development workflows.

Related Articles

Links

Official Documentation