ripgrep Text Search
Use ripgrep (rg) when the user needs fast text or regex content search from
the command line. The useful outcome is a copy-pasteable command plus a clear
statement of what it matches, what it skips, and why.
Triage
Start with the smallest tool that can answer the question.
- For trivial in-conversation lookups, use the harness's built-in
ripgrep-backed search tool instead of shelling out to rg.
- Use rg for exact names, strings, regex content searches, file lists, counts,
and pipeline-friendly output.
- Use ast-grep for syntax shape: descendants, ancestors, call forms,
decorators, missing constructs, or nested contexts.
- Use language tooling for semantic facts such as type resolution, references,
imports, or rename safety.
Before trusting local behavior, verify the binary: rg --version should print
a ripgrep version plus enabled features such as +PCRE2. If it does not, run
which rg — an alias or another tool named rg may shadow it.
Defaults Model
rg is a filter wrapped around a search. By default it:
- searches the current directory recursively (
rg foo equals rg foo ./),
- respects
.gitignore, .ignore, and .rgignore rules (precedence:
.rgignore over .ignore over .gitignore),
- skips hidden files and directories,
- skips binary files (any file containing a NUL byte),
- does not follow symlinks (opt in with
-L/--follow).
Escalation ladder: -u disables ignore-file handling, -uu also searches
hidden files, -uuu also searches binary files — roughly grep -r with no
smart filtering. Individual toggles: --no-ignore, --hidden, -a/--text.
When rg "can't find" a file, diagnose before changing the pattern:
rg --files | rg name — is the file in the searched set at all?
rg pattern --debug — which ignore rule or config excluded it? A * rule
in the global gitignore is the most common cause.
rg pattern -uuu — does the match appear with all filtering off?
Workflow
- Compose the simplest command that could work; prefer
-F for literals.
- Dry-run the file set with
--files plus your -g/-t filters when the
search scope matters.
- Run on a narrow path first (
rg pattern src/module), then widen.
- For complex or shell-hostile patterns, write one pattern per line to a
file and use
-f patterns.txt (patterns are ORed). On Windows this is the
preferred escape hatch from quoting problems; save the file as UTF-8
without BOM.
- Report the command, what it matches, and what it may miss.
Filtering
- Paths:
rg foo src tests README.md. Explicitly named files bypass ignore
rules and hidden-file skipping.
- Globs:
-g '*.toml' includes; -g '!*.toml' excludes — on the command
line ! negates, the reverse of gitignore whitelist semantics. Later globs
override earlier ones. Quote globs so the shell does not expand them.
--iglob is the case-insensitive form. Glob patterns use / separators on
every platform, including Windows.
- Types:
-t py includes a type, -T js excludes one; --type-list shows
the globs behind each type. --type-add 'web:*.{html,css,js}' defines a
type for the current invocation only; persist it in the config file.
- Limits:
--max-filesize 1M skips large files; --max-depth NUM caps
traversal depth.
Regex Engines
- The default engine (Rust regex) guarantees worst-case linear time but has
no lookaround and no backreferences — such patterns fail at compile time
with a parse error.
-P/--pcre2 switches to PCRE2, which supports lookaround and backrefs but
can backtrack catastrophically. It requires a build with +PCRE2 in
rg --version; otherwise rg reports PCRE2 is not available.
--engine auto uses the default engine and falls back to PCRE2 only when
the pattern needs it.
-F treats the pattern as a literal string; -w requires word boundaries;
-x requires the pattern to match the whole line; -e PAT or -- safely
pass patterns that start with -.
- Case:
-i insensitive, -s sensitive, -S smart-case (insensitive unless
the pattern contains an uppercase letter).
- Multiline:
-U lets a match span lines; add --multiline-dotall when .
must match newlines. A bare \n in a pattern errors without -U.
- Unicode is on by default; disable it for a sub-pattern with
(?-u:...).
Output & Pipelines
- Context:
-A NUM, -B NUM, -C NUM.
-o prints only the matched text; -r REPL rewrites the match in the
output, supporting $1, $0, and named groups. See Hard Constraints.
- Machine-readable:
--json emits JSON Lines with byte offsets and
submatches; --vimgrep prints file:line:column:text with one match per
line; --column adds column numbers.
- Lists and counts:
-l prints files with matches, --files-without-match
the inverse; -c counts matched lines per file — use --count-matches for
total matches; --stats appends aggregate totals.
- Piping changes defaults: at a TTY rg shows colors, line numbers, and
headings; when piped it drops them. Force with
--color=always, -n, or
--heading.
- Output order is non-deterministic because rg searches in parallel.
--sort path gives stable order but disables parallelism; -j1 is a
cheaper determinism knob.
Windows Quoting
- cmd.exe: only double quotes delimit strings; single quotes are literal
characters, so
rg '^foo' searches for a pattern containing quotes. Use
rg "^foo". Escape a literal % as %%.
- PowerShell: prefer single quotes for regexes;
$ inside double quotes
triggers variable expansion, so rg "foo$" breaks while rg 'foo$' works.
- Git Bash / MSYS2: POSIX single quotes work, but a pattern or argument
starting with
/ may be silently rewritten by path translation. Fix with a
doubled slash (rg //foo) or MSYS_NO_PATHCONV=1 rg /foo.
- Escape hatch for any shell: put the pattern in a file and use
-f file,
saved as UTF-8 without BOM.
- UTF-16 files (common on Windows) are transcoded automatically via BOM
sniffing; force an encoding with
-E utf-16le when there is no BOM.
Hard Constraints
-r/--replace rewrites rg's OUTPUT only. ripgrep never modifies files and
has no in-place edit flag. For real edits use the sanctioned pipeline
rg foo -l -0 | xargs -0 sed -i 's/foo/bar/g' (BSD/macOS sed needs
-i ''), or a purpose-built tool such as fastmod.
- Zero matches usually means default filtering, not a bad regex. Walk the
Defaults Model diagnosis (
--files, --debug, -uuu) before rewriting
the pattern.
- Lookaround or backreferences on the default engine fail at compile time.
Route to
-P/--pcre2 after checking rg --version for +PCRE2, or
restate the pattern without those features.
Debugging Checklist
Zero matches:
- Verify the binary:
rg --version and which rg.
rg --files | rg name — is the target file searched at all?
- Add
--debug — which ignore rule or config file excluded it?
- Try
-uuu — do matches appear with all filtering disabled?
- Simplify: drop to a
-F literal, then add regex features back.
- On Windows, suspect shell quoting; move the pattern to
-f file.
- For non-UTF-8 files without a BOM, set
-E explicitly.
Too many matches:
- Scope with a path argument,
-g, or -t.
- Add
-w for word boundaries or -x for whole-line matches.
- Use
-s when smart-case or -i over-matches.
- Cap with
-m NUM matching lines per file.
Output Contract
When answering an rg task, include:
Command: copy-pasteable, naming the target shell when quoting matters.
Why these flags: one line per non-obvious flag.
What it matches / misses: the filtering and engine boundaries in effect.
Caveats: ignore-file surprises, output ordering, encoding, or version
gates (this skill documents ripgrep 15.1.0 behavior).
Reference
Load references/cli_reference.md when the task needs detailed flag
semantics, the engine comparison, config-file format, preprocessors and
compressed search, encodings, or JSON output details.
1---2name: ripgrep3description: Use when the user needs text or regex content search with ripgrep: composing rg commands, choosing flags, glob/type filtering, multiline or PCRE2 searches, pipeline output, grep-to-rg migration, or diagnosing why rg missed a file (gitignore, hidden, binary defaults). Not for syntax-aware structural queries (ast-grep) or semantic renames/references (language tooling).4---56# ripgrep Text Search78Use ripgrep (rg) when the user needs fast text or regex content search from9the command line. The useful outcome is a copy-pasteable command plus a clear10statement of what it matches, what it skips, and why.1112## Triage1314Start with the smallest tool that can answer the question.1516- For trivial in-conversation lookups, use the harness's built-in17 ripgrep-backed search tool instead of shelling out to rg.18- Use rg for exact names, strings, regex content searches, file lists, counts,19 and pipeline-friendly output.20- Use ast-grep for syntax shape: descendants, ancestors, call forms,21 decorators, missing constructs, or nested contexts.22- Use language tooling for semantic facts such as type resolution, references,23 imports, or rename safety.2425Before trusting local behavior, verify the binary: `rg --version` should print26a ripgrep version plus enabled features such as `+PCRE2`. If it does not, run27`which rg` — an alias or another tool named rg may shadow it.2829## Defaults Model3031rg is a filter wrapped around a search. By default it:3233- searches the current directory recursively (`rg foo` equals `rg foo ./`),34- respects `.gitignore`, `.ignore`, and `.rgignore` rules (precedence:35 `.rgignore` over `.ignore` over `.gitignore`),36- skips hidden files and directories,37- skips binary files (any file containing a NUL byte),38- does not follow symlinks (opt in with `-L/--follow`).3940Escalation ladder: `-u` disables ignore-file handling, `-uu` also searches41hidden files, `-uuu` also searches binary files — roughly `grep -r` with no42smart filtering. Individual toggles: `--no-ignore`, `--hidden`, `-a/--text`.4344When rg "can't find" a file, diagnose before changing the pattern:45461. `rg --files | rg name` — is the file in the searched set at all?472. `rg pattern --debug` — which ignore rule or config excluded it? A `*` rule48 in the global gitignore is the most common cause.493. `rg pattern -uuu` — does the match appear with all filtering off?5051## Workflow52531. Compose the simplest command that could work; prefer `-F` for literals.542. Dry-run the file set with `--files` plus your `-g`/`-t` filters when the55 search scope matters.563. Run on a narrow path first (`rg pattern src/module`), then widen.574. For complex or shell-hostile patterns, write one pattern per line to a58 file and use `-f patterns.txt` (patterns are ORed). On Windows this is the59 preferred escape hatch from quoting problems; save the file as UTF-860 without BOM.615. Report the command, what it matches, and what it may miss.6263## Filtering6465- Paths: `rg foo src tests README.md`. Explicitly named files bypass ignore66 rules and hidden-file skipping.67- Globs: `-g '*.toml'` includes; `-g '!*.toml'` excludes — on the command68 line `!` negates, the reverse of gitignore whitelist semantics. Later globs69 override earlier ones. Quote globs so the shell does not expand them.70 `--iglob` is the case-insensitive form. Glob patterns use `/` separators on71 every platform, including Windows.72- Types: `-t py` includes a type, `-T js` excludes one; `--type-list` shows73 the globs behind each type. `--type-add 'web:*.{html,css,js}'` defines a74 type for the current invocation only; persist it in the config file.75- Limits: `--max-filesize 1M` skips large files; `--max-depth NUM` caps76 traversal depth.7778## Regex Engines7980- The default engine (Rust regex) guarantees worst-case linear time but has81 no lookaround and no backreferences — such patterns fail at compile time82 with a parse error.83- `-P/--pcre2` switches to PCRE2, which supports lookaround and backrefs but84 can backtrack catastrophically. It requires a build with `+PCRE2` in85 `rg --version`; otherwise rg reports PCRE2 is not available.86- `--engine auto` uses the default engine and falls back to PCRE2 only when87 the pattern needs it.88- `-F` treats the pattern as a literal string; `-w` requires word boundaries;89 `-x` requires the pattern to match the whole line; `-e PAT` or `--` safely90 pass patterns that start with `-`.91- Case: `-i` insensitive, `-s` sensitive, `-S` smart-case (insensitive unless92 the pattern contains an uppercase letter).93- Multiline: `-U` lets a match span lines; add `--multiline-dotall` when `.`94 must match newlines. A bare `\n` in a pattern errors without `-U`.95- Unicode is on by default; disable it for a sub-pattern with `(?-u:...)`.9697## Output & Pipelines9899- Context: `-A NUM`, `-B NUM`, `-C NUM`.100- `-o` prints only the matched text; `-r REPL` rewrites the match in the101 output, supporting `$1`, `$0`, and named groups. See Hard Constraints.102- Machine-readable: `--json` emits JSON Lines with byte offsets and103 submatches; `--vimgrep` prints `file:line:column:text` with one match per104 line; `--column` adds column numbers.105- Lists and counts: `-l` prints files with matches, `--files-without-match`106 the inverse; `-c` counts matched lines per file — use `--count-matches` for107 total matches; `--stats` appends aggregate totals.108- Piping changes defaults: at a TTY rg shows colors, line numbers, and109 headings; when piped it drops them. Force with `--color=always`, `-n`, or110 `--heading`.111- Output order is non-deterministic because rg searches in parallel.112 `--sort path` gives stable order but disables parallelism; `-j1` is a113 cheaper determinism knob.114115## Windows Quoting116117- cmd.exe: only double quotes delimit strings; single quotes are literal118 characters, so `rg '^foo'` searches for a pattern containing quotes. Use119 `rg "^foo"`. Escape a literal `%` as `%%`.120- PowerShell: prefer single quotes for regexes; `$` inside double quotes121 triggers variable expansion, so `rg "foo$"` breaks while `rg 'foo$'` works.122- Git Bash / MSYS2: POSIX single quotes work, but a pattern or argument123 starting with `/` may be silently rewritten by path translation. Fix with a124 doubled slash (`rg //foo`) or `MSYS_NO_PATHCONV=1 rg /foo`.125- Escape hatch for any shell: put the pattern in a file and use `-f file`,126 saved as UTF-8 without BOM.127- UTF-16 files (common on Windows) are transcoded automatically via BOM128 sniffing; force an encoding with `-E utf-16le` when there is no BOM.129130## Hard Constraints1311321. `-r/--replace` rewrites rg's OUTPUT only. ripgrep never modifies files and133 has no in-place edit flag. For real edits use the sanctioned pipeline134 `rg foo -l -0 | xargs -0 sed -i 's/foo/bar/g'` (BSD/macOS sed needs135 `-i ''`), or a purpose-built tool such as fastmod.1362. Zero matches usually means default filtering, not a bad regex. Walk the137 Defaults Model diagnosis (`--files`, `--debug`, `-uuu`) before rewriting138 the pattern.1393. Lookaround or backreferences on the default engine fail at compile time.140 Route to `-P/--pcre2` after checking `rg --version` for `+PCRE2`, or141 restate the pattern without those features.142143## Debugging Checklist144145Zero matches:1461471. Verify the binary: `rg --version` and `which rg`.1482. `rg --files | rg name` — is the target file searched at all?1493. Add `--debug` — which ignore rule or config file excluded it?1504. Try `-uuu` — do matches appear with all filtering disabled?1515. Simplify: drop to a `-F` literal, then add regex features back.1526. On Windows, suspect shell quoting; move the pattern to `-f file`.1537. For non-UTF-8 files without a BOM, set `-E` explicitly.154155Too many matches:1561571. Scope with a path argument, `-g`, or `-t`.1582. Add `-w` for word boundaries or `-x` for whole-line matches.1593. Use `-s` when smart-case or `-i` over-matches.1604. Cap with `-m NUM` matching lines per file.161162## Output Contract163164When answering an rg task, include:1651661. `Command`: copy-pasteable, naming the target shell when quoting matters.1672. `Why these flags`: one line per non-obvious flag.1683. `What it matches / misses`: the filtering and engine boundaries in effect.1694. `Caveats`: ignore-file surprises, output ordering, encoding, or version170 gates (this skill documents ripgrep 15.1.0 behavior).171172## Reference173174Load `references/cli_reference.md` when the task needs detailed flag175semantics, the engine comparison, config-file format, preprocessors and176compressed search, encodings, or JSON output details.