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 fooequalsrg foo ./), - respects
.gitignore,.ignore, and.rgignorerules (precedence:.rgignoreover.ignoreover.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
-Ffor literals. - Dry-run the file set with
--filesplus your-g/-tfilters 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.--iglobis the case-insensitive form. Glob patterns use/separators on every platform, including Windows. - Types:
-t pyincludes a type,-T jsexcludes one;--type-listshows 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 1Mskips large files;--max-depth NUMcaps 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/--pcre2switches to PCRE2, which supports lookaround and backrefs but can backtrack catastrophically. It requires a build with+PCRE2inrg --version; otherwise rg reports PCRE2 is not available.--engine autouses the default engine and falls back to PCRE2 only when the pattern needs it.-Ftreats the pattern as a literal string;-wrequires word boundaries;-xrequires the pattern to match the whole line;-e PATor--safely pass patterns that start with-.- Case:
-iinsensitive,-ssensitive,-Ssmart-case (insensitive unless the pattern contains an uppercase letter). - Multiline:
-Ulets a match span lines; add--multiline-dotallwhen.must match newlines. A bare\nin 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. -oprints only the matched text;-r REPLrewrites the match in the output, supporting$1,$0, and named groups. See Hard Constraints.- Machine-readable:
--jsonemits JSON Lines with byte offsets and submatches;--vimgrepprintsfile:line:column:textwith one match per line;--columnadds column numbers. - Lists and counts:
-lprints files with matches,--files-without-matchthe inverse;-ccounts matched lines per file — use--count-matchesfor total matches;--statsappends 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 pathgives stable order but disables parallelism;-j1is 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. Userg "^foo". Escape a literal%as%%. - PowerShell: prefer single quotes for regexes;
$inside double quotes triggers variable expansion, sorg "foo$"breaks whilerg '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) orMSYS_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-16lewhen there is no BOM.
Hard Constraints
-r/--replacerewrites rg's OUTPUT only. ripgrep never modifies files and has no in-place edit flag. For real edits use the sanctioned pipelinerg 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/--pcre2after checkingrg --versionfor+PCRE2, or restate the pattern without those features.
Debugging Checklist
Zero matches:
- Verify the binary:
rg --versionandwhich 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
-Fliteral, 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
-Eexplicitly.
Too many matches:
- Scope with a path argument,
-g, or-t. - Add
-wfor word boundaries or-xfor whole-line matches. - Use
-swhen smart-case or-iover-matches. - Cap with
-m NUMmatching 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.