# Behavior traces — BurntSushi/ripgrep

> Canonical page: https://codevetter.com/unpack/ripgrep/behavior-traces

# Behavior traces — BurntSushi/ripgrep

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

Three flows dominate: startup/arg-parsing, a default recursive search, and the file-listing path. All of them funnel through `flags::parse()` → `HiArgs` and then diverge on `Mode`. The parallel search path is notable because parallelism lives entirely in the directory walker — `search_parallel` just hands a closure to `WalkParallel::run` and never manages threads itself. The indexed path currently degrades gracefully: `index::read` opens the index and then falls straight through to the ordinary exhaustive search.
- Startup order: `main` → `flags::parse()` → `parse_low()` which first calls `Logger::init()`, then `Parser::new().parse(env::args_os().skip(1), &mut low)`, then `set_log_levels(&low)` so `--trace` is live before config parsing. — [crates/core/flags/parse.rs#L48-L80](https://github.com/BurntSushi/ripgrep/blob/3fce3b5bb0236da2df6d99672afb8a719642eca7/crates/core/flags/parse.rs#L48-L80) [crates/core/logger.rs#L21-L28](https://github.com/BurntSushi/ripgrep/blob/3fce3b5bb0236da2df6d99672afb8a719642eca7/crates/core/logger.rs#L21-L28)
- If a config file yields arguments, the parser discards the first `LowArgs`, builds a fresh `LowArgs::default()`, re-parses `config_args ++ argv`, and re-runs `set_log_levels` because logging flags may have changed. — [crates/core/flags/parse.rs#L92-L108](https://github.com/BurntSushi/ripgrep/blob/3fce3b5bb0236da2df6d99672afb8a719642eca7/crates/core/flags/parse.rs#L92-L108)
- `Parser::new()` returns a `&'static Parser` memoized in a `OnceLock`, so the flag-name trie (`FlagMap` over short names, long names, aliases and negations) is built exactly once per process even though `lookup()` calls it repeatedly. — [crates/core/flags/parse.rs#L143-L172](https://github.com/BurntSushi/ripgrep/blob/3fce3b5bb0236da2df6d99672afb8a719642eca7/crates/core/flags/parse.rs#L143-L172)
- `HiArgs::from_low_args` begins by asserting `low.special == None` ("special mode demands short-circuiting"), which encodes the invariant that help/version never reach high-level conversion. — [crates/core/flags/hiargs.rs#L114-L120](https://github.com/BurntSushi/ripgrep/blob/3fce3b5bb0236da2df6d99672afb8a719642eca7/crates/core/flags/hiargs.rs#L114-L120)
- Default search trace: `run` → `search(args, mode)` → `args.walk_builder()?.build()` → `haystack_builder.build_from_result` → `args.sort(...)` → `args.search_worker(args.matcher()?, args.searcher()?, args.printer(mode, args.stdout()))` → loop `searcher.search(&haystack)`. — [crates/core/main.rs#L107-L152](https://github.com/BurntSushi/ripgrep/blob/3fce3b5bb0236da2df6d99672afb8a719642eca7/crates/core/main.rs#L107-L152)
- Inside one file's search: `SearchWorker::search` sets binary detection (explicit vs implicit) on the `Searcher`, then `search_path` dispatches on the `PatternMatcher` enum to the generic `search_path(m, searcher, printer, path)`, which calls `p.sink_with_path(&matcher, path)` and `searcher.search_path`. — [crates/core/search.rs#L236-L262](https://github.com/BurntSushi/ripgrep/blob/3fce3b5bb0236da2df6d99672afb8a719642eca7/crates/core/search.rs#L236-L262) [crates/core/search.rs#L318-L360](https://github.com/BurntSushi/ripgrep/blob/3fce3b5bb0236da2df6d99672afb8a719642eca7/crates/core/search.rs#L318-L360)
- `Searcher::search_path` → `search_file_maybe_path` first tries `self.config.mmap.open(file, path)` and searches the resulting slice; only if mmap is unavailable does it fall back to the incremental reader path. — [crates/searcher/src/searcher/mod.rs#L643-L700](https://github.com/BurntSushi/ripgrep/blob/3fce3b5bb0236da2df6d99672afb8a719642eca7/crates/searcher/src/searcher/mod.rs#L643-L700)
- The searcher has three internal strategies implemented in `glue.rs`: `ReadByLine` (streaming reader), `SliceByLine` (whole-slice, e.g. mmap) and `MultiLine` (when `--multiline` is on). — [crates/searcher/src/searcher/glue.rs#L11-L160](https://github.com/BurntSushi/ripgrep/blob/3fce3b5bb0236da2df6d99672afb8a719642eca7/crates/searcher/src/searcher/glue.rs#L11-L160)
- Parallel search trace: `search_parallel` creates a `BufferWriter`, an `AtomicBool` matched/searched pair and an optional `Mutex<Stats>`, then `args.walk_builder()?.build_parallel().run(|| Box::new(move |result| ...))` clones a `SearchWorker` per thread. — [crates/core/main.rs#L155-L200](https://github.com/BurntSushi/ripgrep/blob/3fce3b5bb0236da2df6d99672afb8a719642eca7/crates/core/main.rs#L155-L200) [crates/ignore/src/walk.rs#L1411-L1450](https://github.com/BurntSushi/ripgrep/blob/3fce3b5bb0236da2df6d99672afb8a719642eca7/crates/ignore/src/walk.rs#L1411-L1450)
- Early exit under `-q/--quiet` is implemented twice: the sequential loop `break`s when `matched && args.quit_after_match()`, and the parallel closure returns `WalkState::Quit`, which aborts the whole traversal. — [crates/core/main.rs#L138-L141](https://github.com/BurntSushi/ripgrep/blob/3fce3b5bb0236da2df6d99672afb8a719642eca7/crates/core/main.rs#L138-L141) [crates/core/main.rs#L206-L212](https://github.com/BurntSushi/ripgrep/blob/3fce3b5bb0236da2df6d99672afb8a719642eca7/crates/core/main.rs#L206-L212) [crates/core/flags/hiargs.rs#L697-L704](https://github.com/BurntSushi/ripgrep/blob/3fce3b5bb0236da2df6d99672afb8a719642eca7/crates/core/flags/hiargs.rs#L697-L704)
- Broken pipe is handled at three levels: inside the search loop (`break`), inside `bufwtr.print` (`WalkState::Quit`), and finally in `main`, which walks `err.chain()` for an `io::Error` of kind `BrokenPipe` and returns exit code 0. — [crates/core/main.rs#L43-L66](https://github.com/BurntSushi/ripgrep/blob/3fce3b5bb0236da2df6d99672afb8a719642eca7/crates/core/main.rs#L43-L66) [crates/core/main.rs#L128-L132](https://github.com/BurntSushi/ripgrep/blob/3fce3b5bb0236da2df6d99672afb8a719642eca7/crates/core/main.rs#L128-L132) [crates/core/main.rs#L196-L203](https://github.com/BurntSushi/ripgrep/blob/3fce3b5bb0236da2df6d99672afb8a719642eca7/crates/core/main.rs#L196-L203)
- Preprocessor trace: `search_preprocessor` builds `Command::new(bin).arg(path).stdin(Stdio::from(File::open(path)?))`, wraps it in a `CommandReader`, searches the reader, then calls `rdr.close()` so a non-zero exit code surfaces stderr as a Rust error. — [crates/core/search.rs#L285-L316](https://github.com/BurntSushi/ripgrep/blob/3fce3b5bb0236da2df6d99672afb8a719642eca7/crates/core/search.rs#L285-L316) [crates/cli/src/process.rs#L84-L135](https://github.com/BurntSushi/ripgrep/blob/3fce3b5bb0236da2df6d99672afb8a719642eca7/crates/cli/src/process.rs#L84-L135)
- Indexed search currently does no index-based pruning: `index::read` calls `args.index_read()?`, discards the handle into `let _index`, and then delegates to the ordinary `search`/`search_parallel` ("Do an exhaustive search for now"). — [crates/core/index/enabled.rs#L1-L16](https://github.com/BurntSushi/ripgrep/blob/3fce3b5bb0236da2df6d99672afb8a719642eca7/crates/core/index/enabled.rs#L1-L16)
- Index discovery trace: `IndexDiscovery::discover` checks `RIPGREP_INDEX_PATH` first, then walks `cwd.ancestors()` looking for a `.ripgrep` directory containing `index.db`, returning `None` when nothing is found. — [crates/index/src/index.rs#L104-L146](https://github.com/BurntSushi/ripgrep/blob/3fce3b5bb0236da2df6d99672afb8a719642eca7/crates/index/src/index.rs#L104-L146) [crates/core/flags/hiargs.rs#L936-L966](https://github.com/BurntSushi/ripgrep/blob/3fce3b5bb0236da2df6d99672afb8a719642eca7/crates/core/flags/hiargs.rs#L936-L966)
- Man page generation trace: `generate()` groups `FLAGS` by `doc_category()` into a `BTreeMap`, renders each flag's roff via `generate_flag`, then substitutes `!!VERSION!!` and per-category `!!name!!` placeholders in `template.rg.1`. — [crates/core/flags/doc/man.rs#L26-L60](https://github.com/BurntSushi/ripgrep/blob/3fce3b5bb0236da2df6d99672afb8a719642eca7/crates/core/flags/doc/man.rs#L26-L60) [crates/core/flags/doc/template.rg.1](https://github.com/BurntSushi/ripgrep/blob/3fce3b5bb0236da2df6d99672afb8a719642eca7/crates/core/flags/doc/template.rg.1)

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)
