BurntSushi / ripgrep
ripgrep makes repository search feel like a native operation
BurntSushi's search tool combines recursive traversal, sensible ignore behavior, Unicode-aware regular expressions, file type filters, and scriptable output in one focused command. Its value is not just speed. The defaults match how developers usually want a repository search to behave.
WHAT TO KNOW FIRST
- ripgrep searches recursively while respecting ignore files and skipping hidden and binary files by default, which is useful but can conceal material you intended to inspect.
- Its regular expression engine favors predictable linear-time searching and Unicode support; PCRE2 is an optional path for features such as look-around and backreferences.
- The command is excellent for discovery and pipelines, but it is not a portable POSIX primitive, a semantic code index, or an in-place replacement engine.
01A command whose defaults understand a repository
Many search commands can scan text. ripgrep earns its place by deciding what a source-tree search probably means before the user supplies a page of flags. Invoking rg with a pattern recursively walks the current directory, honors version-control ignore rules, and avoids hidden paths and files it considers binary. That starting behavior suits the common question, where does this symbol, message, route, or configuration key appear in code that belongs to the project?
Those defaults also explain why the tool can feel more precise than a raw recursive grep even before performance enters the discussion. Generated dependencies, build output, and other ignored material usually do not belong in a first-pass answer. The result set is smaller because traversal policy and text matching are designed together. A developer can then add line numbers, context, headings, file names, or machine-oriented output without rebuilding the traversal logic in a shell pipeline.
02The traversal policy is part of the result
A search result is only meaningful if you know which files were eligible. ripgrep reads ignore rules from sources documented by the project, including .gitignore, .ignore, and .rgignore, and it normally excludes hidden paths and binary files. The user guide carefully separates these controls because each answers a different question. A hidden file is not necessarily ignored, and an ignored path is not necessarily hidden. Treating them as one switch makes audits unreliable.
The escalation flags are intentionally visible. Adding --hidden includes hidden paths while retaining ignore behavior. Adding --no-ignore turns off ignore rules. The compact -uuu form disables several automatic filters and is useful when the question is truly search everything, but it can dramatically expand the work and the noise. For a security review, migration, or cleanup, record the inclusion flags beside the result so another person can reproduce the search boundary.
03Regular expressions without accidental complexity
ripgrep is built on Rust's regex ecosystem and uses a default engine designed around finite automata, Unicode-aware matching, and strong worst-case behavior. That choice covers ordinary literals, alternation, repetition, character classes, boundaries, and captures without exposing every construct found in backtracking engines. It is a practical trade: repository searches stay responsive, while patterns that depend on look-around or backreferences require a different engine rather than silently changing complexity.
The optional PCRE2 path is selected with -P or --pcre2 when the installed build supports it. That is a deliberate opt-in, not a reason to make every search more elaborate. A literal or simple structural expression is easier to review in scripts and issue reports. Before assuming a pattern is wrong, use fixed-string mode for punctuation-heavy text, inspect escaping in the current shell, and remember that multiline matching changes what a match can span and how much input the engine must consider.
04File types and globs keep questions honest
Large repositories often reuse the same word across documentation, generated fixtures, source code, lockfiles, and vendored assets. ripgrep's file type filters turn that mixed corpus into a stated scope. The -t flag includes a known type, while -T excludes one. The type definitions can group several extensions and file-name conventions, and the command can report or extend those definitions. Globs provide a more direct include or exclude rule when a project has local conventions.
This is more than convenience. A result reported as every use of an API can be false if it actually searched only TypeScript files, while a result polluted by snapshots can obscure the calls that matter. Put the scope in the command: rg -g patterns, type filters, and target paths are reviewable evidence. When a custom type becomes team practice, define it consistently and document the configuration rather than relying on one person's shell history.
05Readable at a terminal, disciplined in a pipeline
Interactive output can include color, headings, line and column information, surrounding context, and hyperlinks supported by compatible terminals or editors. The same binary also supports formats that are easier to consume mechanically. File-only output, counts, null-delimited paths, JSON lines, and controlled color behavior let scripts avoid scraping a decorated terminal view. The key is to select an explicit contract instead of assuming that whatever looks good on screen is stable input for another command.
Exit status matters in automation. A successful search with no matches is different from a search error, and shell scripts should preserve that distinction. File names may contain spaces or newlines, so line-delimited path handling is not always safe. Use the documented null-oriented options when handing paths to another process. If the job is to list candidate files rather than matching lines, rg --files applies the same traversal logic without inventing a pattern that matches everything.
06Power does not turn search into code intelligence
ripgrep can find textual definitions, imports, call sites, error strings, configuration keys, and syntax patterns across mixed languages. It cannot decide that two identifiers with the same spelling refer to different symbols, follow a renamed method through a type system, or prove that a match is reachable. Language servers and indexed code search answer semantic questions. rg remains valuable beside them because raw text is universal and often exposes templates, generated code, scripts, or documentation outside a semantic index.
It also does not edit files in place. Replacement syntax can transform displayed output, which is useful for previewing captures, but a migration needs a separate editing step and verification. Compressed-file searching and preprocessors are available through documented options, yet they expand the trust and performance boundary by executing or invoking other programs. Keep a simple text search simple, and introduce preprocessors only when the file format makes the extra machinery necessary.
07Configuration should remain visible
ripgrep can load default arguments from a configuration file identified through RIPGREP_CONFIG_PATH. This is useful for a preferred color scheme, context style, or custom type, but it can make copied commands behave differently on another machine. Repository instructions and CI jobs should therefore use explicit flags for behavior that affects correctness. Personal display preferences belong in a personal configuration; inclusion rules and output contracts belong in the command or a versioned wrapper.
Cross-platform support is a genuine strength. The project publishes release binaries and documents package-manager routes for Windows, macOS, Linux, and other systems. It is still not ubiquitous in the way a basic grep may be on a Unix host, and the README explicitly notes that ripgrep is not a POSIX-standard tool. A deployment script for unknown recovery environments should not assume rg exists. A development environment can reasonably pin and provision it.
08How to decide whether it belongs in your toolchain
Evaluate ripgrep with your repository's real exclusions and worst folders, not a synthetic speed headline. Check whether developers can explain why a hidden, ignored, binary, encoded, or compressed file did or did not appear. Try literal searches, Unicode text, common regexes, file-type filters, JSON output, and commands that intentionally produce no matches. The goal is confidence in scope and output before speed becomes a benefit.
For most development work, that evaluation is short because the project keeps one job at the center. Install it, learn the automatic filters, and make scopes explicit when reporting a result. Retain grep where portability requires it, retain semantic tools where symbol resolution matters, and use rg as the fast textual layer between them. Its best quality is not that it replaces every search program. It is that routine repository questions become concise enough to ask correctly.
A SENSIBLE FIRST HOUR
Start small enough to learn the repo
- Install an official package or release binary, then run rg --version so you know which build and optional features are present.
- From a repository root, run rg -n 'pattern' and compare the result with rg -n --hidden 'pattern' to see how hidden paths affect discovery.
- Narrow a real search with a file type or glob, such as rg -tpy 'class ' or rg -g '*.tsx' 'useEffect', instead of filtering a broad result later.
- Read rg --help and the official user guide before creating aliases, a configuration file, or automation that changes ignore and binary-file behavior.
SOURCE LEDGER
What this review is built on
We use the project repository and first-party documentation. Access, licenses and project direction can change, so recheck the linked source before making a production decision.