Literal grep in pure Zig

Ripgrep speed, one static binary, zero excuses.

Recursive search scans every byte on every query. ziggygrep cuts the cost per byte instead of indexing around it. First byte prefilter skips what cannot match, line bounding runs on verified hits only. Output matches rg -F on all 7 test patterns.

Free MIT · 656 KB Windows · 326 KB Linux · 22/22 benches at or below rg

ziggygrep bench console
$ ziggygrep HashMap . > /dev/null
200 files / 53 MB · median of 9
ziggygrep 37ms · rg 40ms · delta -3ms
$ ziggygrep x . > /dev/null
ziggygrep 66ms · rg 105ms · delta -39ms
$ ziggygrep ZZZNOMATCHXYZ . > /dev/null
ziggygrep 24ms · rg 24ms · tie
22/22 at or below rgbyte identical on 7/7 patternsrerun: tools/normcmp.py

Why it earns a slot

Less work per byte, not work avoided.

No index to build, no daemon to feed. Each stage removes cost that regex pipelines pay on every file.

Measured bench

Every cell is ziggygrep ms vs rg ms.

200 file 53 MB Rust corpus, ReleaseFast x86_64-v3, stdout piped to null, median of 9. Baseline rg 15.2.0 --no-config -F --no-heading --line-number.

he 112051/112051 HashMap 112426/112426 e 561539/561539 in, pub fn, x, fn 600000/600000
PatternFull-c-l
he38 vs 4428 vs 3517 vs 21
in85 vs 9640 vs 5517 vs 20
HashMap37 vs 4033 vs 4316 vs 20
pub fn66 vs 9233 vs 5415 vs 23
x66 vs 10533 vs 5119 vs 20
fn79 vs 11038 vs 5515 vs 20
e87 vs 10231 vs 4815 vs 18
miss24 vs 24 tie--

GNU grep spot check on the same box: miss 128.7ms vs 17.9ms, HashMap 46.5ms vs 25.8ms. Speedups are ratios of medians on that fixture; your disk and cache shape your numbers.

Internals

Three stages, zero wasted bytes.

01

Prefilter, then confirm

Vector first byte scan skips 32 bytes per step. Line bounding runs on verified hits only. Same line hits dedupe, finished lines jump past.

02

Batch steal, sorted merge

Atomic index hands out fixed batches. Each worker owns scratch, carry, and chunk buffers. Merge sorts by file for deterministic output.

03

Buffer, then one flush

Headers built on the stack, written once. Pipes cap transport at 60 KB chunks. No mmap, flat memory, pipe safe.

Quickstart

One clone, one build, first hit in a minute.

Needs Zig 0.16.0 only. No packages, no services, no accounts.

git clone https://github.com/AkashPriyadarshii/ziggygrep.git
cd ziggygrep
zig build -Doptimize=ReleaseFast
./zig-out/bin/ziggygrep HashMap .
  1. Search one pattern
    Run ziggygrep TODO src/main.zig. Matches print as path:lineno:line.
  2. Count or list
    Run ziggygrep -c HashMap . for counts, ziggygrep -l fn . for file names.
  3. Pipe it
    No paths means stdin. Exit 0 match, 1 no match, 2 error. Alias zgg if you type it daily.

Limits

What it refuses to be.

Ecosystem

Same author, same bar.

TOOL AUTHOR

Akash Priyadarshi

Patna, Bihar, India

Builds fast single purpose CLI tools in Zig and Rust. ziggygrep is the literal search half; archived rustygrep keeps the regex, JSON, and MCP server modes.