# ripgrep — Administrator & Developer Guide

ripgrep (`rg`) is a line-oriented search tool that recursively searches directories for regex patterns while respecting ignore files. Written in Rust by Andrew Gallant, it combines the usability of `grep -r` with the speed of a purpose-built search engine. This guide covers architecture, configuration, deployment, performance tuning, security considerations, and developer internals for administrators, packagers, and contributors.

> **Version covered:** ripgrep 15.1.0 | **License:** MIT OR Unlicense (dual) | **MSRV:** Rust 1.85.0 | **Edition:** 2024

For everyday usage, flag examples, and workflow recipes, see the [User Guide](/BurntSushi/ripgrep/user-guide/).

---

## 1. Architecture Overview

### 1.1 Workspace Structure

ripgrep is a Rust workspace containing one binary crate and eight library crates. Each library crate is independently versioned and publishable to crates.io.

```
ripgrep (binary)                    crates/core/     v15.1.0
├── grep (facade)                   crates/grep/     v0.4.1
│   ├── grep-cli                    crates/cli/      v0.1.12
│   ├── grep-matcher                crates/matcher/  v0.1.8
│   ├── grep-regex                  crates/regex/    v0.1.14
│   ├── grep-pcre2                  crates/pcre2/    v0.1.9
│   ├── grep-searcher               crates/searcher/ v0.1.16
│   └── grep-printer                crates/printer/  v0.3.1
├── globset                         crates/globset/  v0.4.18
└── ignore                          crates/ignore/   v0.4.25
```

| Crate | Role | Key Types |
|---|---|---|
| `ripgrep` (binary) | CLI entry point, flag parsing, search orchestration | `HiArgs`, `LowArgs`, `SearchWorker`, `Printer`, `PatternMatcher` |
| `grep` | Facade that re-exports all `grep-*` crates | -- |
| `grep-cli` | CLI utilities: decompression, escaping, pattern I/O, TTY detection | `DecompressionReader`, `CommandReader`, `StandardStream` |
| `grep-matcher` | Abstract `Matcher` trait and supporting types | `Match`, `LineTerminator`, `ByteSet`, `Matcher` trait |
| `grep-regex` | Rust `regex` engine adapter implementing `Matcher` | `RegexMatcher`, `RegexMatcherBuilder` |
| `grep-pcre2` | PCRE2 engine adapter implementing `Matcher` (optional) | `RegexMatcher`, `RegexMatcherBuilder` |
| `grep-searcher` | Core search engine: reads files/streams, invokes matcher, reports via `Sink` | `Searcher`, `Sink`, `SinkMatch`, `SinkContext`, `LineBuffer` |
| `grep-printer` | Output formatting: standard, summary, JSON, hyperlinks, color | `Standard`, `Summary`, `JSON`, `PathPrinter`, `Stats`, `ColorSpecs` |
| `globset` | High-performance glob matching against multiple patterns simultaneously | `Glob`, `GlobSet`, `GlobMatcher`, `GlobBuilder` |
| `ignore` | `.gitignore`/`.ignore`/`.rgignore` parsing plus recursive directory walking | `Walk`, `WalkParallel`, `WalkBuilder`, `Gitignore`, `Types`, `Override` |

### 1.2 Execution Flow

```
main()
  └─ run(flags::parse())
       ├─ flags::parse()
       │    ├─ Read RIPGREP_CONFIG_PATH → config args
       │    ├─ Merge config args + CLI args
       │    ├─ Parse into LowArgs (raw flag values)
       │    └─ Convert LowArgs → HiArgs (validated, resolved)
       │
       └─ match Mode:
            ├─ Search(single-threaded)
            │    ├─ Build: haystack_builder → walk_builder → matcher → searcher → printer
            │    ├─ Construct SearchWorker
            │    └─ Iterate haystacks sequentially
            │
            ├─ Search(multi-threaded)
            │    ├─ Same builder pipeline
            │    └─ Use WalkParallel (crossbeam-deque work stealing)
            │
            ├─ Files — list matching files only
            ├─ Types — list supported file types
            └─ Generate — emit completions or man page
```

### 1.3 Two-Phase Flag Parsing

Flag parsing uses a deliberate two-phase design (no `clap` or `structopt` dependency):

1. **LowArgs** (`crates/core/flags/lowargs.rs`): Raw representation of every flag value exactly as parsed from the command line. Uses `lexopt` for lightweight argument tokenization. All ~85 flags are defined as unit structs implementing the `Flag` trait in `defs.rs`.

2. **HiArgs** (`crates/core/flags/hiargs.rs`): Validated, resolved representation. Cross-flag validation happens here (e.g., `--sort` disables parallelism, `--count` switches printer mode). This is the struct that the search pipeline actually consumes.

The `Flag` trait per flag defines: `name_long`, `name_short`, `name_negated`, `doc_short`, `doc_long`, `doc_category`, `doc_variable`, and `update()`. The `FLAGS` array in `defs.rs` orders flags for documentation generation.

> [!NOTE]
> Shell completions and man pages are generated at runtime via `rg --generate complete-{bash,zsh,fish,powershell}` and `rg --generate man`, not at build time. This ensures they always match the compiled binary exactly.

### 1.4 Search Pipeline

The search pipeline is a layered composition:

```
Pattern(s)
  → PatternMatcher (grep-regex or grep-pcre2)
    → Searcher (grep-searcher, manages line buffering + binary detection)
      → Sink (grep-printer: Standard | Summary | JSON)
        → Output (stdout, optionally colored via termcolor)
```

**SearchWorker** (`crates/core/search.rs`) owns one instance of each layer and processes haystacks (files or stdin) one at a time. In multi-threaded mode, each thread gets its own `SearchWorker` clone.

### 1.5 Parallel Directory Traversal

The `ignore` crate's `WalkParallel` provides parallel directory traversal using `crossbeam-deque` work-stealing queues. Each worker thread:

1. Pops a directory entry from its local deque
2. If its deque is empty, steals from another thread's deque
3. Applies ignore rules (gitignore, rgignore, overrides) during traversal
4. Feeds matching paths to `SearchWorker`

> [!IMPORTANT]
> When `--sort` is specified, ripgrep automatically falls back to single-threaded mode. Sorted output is incompatible with parallel traversal because results must be emitted in deterministic order.

### 1.6 Ignore File Precedence

Ignore rules are evaluated in a strict precedence order (lowest to highest priority):

| Priority | Source | Notes |
|---|---|---|
| 1 (lowest) | Global gitignore (`core.excludesFile` from git config) | System-wide |
| 2 | `.gitignore` (per-directory, plus parent directories) | Standard git behavior |
| 3 | `.ignore` | ripgrep-specific, same syntax as gitignore |
| 4 | `.rgignore` | ripgrep-specific, same syntax as gitignore |
| 5 | `--ignore-file PATH` | CLI flag; earlier = lower precedence when specified multiple times |
| 6 (highest) | `--glob` / `--iglob` | Always overrides all ignore files |

### 1.7 Dependency Map

**Runtime dependencies:**

| Crate | Version | Role |
|---|---|---|
| `anyhow` | 1.0.75 | Error handling in the binary crate |
| `bstr` | 1.7.0 | Byte string utilities (non-UTF-8 safe) |
| `lexopt` | 0.3.0 | Lightweight CLI argument parsing |
| `log` | 0.4.5 | Logging facade |
| `serde_json` | 1.0.23 | JSON output serialization |
| `termcolor` | 1.1.0 | Cross-platform terminal color output |
| `textwrap` | 0.16.0 | Text wrapping for help output |
| `tikv-jemallocator` | 0.6.0 | jemalloc allocator (musl+64-bit only) |
| `regex-automata` | 0.4.0 | Regex engine backend (DFA/NFA) |
| `regex-syntax` | 0.8.0 | Regex syntax parsing |
| `aho-corasick` | 1.1.1 | Multi-pattern literal matching |
| `encoding_rs` | 0.8.33 | Text encoding support |
| `encoding_rs_io` | 0.1.7 | Streaming encoding transcoder |
| `memchr` | 2.6.3 | Fast single/multi-byte searching |
| `memmap2` | 0.9.0 | Memory-mapped file I/O |
| `crossbeam-deque` | 0.8.3 | Work-stealing deque for parallel walk |
| `walkdir` | 2.4.0 | Sequential directory traversal |
| `same-file` | 1.0.6 | Cross-platform same-file detection |
| `pcre2` | 0.2.6 | PCRE2 bindings (optional, behind `pcre2` feature) |
| `winapi-util` | 0.1.6 | Windows API utilities (Windows only) |
| `libc` | 0.2.148 | C library bindings (Unix only) |

**Dev dependencies:** `serde` 1.0.77, `serde_derive` 1.0.77.

---

## 2. System Requirements

### 2.1 Supported Platforms

ripgrep targets all major platforms via cross-compilation. Pre-built binaries are published for:

| Platform | Target Triple | Allocator | Notes |
|---|---|---|---|
| Linux x86_64 (glibc) | `x86_64-unknown-linux-gnu` | system | Most common |
| Linux x86_64 (musl) | `x86_64-unknown-linux-musl` | jemalloc | Static binary, portable |
| Linux aarch64 (gnu) | `aarch64-unknown-linux-gnu` | system | ARM64 servers |
| macOS x86_64 | `x86_64-apple-darwin` | system | Intel Macs |
| macOS aarch64 | `aarch64-apple-darwin` | system | Apple Silicon |
| Windows x86_64 (MSVC) | `x86_64-pc-windows-msvc` | system | Recommended for Windows |
| Windows x86_64 (GNU) | `x86_64-pc-windows-gnu` | system | MinGW toolchain |

### 2.2 Build Requirements

| Requirement | Version | Notes |
|---|---|---|
| Rust toolchain | 1.85+ (MSRV) | 2024 edition |
| C compiler | Any | Required for `libc` bindings; PCRE2 requires C compiler for JIT |
| PCRE2 development headers | 10.21+ | Only if building with `--features pcre2` |
| pkg-config | Any | Only for PCRE2 feature on Unix |

### 2.3 Optional Runtime Dependencies

ripgrep itself is a static binary with zero runtime library dependencies (when using musl). However, some features require external tools at runtime:

| Feature | External Tool | Purpose |
|---|---|---|
| `--search-zip` / `-z` | `gzip`, `bzip2`, `xz`, `lz4`, `zstd`, `brotli`, `uncompress` | Decompressing archives on the fly |
| `--pre <cmd>` | User-specified preprocessor | Arbitrary file preprocessing before search |
| `--hyperlink-format` | Terminal emulator with OSC 8 support | Clickable file links |

> [!TIP]
> For `--search-zip`, ripgrep shells out to external decompression utilities via `grep-cli`'s `DecompressionReader`. Supported formats: gz, bz2, xz, lzma, lz4, zst (zstandard), br (brotli), Z (compress). The decompressor binary must be in `PATH`.

---

## 3. Configuration Reference

### 3.1 Configuration File

ripgrep reads a configuration file at startup if the `RIPGREP_CONFIG_PATH` environment variable is set.

```bash
# Set in shell profile
export RIPGREP_CONFIG_PATH="$HOME/.ripgreprc"
```

**Config file format:**
- One flag per line (long or short form)
- Lines starting with `#` are comments
- Blank lines are ignored
- Flags that take values use `=` or a separate line for the value
- No shell expansion or quoting

Example `~/.ripgreprc`:

```
# Search hidden files by default
--hidden

# Use smart case
--smart-case

# Set max columns
--max-columns=150
--max-columns-preview

# Custom type definitions
--type-add=web:*.{html,css,js,ts}
```

> [!WARNING]
> Config file flags are prepended to CLI args, so CLI flags always override config file flags via last-wins semantics. Negated flags (e.g., `--no-hidden`) can explicitly reverse a config file setting.

### 3.2 Environment Variables

| Variable | Purpose | Default |
|---|---|---|
| `RIPGREP_CONFIG_PATH` | Path to configuration file | Not set (no config file) |
| `NO_COLOR` | Disables all color output when set to any value | Not set |
| `TERM` | If `dumb` or unset, disables colors | Inherited from terminal |
| `HOME` | Used to locate global gitignore (`$HOME/.config/git/ignore`) | System default |
| `XDG_CONFIG_HOME` | Alternate config directory for global gitignore (`$XDG_CONFIG_HOME/git/ignore`) | `$HOME/.config` |

### 3.3 Exit Codes

| Code | Meaning |
|---|---|
| `0` | At least one match was found |
| `1` | No matches found |
| `2` | An error occurred (also set when non-fatal errors are encountered, via `err_message!` macro) |

On Unix, a broken pipe causes graceful exit with code `0` (standard Unix convention).

### 3.4 Complete Flag Reference

All flags are defined in `crates/core/flags/defs.rs`. Flags follow last-wins semantics: if a flag is specified multiple times, the last occurrence takes effect. Most boolean flags have a `--no-` negated form.

#### 3.4.1 Search Behavior

| Long | Short | Type | Default | Description |
|---|---|---|---|---|
| `--regexp` | `-e` | `PATTERN` | -- | Specify a pattern. Multiple `-e` flags are OR'd together. |
| `--file` | `-f` | `PATH` | -- | Read patterns from a file, one per line. |
| `--fixed-strings` | `-F` | bool | `false` | Treat patterns as literal strings, not regexes. |
| `--no-fixed-strings` | -- | bool | -- | Negate `--fixed-strings`. |
| `--ignore-case` | `-i` | bool | `false` | Case-insensitive search. |
| `--no-ignore-case` | -- | bool | -- | Negate `--ignore-case`. |
| `--case-sensitive` | `-s` | bool | `false` | Force case-sensitive search (overrides `--smart-case`). |
| `--smart-case` | `-S` | bool | `false` | Case-insensitive if pattern is all lowercase; case-sensitive otherwise. |
| `--no-smart-case` | -- | bool | -- | Negate `--smart-case`. |
| `--word-regexp` | `-w` | bool | `false` | Only match whole words. Wraps pattern in `\b...\b`. |
| `--no-word-regexp` | -- | bool | -- | Negate `--word-regexp`. |
| `--line-regexp` | `-x` | bool | `false` | Only match whole lines. Wraps pattern in `^...$`. |
| `--no-line-regexp` | -- | bool | -- | Negate `--line-regexp`. |
| `--multiline` | `-U` | bool | `false` | Enable multiline matching. `.` matches `\n`. |
| `--no-multiline` | -- | bool | -- | Negate `--multiline`. |
| `--multiline-dotall` | -- | bool | `false` | Make `.` match `\n` in multiline mode (enabled by default when `-U` is used). |
| `--no-multiline-dotall` | -- | bool | -- | Negate `--multiline-dotall`. |
| `--crlf` | -- | bool | `false` | Treat CRLF (`\r\n`) as a line terminator. |
| `--no-crlf` | -- | bool | -- | Negate `--crlf`. |
| `--null-data` | -- | bool | `false` | Use NUL byte as line terminator instead of `\n`. |
| `--no-null-data` | -- | bool | -- | Negate `--null-data`. |
| `--invert-match` | `-v` | bool | `false` | Invert matching: show non-matching lines. |
| `--no-invert-match` | -- | bool | -- | Negate `--invert-match`. |
| `--count` | `-c` | bool | `false` | Show count of matching lines per file. |
| `--count-matches` | -- | bool | `false` | Show count of individual matches per file (not lines). |
| `--max-count` | `-m` | `NUM` | `0` (unlimited) | Stop searching a file after `NUM` matching lines. |
| `--only-matching` | `-o` | bool | `false` | Print only matched parts of a line, each on its own line. |
| `--no-only-matching` | -- | bool | -- | Negate `--only-matching`. |
| `--replace` | `-r` | `REPLACEMENT` | -- | Replace matches with the given string. Supports capture groups (`$1`, `$name`). |
| `--passthru` | -- | bool | `false` | Print both matching and non-matching lines (like `cat` with highlights). |
| `--no-passthru` | -- | bool | -- | Negate `--passthru`. |
| `--engine` | -- | `ENGINE` | `default` | Regex engine: `default`, `pcre2`, `auto`. |
| `--no-engine` | -- | bool | -- | Reset to default engine. |
| `--pcre2` | `-P` | bool | `false` | Use PCRE2 regex engine. Shorthand for `--engine=pcre2`. |
| `--no-pcre2` | -- | bool | -- | Negate `--pcre2`. |
| `--auto-hybrid-regex` | -- | bool | `false` | Deprecated alias for `--engine=auto`. |
| `--no-auto-hybrid-regex` | -- | bool | -- | Negate `--auto-hybrid-regex`. |
| `--stop-on-nonmatch` | -- | bool | `false` | Stop searching a file after the first non-matching line following a match. Useful for pre-sorted data. |
| `--no-stop-on-nonmatch` | -- | bool | -- | Negate `--stop-on-nonmatch`. |

#### 3.4.2 File & Directory Selection

| Long | Short | Type | Default | Description |
|---|---|---|---|---|
| `--glob` | `-g` | `GLOB` | -- | Include or exclude files/directories matching the glob. Prefix with `!` to exclude. Multiple allowed. |
| `--iglob` | -- | `GLOB` | -- | Case-insensitive `--glob`. |
| `--type` | `-t` | `TYPE` | -- | Only search files matching the named type (e.g., `py`, `js`). Multiple allowed. |
| `--type-not` | `-T` | `TYPE` | -- | Exclude files matching the named type. Multiple allowed. |
| `--type-add` | -- | `SPEC` | -- | Add a custom file type. Format: `NAME:GLOB` (e.g., `web:*.{html,css,js}`). |
| `--type-clear` | -- | `TYPE` | -- | Clear all glob definitions for the named type. |
| `--type-list` | -- | bool | `false` | List all available file types and their globs. |
| `--hidden` | `-.` | bool | `false` | Search hidden files and directories (those starting with `.`). |
| `--no-hidden` | -- | bool | -- | Negate `--hidden` (default behavior). |
| `--binary` | -- | bool | `false` | Search binary files. By default, binary files are skipped after a NUL byte is detected. |
| `--no-binary` | -- | bool | -- | Negate `--binary`. |
| `--text` | `-a` | bool | `false` | Treat binary files as text (search the entire file regardless of NUL bytes). |
| `--no-text` | -- | bool | -- | Negate `--text`. |
| `--follow` | `-L` | bool | `false` | Follow symbolic links during directory traversal. |
| `--no-follow` | -- | bool | -- | Negate `--follow`. |
| `--one-file-system` | -- | bool | `false` | Do not cross filesystem boundaries during traversal. |
| `--no-one-file-system` | -- | bool | -- | Negate `--one-file-system`. |
| `--max-depth` | `-d` | `NUM` | unlimited | Descend at most `NUM` directories. `--max-depth=0` only searches the start path itself. |
| `--max-filesize` | -- | `SIZE` | unlimited | Skip files larger than `SIZE`. Accepts suffixes: `K`, `M`, `G`. |
| `--ignore-file` | -- | `PATH` | -- | Additional ignore file (gitignore syntax). Multiple allowed; later = higher precedence. |
| `--ignore-file-case-insensitive` | -- | bool | `false` | Process ignore file globs case-insensitively. |
| `--no-ignore-file-case-insensitive` | -- | bool | -- | Negate `--ignore-file-case-insensitive`. |
| `--no-ignore` | -- | bool | `false` | Disable all ignore file processing (gitignore, rgignore, etc.). |
| `--ignore` | -- | bool | -- | Re-enable ignore file processing. |
| `--no-ignore-dot` | -- | bool | `false` | Disable `.ignore` and `.rgignore` processing. |
| `--ignore-dot` | -- | bool | -- | Re-enable `.ignore` / `.rgignore` processing. |
| `--no-ignore-global` | -- | bool | `false` | Disable global gitignore processing. |
| `--ignore-global` | -- | bool | -- | Re-enable global gitignore processing. |
| `--no-ignore-parent` | -- | bool | `false` | Disable reading `.gitignore` files from parent directories. |
| `--ignore-parent` | -- | bool | -- | Re-enable parent `.gitignore` processing. |
| `--no-ignore-vcs` | -- | bool | `false` | Disable `.gitignore` processing (but keep `.ignore`/`.rgignore`). |
| `--ignore-vcs` | -- | bool | -- | Re-enable `.gitignore` processing. |
| `--no-ignore-exclude` | -- | bool | `false` | Disable `.git/info/exclude` processing. |
| `--ignore-exclude` | -- | bool | -- | Re-enable `.git/info/exclude` processing. |
| `--no-require-git` | -- | bool | `false` | Apply `.gitignore` rules even outside git repositories. |
| `--require-git` | -- | bool | -- | Only apply `.gitignore` inside git repos (default). |
| `--search-zip` | `-z` | bool | `false` | Search inside compressed files. Requires external decompressor in `PATH`. |
| `--no-search-zip` | -- | bool | -- | Negate `--search-zip`. |
| `--pre` | -- | `COMMAND` | -- | Run each file through `COMMAND` before searching. The file path is passed as the first argument; ripgrep searches stdout. |
| `--no-pre` | -- | bool | -- | Disable preprocessor. |
| `--pre-glob` | -- | `GLOB` | -- | Only apply `--pre` to files matching this glob. Multiple allowed. |
| `--sort` | -- | `CRITERIA` | none | Sort results. Values: `path`, `modified`, `accessed`, `created`, `none`. Disables parallelism. |
| `--sortr` | -- | `CRITERIA` | none | Reverse sort. Same values as `--sort`. Disables parallelism. |

#### 3.4.3 Output Formatting

| Long | Short | Type | Default | Description |
|---|---|---|---|---|
| `--color` | -- | `WHEN` | `auto` | When to use colors: `never`, `auto`, `always`, `ansi`. |
| `--colors` | -- | `SPEC` | -- | Configure specific color settings. Format: `{type}:{attribute}:{value}`. |
| `--hyperlink-format` | -- | `FORMAT` | -- | Format string for hyperlinks (OSC 8). Placeholders: `{path}`, `{line}`, `{column}`, `{host}`. |
| `--no-hyperlink-format` | -- | bool | -- | Disable hyperlinks. |
| `--heading` | -- | bool | auto | Group matches by file with filename as heading. Default when output is a terminal. |
| `--no-heading` | -- | bool | -- | Don't group matches by file. Default when output is piped. |
| `--line-number` | `-n` | bool | auto | Show line numbers. Default when output is a terminal. |
| `--no-line-number` | `-N` | bool | -- | Suppress line numbers. |
| `--column` | -- | bool | `false` | Show column number of first match on each line. |
| `--no-column` | -- | bool | -- | Negate `--column`. |
| `--byte-offset` | `-b` | bool | `false` | Show zero-based byte offset of each matching line. |
| `--no-byte-offset` | -- | bool | -- | Negate `--byte-offset`. |
| `--with-filename` | `-H` | bool | auto | Show filename with matches. Default when searching multiple files. |
| `--no-filename` | `-I` | bool | -- | Suppress filename in output. |
| `--context` | `-C` | `NUM` | `0` | Show `NUM` lines of context around each match. |
| `--after-context` | `-A` | `NUM` | `0` | Show `NUM` lines after each match. |
| `--before-context` | `-B` | `NUM` | `0` | Show `NUM` lines before each match. |
| `--context-separator` | -- | `STRING` | `--` | Separator between context groups. |
| `--no-context-separator` | -- | bool | -- | Disable context separator. |
| `--field-context-separator` | -- | `STRING` | `-` | Separator between fields for context lines. |
| `--field-match-separator` | -- | `STRING` | `:` | Separator between fields for matching lines. |
| `--path-separator` | -- | `STRING` | OS default | Path separator character. |
| `--null` | `0` | bool | `false` | Use NUL byte after file paths (for use with `xargs -0`). |
| `--max-columns` | `-M` | `NUM` | `0` (unlimited) | Don't print lines longer than `NUM` bytes. |
| `--max-columns-preview` | -- | bool | `false` | Show a preview of long lines instead of omitting them entirely. |
| `--no-max-columns-preview` | -- | bool | -- | Negate `--max-columns-preview`. |
| `--trim` | -- | bool | `false` | Trim leading ASCII whitespace from each line. |
| `--no-trim` | -- | bool | -- | Negate `--trim`. |
| `--vimgrep` | -- | bool | `false` | Show results in vim-compatible format (each match on its own line with column). |
| `--json` | -- | bool | `false` | Output results as JSON lines (one JSON object per event). |
| `--no-json` | -- | bool | -- | Negate `--json`. |
| `--stats` | -- | bool | `false` | Print aggregate statistics at the end of the search. |
| `--no-stats` | -- | bool | -- | Negate `--stats`. |
| `--include-zero` | -- | bool | `false` | With `--count`, show files with zero matches. |
| `--no-include-zero` | -- | bool | -- | Negate `--include-zero`. |

#### 3.4.4 File Listing Modes

| Long | Short | Type | Default | Description |
|---|---|---|---|---|
| `--files` | -- | bool | `false` | List files that would be searched, without searching. |
| `--files-with-matches` | `-l` | bool | `false` | Print only names of files containing matches. |
| `--files-without-match` | -- | bool | `false` | Print only names of files containing no matches. |
| `--no-files-without-match` | -- | bool | -- | Negate `--files-without-match`. |

#### 3.4.5 Encoding & Input

| Long | Short | Type | Default | Description |
|---|---|---|---|---|
| `--encoding` | `-E` | `ENCODING` | `auto` | Specify text encoding (e.g., `utf-8`, `euc-jp`, `latin1`). Uses `encoding_rs` names. |
| `--no-encoding` | -- | bool | -- | Reset to auto-detection. |
| `--no-mmap` | -- | bool | `false` | Disable memory-mapped I/O. |
| `--mmap` | -- | bool | -- | Enable memory-mapped I/O. |
| `--line-buffered` | -- | bool | `false` | Force line buffering (flush after each line). |
| `--no-line-buffered` | -- | bool | -- | Negate `--line-buffered`. |
| `--block-buffered` | -- | bool | `false` | Force block buffering. |
| `--no-block-buffered` | -- | bool | -- | Negate `--block-buffered`. |

#### 3.4.6 Concurrency

| Long | Short | Type | Default | Description |
|---|---|---|---|---|
| `--threads` | `-j` | `NUM` | `0` (auto) | Number of threads for parallel search. `0` means auto-detect based on available cores. |

#### 3.4.7 Logging & Debugging

| Long | Short | Type | Default | Description |
|---|---|---|---|---|
| `--debug` | -- | bool | `false` | Show debug messages (written to stderr). |
| `--no-debug` | -- | bool | -- | Negate `--debug`. |
| `--trace` | -- | bool | `false` | Show trace-level debug messages (very verbose). |
| `--no-trace` | -- | bool | -- | Negate `--trace`. |
| `--no-messages` | -- | bool | `false` | Suppress error messages (e.g., permission denied). |
| `--messages` | -- | bool | -- | Re-enable error messages. |
| `--no-unicode` | -- | bool | `false` | Disable Unicode support in regex patterns. |
| `--unicode` | -- | bool | -- | Re-enable Unicode support. |

#### 3.4.8 Meta / Output Generation

| Long | Short | Type | Default | Description |
|---|---|---|---|---|
| `--help` | `-h` | bool | -- | Print short help. Use `--help` for long-form verbose help. |
| `--version` | `-V` | bool | -- | Print version information. |
| `--generate` | -- | `KIND` | -- | Generate auxiliary files: `complete-bash`, `complete-zsh`, `complete-fish`, `complete-powershell`, `man`. |
| `--hostname-bin` | -- | `COMMAND` | -- | Command to run to get hostname (for `{host}` in `--hyperlink-format`). |

---

## 4. Deployment & Scaling

### 4.1 Building from Source

```bash
# Standard release build
git clone https://github.com/BurntSushi/ripgrep
cd ripgrep
cargo build --release
# Binary at: target/release/rg

# Optimized release with LTO (smaller, faster, slower to compile)
cargo build --profile release-lto
# Binary at: target/release-lto/rg

# With PCRE2 support
cargo build --release --features pcre2

# Debian package (requires cargo-deb)
cargo install cargo-deb
cargo deb --profile deb
```

### 4.2 Build Profiles

| Profile | LTO | Debug Info | Strip | Panic | Codegen Units | Use Case |
|---|---|---|---|---|---|---|
| `release` | no | `1` (line tables) | no | unwind | default | Development releases |
| `release-lto` | fat | `0` | yes | abort | 1 | Production binaries |
| `deb` | inherits `release-lto` | `0` | yes | abort | 1 | `.deb` packages |

### 4.3 Feature Flags

| Feature | Default | Effect |
|---|---|---|
| `pcre2` | off | Enables the `grep-pcre2` crate, linking against `libpcre2-8`. Requires PCRE2 development headers and a C compiler. |

### 4.4 Allocator Selection

The allocator is selected at compile time via `build.rs`:

| Condition | Allocator |
|---|---|
| `target_env = "musl"` AND 64-bit | `tikv-jemallocator` (jemalloc) |
| All other targets | System allocator |

> [!NOTE]
> jemalloc is used on musl+64-bit targets because musl's built-in allocator has known performance regressions with allocation-heavy workloads. On glibc targets, the system allocator is generally competitive with jemalloc.

### 4.5 Cross-Compilation

ripgrep supports cross-compilation via standard Rust toolchains:

```bash
# Example: build for aarch64 Linux from x86_64
rustup target add aarch64-unknown-linux-gnu
cargo build --release --target aarch64-unknown-linux-gnu

# Using cross (recommended for cross-compilation with C dependencies like PCRE2)
cargo install cross
cross build --release --target aarch64-unknown-linux-musl
```

### 4.6 Package Distribution

**Shell completions** (generate and install):

```bash
# Bash
rg --generate complete-bash > /usr/share/bash-completion/completions/rg

# Zsh
rg --generate complete-zsh > /usr/local/share/zsh/site-functions/_rg

# Fish
rg --generate complete-fish > /usr/share/fish/vendor_completions.d/rg.fish

# PowerShell
rg --generate complete-powershell | Out-File -Encoding utf8 -FilePath "$env:USERPROFILE\Documents\PowerShell\Completions\rg.ps1"
```

**Man page:**

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

### 4.7 Static Binary Builds

For fully static, zero-dependency binaries:

```bash
# Build static musl binary (Linux)
cargo build --release --target x86_64-unknown-linux-musl
# Result: standalone ~6MB binary, no shared library dependencies
```

This is the recommended approach for containerized deployments:

```dockerfile
# Multi-stage build for minimal image
FROM rust:1.85-slim AS builder
RUN apt-get update && apt-get install -y pkg-config musl-tools
WORKDIR /build
COPY . .
RUN rustup target add x86_64-unknown-linux-musl
RUN cargo build --profile release-lto --target x86_64-unknown-linux-musl

FROM scratch
COPY --from=builder /build/target/x86_64-unknown-linux-musl/release-lto/rg /rg
ENTRYPOINT ["/rg"]
```

---

## 5. Operations

### 5.1 Debugging and Diagnostics

**Debug output** shows which files are searched, which are skipped, and why:

```bash
# Show debug messages
rg --debug PATTERN

# Show trace-level detail (very verbose — shows every ignore rule evaluation)
rg --trace PATTERN
```

Debug output goes to stderr, so it can be captured separately:

```bash
rg --debug PATTERN 2>debug.log
```

Common debug output patterns:

| Message Pattern | Meaning |
|---|---|
| `ignoring <path>: matched ignore pattern` | File excluded by gitignore/rgignore |
| `binary file matches` | NUL byte detected, file skipped |
| `<path>: Permission denied` | OS-level permission error |
| `skipping <path>: max filesize exceeded` | File exceeds `--max-filesize` |

**Statistics** provide aggregate search metrics:

```bash
rg --stats PATTERN
# Output includes: files searched, files matched, lines matched,
# matches found, bytes searched, time elapsed
```

### 5.2 Search Modes

| Mode | Activated By | Behavior |
|---|---|---|
| Search (default) | `rg PATTERN [PATH...]` | Search for matches and print results |
| Count | `--count` / `-c` | Print match count per file |
| Count matches | `--count-matches` | Print individual match count (not lines) per file |
| Files with matches | `--files-with-matches` / `-l` | Print only filenames with matches |
| Files without match | `--files-without-match` | Print only filenames without matches |
| List files | `--files` | List all files that would be searched |
| List types | `--type-list` | List all known file types |
| Generate | `--generate KIND` | Emit shell completions or man page |

### 5.3 JSON Output Format

The `--json` flag outputs structured JSON lines, one per event. Event types:

| Event | Description | Key Fields |
|---|---|---|
| `begin` | Start of a file search | `path` |
| `end` | End of a file search | `path`, `stats` |
| `match` | A matching line | `path`, `lines`, `line_number`, `submatches` |
| `context` | A context line | `path`, `lines`, `line_number` |
| `summary` | Final statistics | `elapsed_total`, `stats` |

```bash
# Pipe JSON output to jq for processing
rg --json PATTERN | jq 'select(.type == "match") | .data.submatches'
```

> [!TIP]
> JSON output is stable and machine-parseable. It is the recommended format for programmatic consumption of ripgrep results. Each line is a self-contained JSON object, making it compatible with streaming JSON processors like `jq`.

### 5.4 Binary File Handling

ripgrep uses a NUL-byte heuristic to detect binary files:

| Flag | Behavior |
|---|---|
| (default) | If a NUL byte is found in the first few KB, stop searching the file and print a notification |
| `--binary` | Search binary files but still report binary detection |
| `--text` / `-a` | Treat all files as text (search entire contents regardless of NUL bytes) |
| `--no-binary` | Skip binary files entirely (no notification printed) |

### 5.5 Memory-Mapped I/O

ripgrep can use memory-mapped I/O for reading files. The decision is made heuristically by default, but can be overridden:

```bash
# Force memory-mapped I/O
rg --mmap PATTERN

# Disable memory-mapped I/O
rg --no-mmap PATTERN
```

> [!CAUTION]
> Memory-mapped I/O can cause `SIGBUS` on Unix systems if a file is truncated while being read. ripgrep installs a `SIGBUS` handler to deal with this gracefully, but `--no-mmap` avoids the issue entirely. Additionally, memory-mapped I/O is generally slower when searching many small files due to page fault overhead.

### 5.6 Handling Large-Scale Searches

For searching very large codebases or directory trees:

```bash
# Limit thread count to reduce memory pressure
rg -j4 PATTERN /large/tree

# Skip large files (e.g., vendored bundles, generated code)
rg --max-filesize 1M PATTERN

# Limit traversal depth
rg --max-depth 5 PATTERN

# Stay on one filesystem (avoid NFS, tmpfs, etc.)
rg --one-file-system PATTERN

# Suppress permission errors to reduce noise
rg --no-messages PATTERN /
```

---

## 6. Performance

### 6.1 Performance Architecture

ripgrep's speed comes from several architectural decisions working together:

1. **Regex engine selection**: Uses `regex-automata` which compiles patterns to DFA or NFA state machines. For literal patterns, it extracts literals and uses `memchr` or `aho-corasick` for fast scanning before engaging the full regex engine.

2. **Parallel traversal**: The `ignore` crate's `WalkParallel` uses `crossbeam-deque` work-stealing for efficient parallel directory traversal. Each thread has its own search stack.

3. **Ignore-during-walk**: `.gitignore` rules are evaluated during directory traversal, not after. Entire directory trees can be pruned without reading their contents.

4. **Line-oriented searching**: `grep-searcher` reads in large chunks (default 64KB buffer) and scans for line terminators and matches simultaneously, minimizing passes over the data.

5. **Allocation minimization**: The `bstr` crate and careful buffer reuse minimize allocations in the hot path.

### 6.2 Thread Tuning

```bash
# Use exactly 4 threads
rg -j4 PATTERN

# Use 1 thread (single-threaded mode, deterministic output order)
rg -j1 PATTERN

# Use all available cores (default)
rg -j0 PATTERN
```

The default (`-j0`) detects available CPU cores via `std::thread::available_parallelism()`. For I/O-bound searches (network filesystems, spinning disks), reducing thread count may improve throughput by reducing seek contention.

### 6.3 Performance-Impacting Flags

| Flag | Performance Impact | Why |
|---|---|---|
| `--sort` / `--sortr` | Disables parallelism entirely | Must collect and sort all results |
| `--pcre2` / `-P` | Slower for simple patterns | PCRE2 engine is generally slower than Rust regex for non-backtracking patterns |
| `--multiline` / `-U` | Slower | Must process entire file as one unit instead of line-by-line |
| `--search-zip` / `-z` | Much slower | Must decompress each file via external process |
| `--pre` | Much slower | Must fork and exec external command per file |
| `--no-ignore` | Mixed | Skips ignore file parsing but searches more files total |
| `--mmap` | Mixed | Faster for large files on SSDs; slower for many small files |
| `--text` / `-a` | Neutral | Only disables binary detection heuristic |
| `--encoding` | Slightly slower | Must transcode file contents through `encoding_rs` |
| `--no-unicode` | Faster | Disables Unicode character class tables in regex engine |
| `--fixed-strings` / `-F` | Faster | Enables pure literal matching, bypasses regex compilation |

### 6.4 Benchmarking

ripgrep includes a benchmark suite at `benchsuite/benchsuite` (Python script):

```bash
cd benchsuite
python benchsuite --help
```

The benchmark suite compares ripgrep against:
- `grep` (GNU)
- `git grep`
- `ag` (The Silver Searcher)
- `ugrep`

> [!TIP]
> For accurate benchmarks, drop filesystem caches before each run: `sudo sh -c 'echo 3 > /proc/sys/vm/drop_caches'` on Linux. Run each benchmark multiple times to account for variance. The benchsuite uses a corpus of real-world data (Linux kernel source, subtitles, etc.) for representative measurements.

---

## 7. Security

### 7.1 Security Model

ripgrep is a local tool that reads files and writes to stdout. Its security surface:

| Surface | Risk | Mitigation |
|---|---|---|
| Regex patterns | ReDoS (catastrophic backtracking) | Rust `regex` engine guarantees linear time (no backtracking). PCRE2 engine (`-P`) does allow backtracking. |
| File traversal | Symlink following | Symlinks are NOT followed by default. `--follow` / `-L` enables traversal. |
| File traversal | Symlink loops | The `ignore` crate detects and breaks symlink cycles. |
| Preprocessor | Arbitrary code execution | `--pre` runs arbitrary commands; only use trusted preprocessors. |
| Decompression | Zip bombs / decompression bombs | `--search-zip` shells out to decompressor utilities; they handle their own limits. |
| Input patterns | Untrusted pattern injection | Patterns from files (`-f`) or args (`-e`) are executed as regexes. Use `--fixed-strings` for untrusted input. |
| Config file | Privilege escalation | `RIPGREP_CONFIG_PATH` could point to an attacker-controlled file. Only set in trusted environments. |
| Binary detection | Information disclosure | NUL-byte heuristic may miss some binary files. `--no-binary` is more conservative. |

### 7.2 Regex Engine Safety

The default Rust `regex` engine provides **guaranteed linear-time** matching:

- No catastrophic backtracking
- No ReDoS vulnerability
- Bounded memory usage proportional to pattern size
- No backreferences (by design)

> [!WARNING]
> The PCRE2 engine (`--pcre2` / `-P`) does NOT guarantee linear time. Patterns with backreferences or complex lookaround can exhibit exponential time complexity. Do not use `--pcre2` with untrusted patterns in security-sensitive contexts.

### 7.3 Safe Usage with Untrusted Input

```bash
# Safe: treat user input as literal string
rg --fixed-strings -- "$USER_INPUT" /path

# Safe: read patterns from file, treated as literals
rg --fixed-strings -f patterns.txt /path

# Unsafe: user input interpreted as regex
rg "$USER_INPUT" /path  # DO NOT do this with untrusted input

# Note: use -- to prevent patterns starting with - from being parsed as flags
rg --fixed-strings -- "$USER_INPUT" /path
```

### 7.4 File System Safety

- ripgrep does not follow symlinks unless `--follow` is explicitly passed
- The `--one-file-system` flag prevents crossing mount boundaries (useful in containers or to avoid NFS mounts)
- `--max-depth` limits traversal depth, preventing runaway searches in deep directory trees
- `--max-filesize` limits per-file read size, preventing memory exhaustion on large files

> [!CAUTION]
> When running ripgrep in environments where the file tree is partially controlled by untrusted users (e.g., shared hosting, CI with untrusted repos), be aware that maliciously crafted `.gitignore` or `.rgignore` files can influence which files are skipped. Use `--no-ignore` to disable all ignore file processing in such environments.

---

## 8. Developer Internals

### 8.1 Source Layout

```
crates/
  core/                    Binary crate (rg)
    main.rs                Entry point: main() → run()
    search.rs              SearchWorker: owns matcher + searcher + printer
    haystack.rs            Haystack construction and filtering
    logger.rs              Log initialization (env_logger-style)
    flags/
      mod.rs               Flag trait, Category enum, FlagValue
      defs.rs              ~85 flag definitions (unit structs implementing Flag)
      parse.rs             CLI argument parser → LowArgs
      lowargs.rs           LowArgs struct (raw flag values)
      hiargs.rs            HiArgs struct (validated, resolved)
      config.rs            Config file parser (RIPGREP_CONFIG_PATH)
      complete/            Shell completion generators
        bash.rs            Bash completion script
        zsh.rs             Zsh completion script
        fish.rs            Fish completion script
        powershell.rs      PowerShell completion script
      doc/
        help.rs            Help text generation (short + long)
        man.rs             Man page (roff) generation
  grep/                    Facade crate (re-exports grep-*)
  cli/                     CLI utilities
    decompress.rs          DecompressionReader (external decompressor process)
    escape.rs              Byte string escaping
    pattern.rs             Pattern I/O (read from file, stdin)
    wtr.rs                 StandardStream (TTY-aware writer)
  matcher/                 Matcher trait
    interpolate.rs         Capture group interpolation ($1, $name)
  regex/                   Rust regex adapter
    ast.rs                 AST analysis for optimization
    config.rs              RegexMatcherBuilder config
    error.rs               Error types
    literal.rs             Literal extraction for acceleration
    non_matching.rs        Non-matching byte detection
    strip.rs               Pattern stripping utilities
    word.rs                Word boundary handling
  pcre2/                   PCRE2 adapter (optional feature)
    error.rs               PCRE2 error types
    matcher.rs             PCRE2 Matcher implementation
  searcher/                Core search engine
    searcher/
      core.rs              Searcher implementation
      glue.rs              Searcher-to-Matcher glue logic
    line_buffer.rs         Line-oriented buffered reading (64KB default)
    sink.rs                Sink trait and implementations
  printer/                 Output printers
    standard.rs            Standard human-readable output (grep-like)
    summary.rs             Summary output (counts, file lists)
    json.rs                JSON lines output format
    hyperlink.rs           OSC 8 hyperlink generation
    color.rs               Color specification parsing
    stats.rs               Search statistics accumulation
    util.rs                Shared printer utilities
  globset/                 Glob matching library
    glob.rs                Glob parsing and compilation to regex
    fnmatch.rs             fnmatch-style matching
    pathutil.rs            Path normalization utilities
    serde_impl.rs          Serde Serialize/Deserialize for Glob
  ignore/                  Ignore + directory walking
    walk.rs                Walk (sequential) and WalkParallel (crossbeam-deque)
    dir.rs                 Per-directory ignore rule management
    gitignore.rs           .gitignore file parser
    overrides.rs           CLI --glob override rules
    types.rs               Built-in file type definitions and matching
    pathutil.rs            Path utilities (is_hidden, strip_prefix, etc.)

tests/
  tests.rs                 Integration test entry point (imports all test modules)
  binary.rs                Binary file handling tests
  feature.rs               Feature-specific tests (types, globs, etc.)
  json.rs                  JSON output format tests
  misc.rs                  Miscellaneous tests
  multiline.rs             Multiline matching tests
  regression.rs            Regression tests (linked to GitHub issues)
  hay.rs                   Test haystack helpers (create temp dirs with test data)
  util.rs                  Test utilities (run rg binary, assert output)
  macros.rs                Test assertion macros
  data/                    Test data (sherlock.txt in various compressed formats)

benchsuite/
  benchsuite               Python benchmark runner script

fuzz/
  fuzz_targets/
    fuzz_glob.rs           Fuzz target for globset glob parsing

ci/
  sha256-releases          Generate SHA256 checksums for release artifacts
  test-complete            Validate generated shell completions
  ubuntu-install-packages  Install build dependencies on Ubuntu
  utils.sh                 Shared CI utility functions
```

### 8.2 Adding a New Flag

Each flag is a unit struct implementing the `Flag` trait in `crates/core/flags/defs.rs`. To add a new flag:

1. **Define the struct and implement `Flag`:**

```rust
/// --my-new-flag
#[derive(Debug)]
struct FlagMyNewFlag;

impl Flag for FlagMyNewFlag {
    fn is_switch(&self) -> bool { true }
    fn name_long(&self) -> &'static str { "my-new-flag" }
    fn name_short(&self) -> Option<u8> { None }
    fn name_negated(&self) -> Option<&'static str> { Some("no-my-new-flag") }
    fn doc_category(&self) -> Category { Category::Search }
    fn doc_short(&self) -> &'static str { "Short description." }
    fn doc_long(&self) -> &'static str { "Long description..." }
    fn update(&self, v: FlagValue, args: &mut LowArgs) -> anyhow::Result<()> {
        args.my_new_flag = v.unwrap_switch();
        Ok(())
    }
}
```

2. **Add the field to `LowArgs`** in `lowargs.rs`.
3. **Add the flag to the `FLAGS` array** in `defs.rs`, maintaining alphabetical order.
4. **Wire it into `HiArgs`** in `hiargs.rs` for validation and resolution.
5. **Use it in the search pipeline** (e.g., `search.rs`, `haystack.rs`).
6. **Add tests**: inline `#[test]` functions in the flag definition, plus integration tests in `tests/`.

### 8.3 The Matcher Trait

The `grep-matcher` crate defines the abstract `Matcher` trait that makes ripgrep engine-agnostic:

```rust
pub trait Matcher {
    type Captures: Captures;
    type Error: std::fmt::Display;

    fn find_at(
        &self, haystack: &[u8], at: usize,
    ) -> Result<Option<Match>, Self::Error>;

    fn new_captures(
        &self,
    ) -> Result<Self::Captures, Self::Error>;

    fn captures_at(
        &self, haystack: &[u8], at: usize, caps: &mut Self::Captures,
    ) -> Result<bool, Self::Error>;

    // Additional methods with default implementations:
    // find(), find_iter(), captures(), captures_iter(),
    // replace(), replace_with_captures(), etc.
}
```

Both `grep-regex::RegexMatcher` and `grep-pcre2::RegexMatcher` implement this trait. Custom regex engines can be integrated by providing a `Matcher` implementation.

The `Match` type is a simple `(start, end)` byte offset pair. `LineTerminator` controls what constitutes a line boundary. `ByteSet` is a bitset over byte values used for fast character class membership tests.

### 8.4 The Sink Trait

The `grep-searcher` crate's `Sink` trait is the output callback interface:

```rust
pub trait Sink {
    type Error;

    fn matched(
        &mut self, searcher: &Searcher, mat: &SinkMatch<'_>,
    ) -> Result<bool, Self::Error>;

    // Optional methods with defaults:
    fn context(
        &mut self, _: &Searcher, _: &SinkContext<'_>,
    ) -> Result<bool, Self::Error> { Ok(true) }

    fn begin(
        &mut self, _: &Searcher,
    ) -> Result<bool, Self::Error> { Ok(true) }

    fn finish(
        &mut self, _: &Searcher, _: &SinkFinish,
    ) -> Result<(), Self::Error> { Ok(()) }
}
```

The `grep-printer` crate provides three `Sink` implementations:

| Implementation | Output Format | Use Case |
|---|---|---|
| `Standard` | Human-readable, grep-like, with optional color | Terminal output |
| `Summary` | File-level summaries (counts, paths only) | `--count`, `--files-with-matches` |
| `JSON` | Machine-readable JSON lines | `--json`, programmatic consumption |

The return value of `matched()` and `context()` controls whether searching continues (`true`) or stops early (`false`), enabling features like `--max-count`.

### 8.5 The Ignore Crate — Reusable Library

The `ignore` crate is one of ripgrep's most widely reused components. It is used by many other tools (fd, tokei, etc.) for fast, gitignore-aware directory traversal.

**`WalkBuilder`**: Configures directory traversal with ignore rules, file type filters, and parallelism.

```rust
use ignore::WalkBuilder;

// Sequential walk
for entry in WalkBuilder::new("./src").build() {
    let entry = entry.unwrap();
    println!("{}", entry.path().display());
}

// Parallel walk
WalkBuilder::new("./src")
    .hidden(false)        // search hidden files
    .git_ignore(true)     // respect .gitignore
    .follow_links(false)  // don't follow symlinks
    .threads(4)           // parallel walk threads
    .build_parallel()
    .run(|| {
        Box::new(|entry| {
            // Process entry in worker thread
            ignore::WalkState::Continue
        })
    });
```

**`Gitignore`**: Parses and evaluates `.gitignore` rules. Can be used standalone without directory traversal.

**`Types`**: File type matching based on glob patterns. Includes ~150 built-in file type definitions.

### 8.6 The Globset Crate — Reusable Library

`globset` is a standalone crate for high-performance glob matching. Its key feature is `GlobSet`, which compiles multiple globs into a single regex for simultaneous matching in one pass:

```rust
use globset::{Glob, GlobSetBuilder};

let mut builder = GlobSetBuilder::new();
builder.add(Glob::new("*.rs")?);
builder.add(Glob::new("*.toml")?);
let set = builder.build()?;

// Returns indices of all matching globs
let matches: Vec<usize> = set.matches("src/main.rs");
assert!(set.is_match("src/main.rs"));
```

Glob syntax supported:
- `*` — matches any sequence of non-path-separator characters
- `**` — matches any sequence of characters, including path separators
- `?` — matches any single non-path-separator character
- `[abc]` — character class
- `[!abc]` / `[^abc]` — negated character class
- `{a,b,c}` — alternation

### 8.7 Error Handling

- The binary crate uses `anyhow` for error propagation with context
- Library crates define their own error types (no `anyhow` dependency in libraries)
- The `err_message!` macro in the binary crate prints non-fatal errors to stderr and sets the exit code to `2`
- Broken pipe errors (`std::io::ErrorKind::BrokenPipe`) are caught and cause a graceful exit with code `0`
- The `HiArgs` conversion phase (LowArgs -> HiArgs) performs cross-flag validation and reports conflicts as errors

### 8.8 Testing

**Unit tests**: Each flag in `defs.rs` has inline `#[test]` functions testing parsing behavior for positive, negative, and edge cases.

**Integration tests** (`tests/`): End-to-end tests that invoke `rg` as a subprocess and assert on stdout/stderr content:

```bash
# Run all tests
cargo test

# Run only integration tests
cargo test --test tests

# Run a specific test module
cargo test --test tests -- regression

# Run tests with PCRE2
cargo test --features pcre2
```

**Test infrastructure** (`tests/util.rs`): Provides a `Dir` builder that creates temporary directories with test files, runs `rg` against them, and asserts on output. The `rgtest!` macro (in `macros.rs`) simplifies test definitions.

**Fuzz testing**: The `fuzz/` directory contains a fuzzing target for `globset` glob parsing:

```bash
cargo install cargo-fuzz
cargo fuzz run fuzz_glob
```

### 8.9 CI Pipeline

The `ci/` directory contains CI support scripts:

| Script | Purpose |
|---|---|
| `ci/sha256-releases` | Generate SHA256 checksums for release artifacts |
| `ci/test-complete` | Validate that generated shell completion scripts parse correctly |
| `ci/ubuntu-install-packages` | Install build dependencies on Ubuntu CI runners (including PCRE2 headers) |
| `ci/utils.sh` | Shared CI utility functions (target detection, artifact naming) |

### 8.10 build.rs

The `build.rs` script reads two environment variables set by Cargo:

| Variable | Purpose |
|---|---|
| `CARGO_CFG_TARGET_OS` | Detects target OS for platform-specific conditional compilation |
| `CARGO_CFG_TARGET_ENV` | Detects target environment (e.g., `musl` vs `gnu`) for allocator selection |

The build script emits `cargo:rustc-cfg` directives that control conditional compilation in `main.rs` (e.g., jemalloc usage on musl).

---

## 9. Integration Points

### 9.1 As a Library

ripgrep's library crates are published to crates.io independently. The `grep` facade crate provides a single dependency that re-exports all `grep-*` crates:

```toml
[dependencies]
grep = "0.4"
```

For selective usage (smaller dependency tree):

```toml
[dependencies]
grep-searcher = "0.1"
grep-regex = "0.1"
grep-printer = "0.3"
```

The `ignore` and `globset` crates are particularly popular as standalone libraries:

```toml
[dependencies]
ignore = "0.4"    # gitignore-aware directory walking
globset = "0.4"   # high-performance glob matching
```

### 9.2 Editor Integration

ripgrep is widely integrated into code editors:

| Editor | Integration | Configuration |
|---|---|---|
| VS Code | Built-in (workspace search engine) | `search.useRipgrep` setting |
| Neovim | Native `grepprg` support | `:set grepprg=rg\ --vimgrep` |
| Emacs | `rg.el`, `counsel-rg`, `deadgrep` | Package-specific config |
| Sublime Text | Plugin ecosystem | Plugin-specific config |
| IntelliJ IDEA | Plugin available | Plugin-specific config |

The `--vimgrep` flag produces output compatible with vim's errorformat:

```
file.rs:10:5:matched text here
```

### 9.3 Shell Integration

**Pipe-friendly defaults**: When stdout is not a TTY, ripgrep automatically:
- Disables colors
- Disables headings
- Enables line numbers

**xargs integration**:

```bash
# NUL-separated output for safe filename handling
rg --files --null | xargs -0 wc -l
rg -l --null PATTERN | xargs -0 sed -i 's/old/new/g'
```

**fzf integration**:

```bash
# Interactive ripgrep with fzf preview
rg --line-number --color=always PATTERN | \
  fzf --ansi --preview 'bat --color=always {1} --highlight-line {2}'
```

### 9.4 JSON Output for Tooling

The `--json` output format enables programmatic integration:

```bash
# Count matches per file using jq
rg --json PATTERN | \
  jq -r 'select(.type == "end") | "\(.data.path.text): \(.data.stats.matches)"'

# Extract matched text only
rg --json PATTERN | \
  jq -r 'select(.type == "match") | .data.submatches[].match.text'

# Get file paths with matches
rg --json PATTERN | \
  jq -r 'select(.type == "begin") | .data.path.text'
```

### 9.5 Preprocessor Integration

The `--pre` flag enables arbitrary file preprocessing:

```bash
# Search inside PDF files using pdftotext
rg --pre pdftotext --pre-glob '*.pdf' PATTERN

# Search inside Word documents
rg --pre 'pandoc --to=plain' --pre-glob '*.docx' PATTERN

# Search inside SQLite databases
rg --pre 'sqlite3 -csv' --pre-glob '*.db' PATTERN
```

> [!IMPORTANT]
> The `--pre` command receives the file path as its first argument and must write the searchable text to stdout. It runs once per file, so this is significantly slower than direct file searching. Always use `--pre-glob` to limit preprocessing to specific file types.

### 9.6 Compressed File Search

ripgrep delegates decompression to external utilities via `grep-cli`'s `DecompressionReader`:

| Format | Extension | Decompressor Command |
|---|---|---|
| gzip | `.gz` | `gzip -d -c` |
| bzip2 | `.bz2` | `bzip2 -d -c` |
| xz | `.xz` | `xz -d -c` |
| lzma | `.lzma` | `xz --format=lzma -d -c` |
| lz4 | `.lz4` | `lz4 -d -c` |
| zstandard | `.zst` | `zstd -d -c` |
| brotli | `.br` | `brotli -d -c` |
| compress | `.Z` | `uncompress -c` |

```bash
# Search all compressed files in a directory
rg -z PATTERN /var/log/
```

> [!NOTE]
> Compressed file format detection uses file extensions, not content sniffing (see GitHub issue #3342). Files with incorrect or missing extensions will not be decompressed. Use `--pre` with a content-aware tool for extension-independent detection.

### 9.7 Known Issues and Workarounds

Sourced from the project's GitHub issue tracker:

| Issue | Description | Workaround |
|---|---|---|
| #3262 | `$F` treated as capture group in replacement despite `--fixed-strings` | Escape the `$` in the replacement string, or avoid `--replace` with `--fixed-strings` when replacement contains `$` |
| #3277 | Config file reported as not working | Verify `RIPGREP_CONFIG_PATH` is set and exported; use `--debug` to confirm config file loading |
| #3286 | Panic with walk builder min_depth/max_depth edge cases | Avoid setting `min_depth` greater than `max_depth` |
| #3309 | Regex error messages could be more descriptive | Use `--debug` for additional context on pattern compilation failures |
| #3342 | `--search-zip` uses file extension, not content detection | Rename files with correct extensions, or use `--pre` for content-based detection |
| #3364 | Unexpected output with `--multiline --pcre2 --json` combined | Avoid combining all three flags; use the default regex engine for multiline JSON output |

---

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