# ripgrep — User Guide

ripgrep (`rg`) is a line-oriented search tool that recursively searches directories for regex patterns while respecting gitignore rules. It is fast, cross-platform, and designed as a modern replacement for `grep`. ripgrep runs on Windows, macOS, and Linux with first-class support on all three.

**Version covered:** 15.1.0 | **Binary name:** `rg` | **License:** Unlicense OR MIT

---

## 1. Quick Start

### Your First Search

Search for a word in the current directory:

```bash
rg "TODO"
```

Expected output:

```text
src/main.rs:42:    // TODO: refactor this function
src/lib.rs:107:    // TODO: add error handling
tests/test_core.rs:15:    // TODO: parameterize
```

ripgrep searches recursively, skips binary files, respects `.gitignore`, and highlights matches — all by default.

### Five Commands to Get Started

```bash
# Search for a pattern in a specific directory
rg "pattern" ./src/

# Case-insensitive search
rg -i "error"

# Search only Python files
rg -t py "import requests"

# Show 3 lines of context around matches
rg -C 3 "panic"

# Count matches per file
rg -c "TODO"
```

> [!TIP]
> Run `rg --help` for a compact flag summary, or `rg -h` for a brief overview. The full manual page can be generated with `rg --generate man`.

---

## 2. Installation

### Package Managers

| Platform | Command |
|----------|---------|
| **macOS (Homebrew)** | `brew install ripgrep` |
| **macOS (MacPorts)** | `sudo port install ripgrep` |
| **Ubuntu/Debian** | `sudo apt install ripgrep` |
| **Fedora** | `sudo dnf install ripgrep` |
| **Arch Linux** | `sudo pacman -S ripgrep` |
| **Windows (Chocolatey)** | `choco install ripgrep` |
| **Windows (Scoop)** | `scoop install ripgrep` |
| **Windows (winget)** | `winget install BurntSushi.ripgrep.MSVC` |
| **Cargo (any OS)** | `cargo install ripgrep` |
| **Nix** | `nix-env -i ripgrep` |

### From GitHub Releases

Download prebuilt binaries from [github.com/BurntSushi/ripgrep/releases](https://github.com/BurntSushi/ripgrep/releases). Archives contain the `rg` binary and shell completions.

```bash
# Example: Linux x86_64
curl -LO https://github.com/BurntSushi/ripgrep/releases/download/14.1.1/ripgrep-14.1.1-x86_64-unknown-linux-musl.tar.gz
tar xzf ripgrep-14.1.1-x86_64-unknown-linux-musl.tar.gz
sudo cp ripgrep-14.1.1-x86_64-unknown-linux-musl/rg /usr/local/bin/
```

### Verify Installation

```bash
rg --version
```

Expected output:

```text
ripgrep 15.1.0
```

### Shell Completions

ripgrep can generate completion scripts for your shell:

```bash
# Bash
rg --generate complete-bash > ~/.local/share/bash-completion/completions/rg

# Zsh
rg --generate complete-zsh > ~/.zfunc/_rg

# Fish
rg --generate complete-fish > ~/.config/fish/completions/rg.fish

# PowerShell
rg --generate complete-powershell >> $PROFILE
```

### Man Page

```bash
rg --generate man > rg.1
sudo cp rg.1 /usr/local/share/man/man1/
```

---

## 3. Configuration

### Config File

ripgrep reads a configuration file from the path specified by the `RIPGREP_CONFIG_PATH` environment variable. There is no default config file location — you must set this variable explicitly.

```bash
# Set up a config file (add to your shell profile)
export RIPGREP_CONFIG_PATH="$HOME/.config/ripgrep/config"
```

Config file format — one flag per line:

```text
# Search settings
--smart-case
--hidden
--glob=!.git

# Output settings
--color=always
--heading
--line-number

# Max columns for readability
--max-columns=200
--max-columns-preview
```

> [!IMPORTANT]
> Arguments in the config file are prepended to any arguments you pass on the command line. CLI arguments always take precedence because they come last and override earlier conflicting flags.

### Disabling the Config File

```bash
# Temporarily ignore your config
rg --no-config "pattern"
```

### Ignore Files

ripgrep honors several ignore file formats, applied in this precedence order (highest precedence last):

| File | Scope | Purpose |
|------|-------|---------|
| `.gitignore` | Per-directory | Standard git ignores |
| `.ignore` | Per-directory | ripgrep + other tools (fd, etc.) |
| `.rgignore` | Per-directory | ripgrep-specific ignores |
| Global gitignore | User-wide | Git's `core.excludesFile` |
| `--ignore-file PATH` | Per-invocation | Extra ignore files via CLI |

All ignore files use gitignore syntax. Later sources override earlier ones, and patterns within the same file are applied in order (last match wins).

Example `.rgignore`:

```text
# Skip build artifacts
target/
dist/
node_modules/

# Skip generated files
*.generated.*
*.min.js
```

---

## 4. Core Usage

### Basic Pattern Matching

```bash
# Simple string search
rg "hello world"

# Regex search (default)
rg "fn\s+\w+\("

# Fixed-string search (no regex interpretation)
rg -F "user.name()"

# Search a specific file
rg "pattern" path/to/file.rs

# Search a specific directory
rg "pattern" src/
```

### Case Sensitivity

```bash
# Case sensitive (default)
rg -s "Error"

# Case insensitive
rg -i "error"

# Smart case: insensitive if pattern is all lowercase,
# sensitive if it contains any uppercase
rg -S "error"    # matches Error, ERROR, error
rg -S "Error"    # matches only Error
```

> [!TIP]
> Add `--smart-case` to your config file — it is the most practical default for everyday searching. You can override with `-s` when you need exact case matching.

### Multiple Patterns

```bash
# OR: match any of these patterns
rg -e "TODO" -e "FIXME" -e "HACK"

# Read patterns from a file (one per line)
rg -f patterns.txt

# Read patterns from stdin
echo "pattern" | rg -f -

# Combine file and CLI patterns
rg -f patterns.txt -e "additional_pattern"
```

### Regex Syntax

ripgrep uses Rust's regex engine by default. Common patterns:

| Pattern | Meaning |
|---------|---------|
| `.` | Any character (except newline) |
| `\d` | Digit `[0-9]` |
| `\w` | Word character `[a-zA-Z0-9_]` |
| `\s` | Whitespace |
| `\b` | Word boundary |
| `^` / `$` | Start / end of line |
| `(a\|b)` | Alternation |
| `[abc]` | Character class |
| `[^abc]` | Negated character class |
| `x{3}` | Exactly 3 repetitions |
| `x{2,5}` | 2 to 5 repetitions |
| `x+?` | Non-greedy one-or-more |
| `(?:...)` | Non-capturing group |
| `(?P<name>...)` | Named capture group |
| `(?i)` | Inline case-insensitive flag |

```bash
# IP addresses
rg "\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}"

# Email-like patterns
rg "\b[\w.+-]+@[\w-]+\.[\w.]+\b"

# Function definitions in Python
rg "def \w+\(.*\):"

# URLs
rg "https?://\S+"
```

### Multiline Matching

```bash
# Enable multiline mode
rg -U "struct \w+ \{[^}]*\}"

# Dot matches newlines too
rg -U --multiline-dotall "BEGIN.*?END"
```

### PCRE2 Engine

For advanced regex features (backreferences, lookaheads), use the PCRE2 engine:

```bash
# Enable PCRE2
rg -P "(\w+)\s+\1"           # backreference: repeated word
rg -P "(?<=fn )\w+"          # lookbehind: word after "fn "
rg -P "foo(?=\()"            # lookahead: "foo" followed by "("

# Auto engine: tries default first, falls back to PCRE2
rg --engine auto "(\w+)\s+\1"
```

> [!NOTE]
> PCRE2 support is an optional compile-time feature. Run `rg --pcre2-version` to check if your build includes it. If not, you will see an error when using `-P`.

### Word and Line Matching

```bash
# Match whole words only (adds \b boundaries)
rg -w "error"      # matches "error" but not "errors" or "terror"

# Match entire lines
rg -x "use std::io;"  # only lines that are exactly "use std::io;"
```

### Inverted Matching

```bash
# Show lines that do NOT match
rg -v "^#"         # all non-comment lines
rg -v "^\s*$"      # all non-empty lines
```

---

## 5. Common Tasks

### 5.1 Search Only Certain File Types

ripgrep has 150+ built-in file type definitions:

```bash
# Search only Rust files
rg -t rust "unwrap()"

# Search only JavaScript and TypeScript
rg -t js -t ts "addEventListener"

# Exclude test files
rg -T test "fn main"

# List all built-in types
rg --type-list
```

Expected output from `--type-list` (excerpt):

```text
c: *.c, *.h
cpp: *.cpp, *.cc, *.cxx, *.hpp, *.hh, *.hxx, *.h, *.inl
js: *.js, *.mjs, *.cjs, *.jsx
py: *.py, *.pyi
rust: *.rs
...
```

#### Custom File Types

```bash
# Define a custom type for this invocation
rg --type-add "web:*.html" --type-add "web:*.css" --type-add "web:*.js" -t web "TODO"

# Clear an existing type's definitions
rg --type-clear js --type-add "js:*.mjs" -t js "import"

# Add types via config file for persistent use
# In your config: --type-add=config:*.yaml,*.yml,*.toml,*.json
```

### 5.2 Filter Files with Globs

```bash
# Only search .go files
rg -g "*.go" "func main"

# Exclude test files
rg -g "!*_test.go" "func main"

# Multiple globs
rg -g "*.rs" -g "!tests/*" "pub fn"

# Case-insensitive globs
rg --iglob "*.Readme" "license"

# Only search in a specific directory pattern
rg -g "src/**/*.py" "import"
```

### 5.3 Replace Text (Preview)

ripgrep can show replacements without modifying files:

```bash
# Simple replacement
rg "foo" -r "bar"

# Using capture groups
rg "(\w+)\.unwrap\(\)" -r '${1}.expect("failed")'

# Named capture groups
rg "(?P<year>\d{4})-(?P<month>\d{2})" -r '${month}/${year}'

# Remove matched text (replace with empty)
rg "// TODO:.*" -r ""
```

> [!WARNING]
> The `-r/--replace` flag only changes what ripgrep prints to stdout. It does **not** modify files on disk. To apply changes, pipe through `sed`, use your editor, or a dedicated refactoring tool.

### 5.4 Context Around Matches

```bash
# 5 lines after each match
rg -A 5 "fn main"

# 3 lines before each match
rg -B 3 "panic!"

# 2 lines before and after (context)
rg -C 2 "error"

# Custom context separator
rg -C 2 --context-separator "===" "error"

# No context separator
rg -C 2 --no-context-separator "error"

# Show ALL lines, highlighting matches (like grep --color + cat)
rg --passthru "TODO" src/main.rs
```

### 5.5 Count Matches

```bash
# Count matching lines per file
rg -c "TODO"
```

Expected output:

```text
src/main.rs:3
src/lib.rs:7
tests/test_core.rs:1
```

```bash
# Count individual matches (not lines)
rg --count-matches "the" README.md

# Include files with zero matches
rg -c --include-zero "TODO"
```

### 5.6 List Files Only

```bash
# Files with matches
rg -l "TODO"

# Files without matches
rg --files-without-match "TODO"

# Files that WOULD be searched (no pattern needed)
rg --files

# Combine with globs to see what files match a filter
rg --files -g "*.rs"
```

### 5.7 Search Hidden Files and Ignored Files

By default, ripgrep skips hidden files (dotfiles), files matched by `.gitignore`, and binary files.

```bash
# Include hidden files (dotfiles)
rg --hidden "API_KEY"

# Ignore .gitignore rules
rg --no-ignore "password"

# Ignore all ignore files (.gitignore, .ignore, .rgignore)
rg --no-ignore "debug"

# Search everything: no-ignore + hidden + binary
rg -uuu "pattern"
```

The `-u` flag is cumulative:

| Flag | Effect |
|------|--------|
| `-u` | `--no-ignore` — skip ignore rules |
| `-uu` | `--no-ignore --hidden` — also search hidden files |
| `-uuu` | `--no-ignore --hidden --binary` — search everything |

### 5.8 Search Compressed Files

```bash
# Search inside compressed files (gz, bz2, xz, lzma, lz4, zst)
rg -z "ERROR" /var/log/

# Combine with type filters
rg -z -t log "FATAL" /var/log/
```

Supported compressed formats: `.gz`, `.bz2`, `.xz`, `.lzma`, `.lz4`, `.zst`, `.br`, `.Z`

### 5.9 Search with Specific Encodings

```bash
# Auto-detect encoding (default)
rg "pattern"

# Specify encoding explicitly
rg -E utf-16 "pattern" file.txt
rg -E shift_jis "pattern" japanese_text.txt
rg -E euc-jp "pattern" legacy_file.txt

# Disable encoding detection (search raw bytes)
rg --no-encoding "pattern"
```

### 5.10 Sorted Output

```bash
# Sort results by file path (deterministic output)
rg --sort path "TODO"

# Sort by modification time (newest last)
rg --sort modified "TODO"

# Reverse sort (newest first)
rg --sortr modified "TODO"

# Sort options: path, modified, accessed, created
```

> [!NOTE]
> Sorting disables parallelism, which makes searches slower. Use it only when you need deterministic or ordered output.

### 5.11 Limit Search Depth and File Size

```bash
# Only search 2 levels deep
rg --max-depth 2 "pattern"

# Skip files larger than 1MB
rg --max-filesize 1M "pattern"

# Skip files larger than 500KB
rg --max-filesize 500K "pattern"
```

### 5.12 Follow Symlinks

```bash
# Follow symbolic links (off by default)
rg -L "pattern"
```

### 5.13 JSON Output for Scripting

```bash
# Machine-readable JSON Lines output
rg --json "pattern"
```

Each line is a JSON object with a `type` field. Five message types:

| Type | When | Key Fields |
|------|------|------------|
| `begin` | Start of a file | `path` |
| `match` | Each match | `path`, `lines`, `line_number`, `submatches` |
| `context` | Context lines | `path`, `lines`, `line_number` |
| `end` | End of a file | `path`, `stats` |
| `summary` | End of search | `elapsed_total`, `stats` |

Text data uses a `text` field for valid UTF-8, or a `bytes` field with base64 encoding for non-UTF-8 content.

```bash
# Pipe to jq for processing
rg --json "TODO" | jq 'select(.type == "match") | .data.lines.text'

# Extract just the matched text from each match
rg --json "TODO" | jq -r 'select(.type == "match") | .data.submatches[].match.text'
```

### 5.14 Preprocessor for Unsupported Formats

```bash
# Use a preprocessor to search PDFs
rg --pre "pdftotext {} -" "pattern" docs/

# Only apply preprocessor to PDF files
rg --pre "pdftotext {} -" --pre-glob "*.pdf" "pattern" docs/

# Search Word documents
rg --pre "catdoc" --pre-glob "*.doc" "pattern" documents/
```

### 5.15 Vim-Compatible Output

```bash
# One match per line, with column numbers (for :grep in Vim)
rg --vimgrep "pattern"
```

Expected output:

```text
src/main.rs:42:5:    // TODO: refactor this function
src/main.rs:42:18:   // TODO: refactor this function
```

Set in your `.vimrc`:

```vim
set grepprg=rg\ --vimgrep
set grepformat=%f:%l:%c:%m
```

---

## 6. Troubleshooting

### Exit Codes

| Code | Meaning |
|------|---------|
| `0` | At least one match found (or successful special operation like `--type-list`) |
| `1` | No matches found |
| `2` | An error occurred |

### Error: No matches found (exit code 1)

**Cause:** The pattern did not match any content in the searched files, or files were filtered out before searching.

**Solution:**

1. Verify your pattern is correct: `rg -F "exact string"` to avoid regex issues.
2. Check if files are being ignored: `rg --debug "pattern" 2>&1 | head -20` to see which files are skipped and why.
3. Try relaxing filters: `rg -uuu "pattern"` to search everything.
4. List files that would be searched: `rg --files | head` to confirm your target files are included.

### Error: regex parse error

**Cause:** The search pattern contains invalid regex syntax. Characters like `(`, `)`, `[`, `{`, `.`, `*`, `+`, `?`, `|`, `^`, `$`, `\` have special meaning in regex.

**Solution:**

```bash
# Use fixed-string mode to search for literal text
rg -F "function()" src/

# Or escape special characters
rg "function\(\)" src/
```

**Prevention:** When searching for code snippets that contain regex metacharacters, always use `-F` (fixed strings).

### Error: PCRE2 is not available

**Cause:** Your ripgrep binary was compiled without PCRE2 support, but you used `-P` or `--engine pcre2`.

**Solution:**

```bash
# Check if PCRE2 is available
rg --pcre2-version

# If not available, install a build with PCRE2:
cargo install ripgrep --features pcre2

# Or on macOS:
brew install ripgrep
```

### Error: binary file matches (hidden by default)

**Cause:** ripgrep detected binary content in a file and suppressed the output.

**Solution:**

```bash
# Show binary file matches as text
rg -a "pattern"

# Or explicitly enable binary searching
rg --binary "pattern"

# Or make ripgrep search everything
rg -uuu "pattern"
```

### Error: file not searched due to ignore rules

**Cause:** The file matches a pattern in `.gitignore`, `.ignore`, `.rgignore`, or a global ignore file.

**Solution:**

```bash
# See WHY a file is being ignored
rg --debug "pattern" 2>&1 | grep -i "ignore"

# Bypass all ignore rules
rg --no-ignore "pattern"

# Bypass only .gitignore
rg --no-ignore-vcs "pattern"

# Bypass only global gitignore
rg --no-ignore-global "pattern"
```

### Error: `$` treated as capture group in replacement with `--fixed-strings`

**Cause:** Even when using `-F/--fixed-strings` for the search pattern, the replacement string (`-r`) still interprets `$1`, `$2`, `${name}` as capture group references.

**Solution:**

```bash
# Escape dollar signs in the replacement
rg -F "search" -r "\$variable"
```

### Problem: Search is too slow

**Cause:** Several factors can slow ripgrep: sorted output, following symlinks into large trees, searching compressed files, or PCRE2 patterns.

**Solution:**

1. Remove `--sort` / `--sortr` if deterministic output is not required.
2. Check for symlink loops: avoid `-L` in directories with circular links.
3. Limit scope: use `-g`, `-t`, `--max-depth`, or `--max-filesize`.
4. Avoid `--pcre2` unless you need backreferences or lookaround.
5. Use `--stats` to see timing breakdown.

```bash
rg --stats "pattern" src/
```

### Problem: Matches not highlighted in piped output

**Cause:** ripgrep automatically disables colors when stdout is not a terminal (a pipe or redirect).

**Solution:**

```bash
# Force colors even when piping
rg --color always "pattern" | less -R

# Use --pretty for heading + line numbers + color
rg -p "pattern" | less -R
```

### Problem: Config file not loading

**Cause:** The `RIPGREP_CONFIG_PATH` environment variable is not set, or points to a non-existent file.

**Solution:**

```bash
# Verify the variable is set
echo $RIPGREP_CONFIG_PATH

# Verify the file exists
cat "$RIPGREP_CONFIG_PATH"

# Test with debug output
rg --debug "test" 2>&1 | grep -i "config"
```

**Prevention:** Add the export to your shell profile (`~/.bashrc`, `~/.zshrc`, `$PROFILE` for PowerShell).

### Problem: Different results on different machines

**Cause:** Different ignore files, config files, or ripgrep versions across machines.

**Solution:**

```bash
# Compare versions
rg --version

# Run without any config
rg --no-config "pattern"

# Run with no ignore rules and hidden files
rg -uuu "pattern"

# Show debug info to see what's being loaded
rg --debug "pattern" 2>&1 | head -30
```

### Problem: Searching in non-git directories skips files unexpectedly

**Cause:** By default, ripgrep looks for a `.git` directory to determine the repository root for ignore processing. Without one, certain ignore behaviors may not work as expected.

**Solution:**

```bash
# Allow searching without a git repository
rg --no-require-git "pattern"
```

### Problem: Windows path separators in output

**Cause:** ripgrep uses the OS-native path separator by default.

**Solution:**

```bash
# Force forward slashes on Windows
rg --path-separator / "pattern"
```

### Problem: Multiline matches with PCRE2 and JSON output produce unexpected results

**Cause:** When combining `--multiline`, `--pcre2`, and `--json`, certain edge cases in line boundary detection can produce unexpected output formatting.

**Solution:**

```bash
# Use the default regex engine for multiline JSON output when possible
rg -U --json "pattern"

# If you must use PCRE2, verify output with a small test first
rg -P -U --json "pattern" test_file.txt
```

### Problem: Error messages cluttering output

**Cause:** Permission errors, broken symlinks, or unreadable files produce warnings on stderr.

**Solution:**

```bash
# Suppress all error messages
rg --no-messages "pattern"

# Suppress only ignore-file parse errors
rg --no-ignore-messages "pattern"

# Redirect stderr to separate from results
rg "pattern" 2>/dev/null
```

> [!CAUTION]
> When using `--debug` or `--trace` for troubleshooting, be aware that these flags produce verbose output on stderr. Redirect stderr to a file for easier analysis: `rg --debug "pattern" 2>debug.log`.

---

## 7. FAQ

**Q: How is ripgrep different from grep?**

ripgrep is faster than GNU grep in most scenarios because it uses parallelism, memory-mapped I/O, and the Rust regex engine. It also automatically skips binary files, respects `.gitignore`, and uses smart defaults (recursive search, colored output on terminals). Unlike grep, ripgrep does not support the BRE (basic regular expression) syntax — it always uses a modern regex syntax similar to Perl and RE2.

---

**Q: Can ripgrep replace files in-place like sed?**

No. The `--replace` flag only changes what is printed to stdout. ripgrep is a search tool, not an editing tool. To modify files, pipe ripgrep output into `sed`, `awk`, or use your editor's search-and-replace. For example:

```bash
# Preview replacements
rg "old_name" -r "new_name"

# Apply with sed (GNU sed)
rg -l "old_name" | xargs sed -i 's/old_name/new_name/g'
```

---

**Q: How do I search for a pattern that starts with a dash?**

Use `--` to signal the end of flags, or use `-e`:

```bash
rg -- "-TODO"
rg -e "-TODO"
```

---

**Q: Can I search only filenames, not contents?**

Use `rg --files` combined with a pipe to filter:

```bash
# Find files with "test" in their name
rg --files | rg "test"

# Using globs
rg --files -g "*test*"
```

---

**Q: How do I match across multiple lines?**

Use the `-U` (multiline) flag:

```bash
# Match a struct definition spanning multiple lines
rg -U "struct \w+ \{[^}]*\}"

# Use --multiline-dotall to make . match newlines
rg -U --multiline-dotall "BEGIN.*?END"
```

---

**Q: Why does ripgrep skip my `.env` file?**

`.env` is a hidden file (starts with `.`). By default ripgrep skips hidden files. Additionally, `.env` is commonly listed in `.gitignore`. Use `--hidden` and/or `--no-ignore` to include it:

```bash
rg --hidden --no-ignore "API_KEY" .env
```

---

**Q: How do I use ripgrep with `xargs` or `find`?**

Use `-0/--null` to NUL-terminate filenames for safe piping:

```bash
# Search specific files found by find
find . -name "*.log" -print0 | xargs -0 rg "ERROR"

# Use ripgrep's own file listing with NUL separation
rg --files -0 -g "*.py" | xargs -0 rg "import os"
```

---

**Q: Can I make ripgrep ignore certain directories permanently?**

Yes. Add patterns to any of the supported ignore files:

```bash
# Project-specific: create .rgignore in the project root
echo "vendor/" >> .rgignore
echo "node_modules/" >> .rgignore
echo "*.min.js" >> .rgignore

# Or use .ignore (also respected by fd and other tools)
echo "build/" >> .ignore
```

---

**Q: How do I get ripgrep to show only the matched text, not the whole line?**

Use `-o` (only-matching):

```bash
rg -o "\d+\.\d+\.\d+" Cargo.toml
```

Output:

```text
0.15.1
1.2.3
```

---

**Q: What is the `--stop-on-nonmatch` flag for?**

It tells ripgrep to stop searching a file after the first non-matching line is encountered (when using context flags). This is useful for structured files like logs where matches are expected to be contiguous at the beginning or end of the file.

---

**Q: Does ripgrep support lookahead and lookbehind?**

Not with the default regex engine. Use `-P` (PCRE2) for these features:

```bash
# Lookbehind: find words after "version: "
rg -P "(?<=version: )\S+"

# Lookahead: find "import" followed by "React"
rg -P "import(?=.*React)"

# Negative lookahead: "error" not followed by "handling"
rg -P "error(?!.*handling)"
```

---

**Q: How do I add hyperlinks to matches in my terminal?**

If your terminal supports OSC 8 hyperlinks:

```bash
# Enable file:// hyperlinks
rg --hyperlink-format default "pattern"

# Use grep+ format for click-to-line support
rg --hyperlink-format "grep+" "pattern"
```

---

**Q: Can I limit the number of matches shown?**

Yes, use `-m/--max-count`:

```bash
# Show at most 5 matches per file
rg -m 5 "TODO"

# Show at most 1 match per file (first match only)
rg -m 1 "TODO"
```

---

**Q: How do I customize colors?**

Use `--colors` with the format `{type}:{attribute}:{value}`:

```bash
# Red matches on yellow background
rg --colors "match:fg:red" --colors "match:bg:yellow" "pattern"

# Bold green filenames
rg --colors "path:fg:green" --colors "path:style:bold" "pattern"

# Types: path, line, column, match, highlight
# Attributes: fg, bg, style
# Colors: red, green, blue, yellow, magenta, cyan, white, black
# Styles: bold, nobold, intense, nointense, underline, nounderline
```

Add these to your config file for persistent styling.

---

**Q: How do I search stdin instead of files?**

When no file path is given and stdin is not a terminal, ripgrep reads from stdin:

```bash
# Pipe data to ripgrep
cat server.log | rg "ERROR"

# Combine with other commands
docker logs mycontainer 2>&1 | rg "timeout"
```

---

**Q: What does the `--crlf` flag do?**

It tells ripgrep to treat `\r\n` (Windows-style line endings) as line terminators. This affects how `$` anchors work in patterns — with `--crlf`, the `$` matches before the `\r\n` rather than between `\r` and `\n`.

```bash
rg --crlf "pattern$" windows_file.txt
```

---

**Q: How do I prevent ripgrep from crossing filesystem boundaries?**

Use the `--one-file-system` flag to stay on the same filesystem when recursing:

```bash
rg --one-file-system "pattern" /
```

This is useful on Linux when you want to avoid searching into mounted filesystems like `/proc`, `/sys`, or network mounts.

---

> [!IMPORTANT]
> For architecture details, configuration deep-dives, performance tuning, regex engine internals, and crate-level API documentation, see the [Admin Guide](/BurntSushi/ripgrep/admin-guide/).

---

## Quick Reference Card

### Most-Used Flags

| Flag | Purpose |
|------|---------|
| `-i` | Case insensitive |
| `-S` | Smart case |
| `-F` | Fixed strings (no regex) |
| `-w` | Whole word match |
| `-v` | Invert match |
| `-c` | Count matches per file |
| `-l` | List matching files only |
| `-o` | Print only matched text |
| `-n` | Show line numbers |
| `-C NUM` | Context lines (before + after) |
| `-A NUM` | Lines after match |
| `-B NUM` | Lines before match |
| `-t TYPE` | Only search file type |
| `-T TYPE` | Exclude file type |
| `-g GLOB` | Include/exclude by glob |
| `-r REPL` | Replace match in output |
| `-z` | Search compressed files |
| `-U` | Multiline matching |
| `-P` | PCRE2 regex engine |
| `-p` | Pretty output (color + heading + line numbers) |
| `-u` | Unrestricted (cumulative) |
| `-m NUM` | Max matches per file |
| `-M NUM` | Max columns per line |
| `--hidden` | Include hidden files |
| `--no-ignore` | Skip ignore rules |
| `--sort path` | Deterministic sorted output |
| `--json` | JSON Lines output |
| `--stats` | Print search statistics |
| `--debug` | Debug output on stderr |

### Cheat Sheet

```bash
# Find all TODO/FIXME/HACK comments
rg -e "TODO" -e "FIXME" -e "HACK"

# Find function definitions with context
rg -t rust "fn \w+\(" -A 2

# Find files containing "password" (hidden + ignored files too)
rg -uu -l "password"

# Count files per file type that would be searched
rg --files -t py | wc -l

# Search gzipped logs for errors
rg -z "ERROR" /var/log/app/*.gz

# Preview a rename refactor
rg "OldClassName" -r "NewClassName"

# Get match statistics
rg --stats "pattern" src/ 2>&1 | tail -6

# JSON output piped to jq — extract matching filenames
rg --json "TODO" | jq -r 'select(.type == "begin") | .data.path.text'

# Find lines NOT containing a pattern
rg -v "^(#|$)" config.ini

# Search with byte offset (for binary analysis)
rg -b "magic_bytes"

# Trim leading whitespace from output
rg --trim "pattern"

# NUL-separated output for safe scripting
rg -l -0 "pattern" | xargs -0 wc -l
```

---

_Generated May 2026 from BurntSushi/ripgrep at 4519153. AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it. Unofficial; not affiliated with or reviewed by the project._
