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).