rg is the tool with the most sensible defaults for searching a whole project. It skips node_modules and .git on its own and uses every core you have.

Install

  brew install ripgrep          # macOS
sudo apt install ripgrep      # Ubuntu 18.10+
winget install BurntSushi.ripgrep.MSVC
  

Basics

  rg "createUser"                    # search the whole current directory
rg "createUser" src/               # limit to a directory
rg -i "createuser"                 # case insensitive
rg -w "id"                         # whole word (won't match "identity")
rg -F "a.b.c"                      # literal string, not a regex
  

Options worth knowing

OptionMeaning
-t py / -t jsOnly files of a language (rg --type-list for the full set)
-T testExclude a type
-g '*.md'Include by glob
-g '!dist/*'Exclude by glob
-lPrint filenames only
-cCount matches per file
-nLine numbers (on by default)
-A 3 / -B 3 / -C 3Context lines after / before / both
--hiddenInclude hidden files
-u / -uuRelax / ignore the ignore rules

In practice

  # rank files by how many TODOs they carry
rg -c "TODO" | sort -t: -k2 -rn | head

# find env var usage with context
rg -C 2 "process\.env\." -t ts

# find declarations only
rg "^(export )?(async )?function \w+" -t ts

# search, then replace across the matches (needs sd)
rg -l "oldName" | xargs sd "oldName" "newName"
  

Replacing text

ripgrep itself only previews replacements.

  rg "oldName" -r "newName"     # shows the result; files are untouched
  

To change files, combine it with sd or sed.

  brew install sd
rg -l "oldName" | xargs sd "oldName" "newName"
  

Config file

Move repeated options out into a config.

  # ~/.ripgreprc
--smart-case
--hidden
--glob=!.git/*
--max-columns=200
  
  # ~/.zshrc
export RIPGREP_CONFIG_PATH="$HOME/.ripgreprc"
  

Next

When you’re searching by filename rather than content, reach for fdfd

Last updated 19 Aug 2026, 00:00 UTC. history