Configuring FZF_DEFAULT_COMMAND
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:
bashexport 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:
| Method | Time to Interactive UI | Notes |
|---|---|---|
| fzf built-in walker | ~0.011s | Marginally faster |
| ripgrep | fzf | ~0.015s | Negligible 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:
- Walk the directory tree
- Check
.gitignorerules for each file - 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-skipfor 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
.gitignoreby default (huge win for Git repos) - β
Respects
.ignore,.rgignorefiles - β 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:
bashexport FZF_DEFAULT_COMMAND='rg --files --hidden --follow --glob "!.git/*"'
fd (Modern Alternative)
Pros:
- β
Respects
.gitignoreby 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:
bashexport FZF_DEFAULT_COMMAND='fd --type f --hidden --follow --exclude .git'
Real-World File Count Comparison
Testing on midimaze vault (development repository):
| Method | Files Found | What's Included |
|---|---|---|
find | 13,365 | Everything (including .obsidian, .DS_Store, etc.) |
rg --files --no-ignore | 6,082 | Everything except .git |
rg --files | 4,936 | Respects .gitignore β
|
| fzf walker | Similar to find | No .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)
bashexport 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
bashexport 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!
| Binding | Variable | Default |
|---|---|---|
fzf (bare command) | FZF_DEFAULT_COMMAND | Built-in walker |
| CTRL-T | FZF_CTRL_T_COMMAND | --walker file,dir,follow,hidden |
| ALT-C | FZF_ALT_C_COMMAND | --walker dir,follow,hidden |
| CTRL-R | N/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)
rfvfunction 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
bashexport 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
- Tool Composition - fzf ripgrep zoxide - How these tools work together
- Yazi Navigation with fzf and zoxide - Using fzf in Yazi
- ripgrep - Fast content and file search
Links
Official Documentation
- fzf walker options: https://github.com/junegunn/fzf#directory-traversal
- ripgrep files mode: https://github.com/BurntSushi/ripgrep/blob/master/GUIDE.md#manual-filtering-globs
- fd usage: https://github.com/sharkdp/fd#usage
- Summary: Comparison of file discovery tools for fzf configuration