Skip to main content

Basic Search

rg syntax is:

rg [OPTIONS] PATTERN [PATH ...]

If PATH is omitted, rg searches the current working directory recursively.

Your First Searches

# Search the current project for any occurrence of "TODO"
rg "TODO"

# Search a specific directory
rg "error" /var/log/

# Search a single file
rg "return" src/app.py

rg automatically outputs:

  • Grouped by file (filename header in bold)
  • Line numbers for every match
  • Colorized match highlighting
src/app.py
42: return HttpResponse(data)
87: return render(request, "index.html")

src/utils.py
15: return cache.get(key)

Searching for Phrases (Spaces)

Wrap patterns in quotes to prevent the shell from splitting on spaces:

rg "connection refused"
rg "def process_data"
rg "404 Not Found"

Anchoring to Filename vs Full Path

By default the PATTERN is matched against file contents. If you want to search by filename, use fd or find. rg searches text.

Case Sensitivity

By default rg is case-sensitive:

rg "error" # matches "error" but NOT "Error" or "ERROR"
rg -i "error" # case-insensitive: matches all variants

rg also has a "smart case" mode (similar to fd):

rg -S "error" # smart case: lowercase = insensitive, any uppercase = sensitive
rg -S "Error" # smart case: uppercase present → strict case-sensitive

Exit Codes (Critical for Scripting)

Like grep, rg communicates match status via exit codes:

CodeMeaning
0At least one match found
1No matches
2Error (bad pattern, file not found)
# Use in a CI health check
if rg -q "FIXME" src/; then
echo "Blocking: FIXME comments found"
exit 1
fi

(The -q / --quiet flag suppresses all output and returns only the exit code).