Scout, ripgrep, and GNU grep measured

Scout answers searches that text search cannot. Type part of a file name you half remember, and the file comes back. Ask in plain English — “where request retries are limited” — and Scout finds the code even when it uses none of those words. Describe the shape of the code you want, and Scout matches the shape rather than the characters, so a comment that happens to say the same thing is not a hit.

It also does ordinary text search, and the tables below show how that compares with ripgrep and GNU grep on two real repositories.

Searches only Scout can run

Search typeWhat you askScout
dotnet/runtime · Fuzzy file discovery Finds the file even when you only remember part of its name.httpclientfactory 14.3 ms
dotnet/runtime · Code shape Matches how the code is written, not just the text. $$$ stands for “any arguments”, so this one finds every throw of that exception however it was constructed — and skips the same words inside a comment or a string.throw new ArgumentNullException($$$) 13.5 s
dotnet/runtime · Symbol outline Lists declarations: names, kinds, and where they live.HttpClient 2.2 s
dotnet/runtime · Semantic Ask in plain English; finds code that says it in different words.“where request retries are limited” 628 ms
dotnet/runtime · Semantic Ask in plain English; finds code that says it in different words.“cancellation token propagation through async streams” 622 ms
Private monorepo · Fuzzy file discovery Finds the file even when you only remember part of its name.httpclientfactory 16.4 ms
Private monorepo · Code shape Matches how the code is written, not just the text. $$$ stands for “any arguments”, so this one finds every throw of that exception however it was constructed — and skips the same words inside a comment or a string.throw new ArgumentNullException($$$) 4.2 s
Private monorepo · Symbol outline Lists declarations: names, kinds, and where they live.HttpClient 1.3 s
Private monorepo · Semantic Ask in plain English; finds code that says it in different words.“where request retries are limited” 437 ms
Private monorepo · Semantic Ask in plain English; finds code that says it in different words.“cancellation token propagation through async streams” 418 ms
  • Semantic search needs a one-time setup (start Scout with --semantic); the cost is in the table below.
  • The code-shape and symbol-outline searches read every file Scout has a grammar for, which needed limits.find-budget-ms and limits.structural-parse-cap raised above the shipped default. Out of the box the same search stops earlier and reports how far it got. The other rows in this table ran on the shipped limits: neither limit bounds a fuzzy or a semantic search.

Text search speed — dotnet/runtime

59,319 files, 30,172 of them C#. All three tools read every file. Each number is the median of 10 runs.

SearchScoutripgrepGNU grepMatching lines
Literal, common
public static
372 ms 788 ms 17.2 s 165,310
Literal, rare
ConfiguredCancelableAsyncEnumerable
347 ms 764 ms 17.0 s 33
Regex
async Task<\w+>
407 ms 778 ms 17.0 s 774
Word boundary
Dispose
354 ms 778 ms 17.5 s 10,965
Case-insensitive literal
httpclient
342 ms 752 ms 17.3 s 3,181

Text search speed — a private company repository

46,466 files, 22,381 of them C#. All three tools read every file. Each number is the median of 10 runs.

SearchScoutripgrepGNU grepMatching lines
Literal, common
public static
257 ms 692 ms 12.9 s 13,390
Literal, rare
TaskCompletionSource
250 ms 636 ms 12.9 s 8
Regex
async Task<\w+>
279 ms 643 ms 12.9 s 543
Word boundary
Dispose
260 ms 653 ms 13.2 s 553
Case-insensitive literal
httpclient
380 ms 945 ms 22.8 s 377

What the index costs

Scout pays these once per repository. ripgrep and grep pay nothing up front, but pay the full search cost on every single call.

RepositoryIndex ready inSemantic setupFirst-ever searchMemory
dotnet/runtime 2.2 s 9.9 h 2.6 s 175 MB (6241 MB with semantic on)
Private monorepo This repository already had its index built, so the one-time costs were not measured again. 114 MB (1416 MB with semantic on)
  • Index ready in = start Scout in a repository it has never seen, and wait until search fully works.
  • First-ever search = the very first search in that fresh repository, including startup and index building. Every search after it uses the warm numbers above.
  • Semantic setup is the slow one: Scout downloads a model once, then reads through the whole repository. 0.87 GB of code took 9.9 hours (about 88 MB per hour). Plan from your own repository size. Until it finishes, semantic questions are answered by plain text search instead.

How many searches before the index pays for itself

Build the index once, and every later search is cheaper. This is how many searches it takes until that one-time cost has paid off against ripgrep.

QueryBreak-evenScout per queryripgrep per query
dotnet/runtime · Literal, common 6 searches 372 ms 788 ms
dotnet/runtime · Literal, rare 6 searches 347 ms 764 ms
dotnet/runtime · Regex 6 searches 407 ms 778 ms
dotnet/runtime · Word boundary 6 searches 354 ms 778 ms
dotnet/runtime · Case-insensitive literal 6 searches 342 ms 752 ms
  • Simple math from the numbers above: index build time divided by the time saved per search. Rows where ripgrep is faster per search never pay off, and say so.

Do Scout and ripgrep find the same things?

A speed comparison is worth nothing if the two tools return different results. Before timing anything, every shared search was run through both and the matching lines compared.

SearchResult
dotnet/runtime · Literal, common Same total — 165,315 matches counted by both, on 165,310 lines
dotnet/runtime · Literal, rare Identical — 33 matching lines in both
dotnet/runtime · Regex Identical — 774 matching lines in both
dotnet/runtime · Word boundary Same total — 11,073 matches counted by both, on 10,965 lines
dotnet/runtime · Case-insensitive literal Identical — 3,181 matching lines in both
Private monorepo · Literal, common Same total — 13,390 matches counted by both, on 13,390 lines
Private monorepo · Literal, rare Identical — 8 matching lines in both
Private monorepo · Regex Identical — 543 matching lines in both
Private monorepo · Word boundary Identical — 553 matching lines in both
Private monorepo · Case-insensitive literal Identical — 377 matching lines in both
  • One catch on Windows: ripgrep reads .gitignore case-sensitively, git itself usually does not, and Scout follows git. On one repository here that difference was 1,753 files (restored NuGet packages nobody tracks) that ripgrep would have searched and Scout correctly skips. We removed them from ripgrep's side too, so both tools searched exactly the same files.

Environment

  • Machine: AMD Ryzen 9 9955HX 16-Core Processor, 32 logical cores, 62 GB RAM, Windows_NT 10.0.26200.
  • Versions: scout 2.1.0, ripgrep 15.2.0 (rev e89fff89ac), grep (GNU grep) 3.0, Node v24.19.0.
  • Scout flags: --no-semantic --no-telemetry for the comparison battery, --semantic --no-telemetry for the semantic rows. Find budget 120000 ms, page size 200.
  • Repositories: dotnet/runtime v9.0.0 (59,319 files); a private company C# monorepo (46,466 files).
  • Measured: 2026-08-23 on scout 2.1.0. The semantic rows and the semantic setup cost are carried over from 2026-08-21 and 2026-08-22 on scout 2.0.0 — that tier is untouched by the changes the rest was re-measured for.

Raw results

The fine print

  • Scout was faster than ripgrep on every text search here — 10 of 10, by 1.9–2.7x.
  • The very first search in a new repository is slow, because the index has to be built first. Every search after that uses the fast numbers above.
  • Fuzzy and semantic search return the best matches, not every match. Text, structural, and symbol search read every file they are given, and each says so when it could not finish.
  • Not measured yet: how fast the index updates after edits, how speed scales with repository size, and how good the ranked results are.
↑/↓ NavigateEnter OpenSpace Expand