# Data flow — BurntSushi/ripgrep

> Canonical page: https://codevetter.com/unpack/ripgrep/data-flow

# Data flow — BurntSushi/ripgrep

Scanned commit 3fce3b5bb0236da2df6d99672afb8a719642eca7 (2026-08-04). Generated by codevetter codevetter 1.12.0 on 2026-09-22.

Input enters at three boundaries: `std::env::args_os()`, an optional rc file named by `RIPGREP_CONFIG_PATH`, and stdin (patterns via `-f -`, or the haystack itself). The parser folds all of these into a flat, dumb `LowArgs` struct through `Flag::update`, then `HiArgs::from_low_args` performs all the "expensive" derivations — compiling globs, building the type matcher, resolving the CWD and hostname, choosing thread count and mmap strategy. `HiArgs` is the single state owner for the rest of the process; every downstream object (`ignore::WalkBuilder`, `grep::searcher::Searcher`, the matcher, the printer, the `SearchWorker`) is constructed from it by a dedicated accessor. Bytes then flow file → `Searcher` → `Sink` → printer → `termcolor` writer, either directly to stdout (single-threaded) or into per-thread `termcolor::Buffer`s flushed by a `BufferWriter` (parallel). Exit status is a fourth output channel, driven by a match flag plus a global `ERRORED` atomic.
- Config args are read from the file named by `RIPGREP_CONFIG_PATH`, one shell argument per line with `#` comments and blank lines skipped, then **prepended** to `std::env::args_os().skip(1)` and the whole CLI is re-parsed from scratch. — [crates/core/flags/config.rs#L15-L52](https://github.com/BurntSushi/ripgrep/blob/3fce3b5bb0236da2df6d99672afb8a719642eca7/crates/core/flags/config.rs#L15-L52) [crates/core/flags/config.rs#L78-L106](https://github.com/BurntSushi/ripgrep/blob/3fce3b5bb0236da2df6d99672afb8a719642eca7/crates/core/flags/config.rs#L78-L106) [crates/core/flags/parse.rs#L88-L108](https://github.com/BurntSushi/ripgrep/blob/3fce3b5bb0236da2df6d99672afb8a719642eca7/crates/core/flags/parse.rs#L88-L108)
- `--no-config` short-circuits before the config file is read, and `-h`/`-V` short-circuit even earlier via `ParseResult::Special`, so help output never depends on the config file or the CWD. — [crates/core/flags/parse.rs#L74-L92](https://github.com/BurntSushi/ripgrep/blob/3fce3b5bb0236da2df6d99672afb8a719642eca7/crates/core/flags/parse.rs#L74-L92) [crates/core/main.rs#L349-L366](https://github.com/BurntSushi/ripgrep/blob/3fce3b5bb0236da2df6d99672afb8a719642eca7/crates/core/main.rs#L349-L366)
- Each flag writes into `LowArgs` — a flat struct of ~60 public(crate) fields — via `Flag::update(FlagValue, &mut LowArgs)`, and by convention `update` only validates, deferring side effects (e.g. resolving `--hostname-bin`) to the high-level stage. — [crates/core/flags/lowargs.rs#L33-L60](https://github.com/BurntSushi/ripgrep/blob/3fce3b5bb0236da2df6d99672afb8a719642eca7/crates/core/flags/lowargs.rs#L33-L60) [crates/core/flags/mod.rs#L152-L177](https://github.com/BurntSushi/ripgrep/blob/3fce3b5bb0236da2df6d99672afb8a719642eca7/crates/core/flags/mod.rs#L152-L177)
- Patterns are drained from `LowArgs` by `Patterns::from_low_args`, which promotes the first positional to a pattern only when neither `-e` nor `-f` was given, reads `-f -` through `grep::cli::patterns_from_stdin()`, and de-duplicates patterns to avoid pathological regex compile costs. — [crates/core/flags/hiargs.rs#L1016-L1084](https://github.com/BurntSushi/ripgrep/blob/3fce3b5bb0236da2df6d99672afb8a719642eca7/crates/core/flags/hiargs.rs#L1016-L1084)
- `Paths::from_low_args` runs after patterns so all remaining positionals are paths; with none given it uses `grep::cli::is_readable_stdin()` as a heuristic to choose between searching `./` and searching `-` (stdin), and errors if stdin would be consumed twice. — [crates/core/flags/hiargs.rs#L1105-L1172](https://github.com/BurntSushi/ripgrep/blob/3fce3b5bb0236da2df6d99672afb8a719642eca7/crates/core/flags/hiargs.rs#L1105-L1172)
- `State` tracks one-shot derived facts across the low→high conversion, notably `stdin_consumed`, which is what makes the double-stdin error and the CWD heuristic consistent. — [crates/core/flags/hiargs.rs#L968-L1002](https://github.com/BurntSushi/ripgrep/blob/3fce3b5bb0236da2df6d99672afb8a719642eca7/crates/core/flags/hiargs.rs#L968-L1002) [crates/core/flags/hiargs.rs#L1113-L1122](https://github.com/BurntSushi/ripgrep/blob/3fce3b5bb0236da2df6d99672afb8a719642eca7/crates/core/flags/hiargs.rs#L1113-L1122)
- Thread count is derived once in `from_low_args`: forced to 1 when `--sort` is set or only one file is searched, else `--threads`, else `available_parallelism()` capped at 12. — [crates/core/flags/hiargs.rs#L178-L185](https://github.com/BurntSushi/ripgrep/blob/3fce3b5bb0236da2df6d99672afb8a719642eca7/crates/core/flags/hiargs.rs#L178-L185)
- Memory-map policy is decided from the path set: `MmapMode::Auto` only enables mmap when ≤10 paths are given and all of them are files; otherwise `MmapChoice::never()`. — [crates/core/flags/hiargs.rs#L232-L259](https://github.com/BurntSushi/ripgrep/blob/3fce3b5bb0236da2df6d99672afb8a719642eca7/crates/core/flags/hiargs.rs#L232-L259) [crates/searcher/src/searcher/mmap.rs#L49-L90](https://github.com/BurntSushi/ripgrep/blob/3fce3b5bb0236da2df6d99672afb8a719642eca7/crates/searcher/src/searcher/mmap.rs#L49-L90)
- Traversal output is `Result<ignore::DirEntry, ignore::Error>`, converted by `HaystackBuilder::build_from_result` into `Option<Haystack>`; errors are reported through `err_message!` and non-file, non-explicit entries are dropped with a debug log. — [crates/core/haystack.rs#L26-L80](https://github.com/BurntSushi/ripgrep/blob/3fce3b5bb0236da2df6d99672afb8a719642eca7/crates/core/haystack.rs#L26-L80) [crates/core/main.rs#L112-L118](https://github.com/BurntSushi/ripgrep/blob/3fce3b5bb0236da2df6d99672afb8a719642eca7/crates/core/main.rs#L112-L118)
- `SearchWorker::search` selects among four data sources per haystack in priority order: stdin lock, preprocessor subprocess, decompression subprocess, then direct `search_path`. — [crates/core/search.rs#L236-L262](https://github.com/BurntSushi/ripgrep/blob/3fce3b5bb0236da2df6d99672afb8a719642eca7/crates/core/search.rs#L236-L262)
- Search results reach printers only through the `Sink` trait (`matched`, `context`, `context_break`, `binary_data`, `begin`, `finish`); `search_path`/`search_reader` build a `sink_with_path` per printer variant and harvest `has_match()` and `stats()` from it. — [crates/searcher/src/sink.rs#L102-L228](https://github.com/BurntSushi/ripgrep/blob/3fce3b5bb0236da2df6d99672afb8a719642eca7/crates/searcher/src/sink.rs#L102-L228) [crates/core/search.rs#L358-L400](https://github.com/BurntSushi/ripgrep/blob/3fce3b5bb0236da2df6d99672afb8a719642eca7/crates/core/search.rs#L358-L400)
- In parallel mode each worker owns a cloned `SearchWorker` writing into its own `termcolor::Buffer`; the buffer is cleared before each file and printed atomically via `bufwtr.print(...)` to avoid interleaving. — [crates/core/main.rs#L155-L215](https://github.com/BurntSushi/ripgrep/blob/3fce3b5bb0236da2df6d99672afb8a719642eca7/crates/core/main.rs#L155-L215) [crates/core/flags/hiargs.rs#L342-L358](https://github.com/BurntSushi/ripgrep/blob/3fce3b5bb0236da2df6d99672afb8a719642eca7/crates/core/flags/hiargs.rs#L342-L358)
- In `--files` parallel mode output is funneled through an `mpsc::channel::<Haystack>` to a single dedicated printing thread, deliberately in place of a mutex. — [crates/core/main.rs#L255-L303](https://github.com/BurntSushi/ripgrep/blob/3fce3b5bb0236da2df6d99672afb8a719642eca7/crates/core/main.rs#L255-L303)
- Exit status is computed from two independent channels: the boolean `matched` returned by the mode function and the process-global `ERRORED` atomic flipped by `err_message!`, yielding 0/1/2. — [crates/core/main.rs#L99-L105](https://github.com/BurntSushi/ripgrep/blob/3fce3b5bb0236da2df6d99672afb8a719642eca7/crates/core/main.rs#L99-L105) [crates/core/messages.rs#L18-L26](https://github.com/BurntSushi/ripgrep/blob/3fce3b5bb0236da2df6d99672afb8a719642eca7/crates/core/messages.rs#L18-L26)

Every claim links to its cited files at the pinned commit. Citations identify source evidence; they do not establish runtime correctness. Independent CodeVetter scan — not reviewed by upstream maintainers.

## Public product links

- [CodeVetter](https://codevetter.com/)
- [Download](https://codevetter.com/download)
- [Documentation](https://codevetter.com/docs/)
- [Source](https://github.com/Codevetter/codevetter)
