# ZiGrep — A fast, zero-libc grep alternative written in Zig 0.16

> Source: <https://ziggit.dev/t/zigrep-a-fast-zero-libc-grep-alternative-written-in-zig-0-16/18308#post_1>
> Published: 2026-11-11 02:05:26+00:00

ZiGrep is an open-source text search tool I’ve been building in Zig 0.16. It’s MIT-licensed and currently runs on Linux and Windows.

It actually started as an experiment. I wanted to see how far I could push filesystem traversal, SIMD scanning, and concurrency using Zig. One thing led to another, and eventually I started thinking about something a bit different: what would a search tool look like if it were designed for both developers and autonomous coding agents?

That’s the direction I’m exploring now.

On Linux, ZiGrep uses direct syscalls without relying on libc. On Windows, it runs natively through platform APIs, so there’s no need for WSL.

I’ve been experimenting with quite a few approaches, and some have worked better than others.

**Filesystem traversal:** Using Linux’s `getdents64` and `openat` directly to cut down on directory traversal overhead.

**Concurrency:** A work-stealing architecture for parallel searches, plus a zero-thread fast path when the directory tree is small enough that spawning workers would just add overhead.

**SIMD:** Vectorized literal matching with a rarest-byte strategy.

**Regex:** A Thompson NFA with lazy DFA caching, avoiding the catastrophic backtracking problem.

**Deterministic results:** I wanted parallel execution without unpredictable output ordering, so I’ve been working with sequence tickets and pruning to keep results ordered.

**Befunge-inspired traversal:** This one’s a little unusual. I’ve also been experimenting with filesystem navigation inspired by Befunge’s directional instructions. Mostly because I was curious whether the idea could be useful outside an esoteric language.

**`io_uring`:** There’s also an optional experimental Linux backend using native asynchronous I/O.

One thing I care about is being able to verify that the optimizations aren’t changing the actual search results. I’ve been running differential tests against GNU grep and ripgrep, along with conformance checks.

Making something fast is interesting, but making it fast while still returning the right results is the part that really matters to me.

Here are a few results from my Linux tests:

| Workload | ZiGrep | ripgrep | 
|---|---|---|
| 655 MB repository, literal search | 85.31 ms | 108.67 ms | 
| 655 MB repository, regex search | 95.63 ms | 120.33 ms | 
| 131 MB synthetic corpus | 47.57 ms | 37.93 ms | 

These are my own project benchmarks, not independent results. I ran them on a Linux machine with 12 CPU threads, using repeated and interleaved runs to make the comparisons more useful.

As you can see, ZiGrep isn’t faster in every case.

And that’s fine! I’m not trying to claim that I’ve somehow beaten ripgrep at everything. I’m more interested in figuring out *why* certain approaches perform better on some workloads and worse on others.

The slower cases are often just as interesting as the faster ones.

I’ve documented the methodology and more results in [PRUEBAS.md](https://github.com/DannyBaanks/ZiGrep/blob/main/PRUEBAS.md).

Lately, I’ve been thinking a lot about how coding agents interact with search tools.

Most search utilities are designed around a human reading the output. But an AI agent has different constraints. It might need structured results, predictable output sizes, or enough metadata to verify what it received without making several additional tool calls.

So I’m experimenting with a more agent-friendly interface: JSONL output, batched searches, explicit output budgets, and verifiable result metadata.

The question I’m trying to answer is pretty simple:

**Can a search tool designed specifically for agents help them complete more tasks correctly, using fewer tool calls, fewer tokens, and less time?**

I don’t have enough evidence to answer that yet. It’s a research direction, not a performance claim, and I want to test it properly against existing tools.

I’m also deliberately keeping natural-language interpretation outside ZiGrep. I don’t want the search engine itself guessing what the user meant. I’d rather have it remain a deterministic component that other systems can use.

**Zig 0.16.0**

I also want to be transparent about how I’m building this.

I use AI coding agents extensively. They help with implementation, debugging, reviews, and planning experiments.

My part is primarily the system architecture, figuring out what I want to explore, making design decisions, coordinating the agents, and checking whether the results actually hold up through testing.

So no, I’m not going to pretend I manually typed every line of code.

This is a project built through human-directed collaboration with AI, and I’m comfortable saying that openly.

I think being clear about that matters, especially when discussing technical results. Regardless of who wrote a particular piece of code, the behavior and performance claims still need to be tested and reproducible.

I’m still learning Zig, and that’s honestly a big part of why I’m sharing this.

I’d really appreciate feedback from people with more experience, especially around concurrency, filesystem traversal, SIMD, portability, and benchmarking.

If you spot something questionable in the design, a better way to approach a problem, or an experiment worth trying, I’d love to hear about it.

Thanks for checking it out!
