microsoft/tgrep: trigram-indexed grep with a client/server split
Trigram-indexed grep with a client/server architecture for fast regex search in large codebases locally
At a glance
- What is it?
- tgrep builds a trigram index over a repository and keeps a server watching for changes, so repeated regex searches touch only candidate files. It is a Rust workspace from Microsoft, MIT licensed, and it is already used inside GitHub Copilot CLI.
- Who is it for?
- Adopt tgrep when you search the same large checkout many times a day and can afford to keep a server process running; the README's own numbers show the margin is smallest on Linux and on queries that return tens of thousands of matches. Do not adopt it for one-off searches in small directories, for repositories where you cannot write an index, or on a platform where you cannot build the Rust workspace.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 2 days ago.
- What is it written in?
- Mainly Rust, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 23, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
The problem tgrep targets: grep rescans, tgrep precomputes
Classic grep and ripgrep read every file on every query. The README states the cost plainly: O(total bytes) per query. In a monorepo with 100k or more files, that means each search pays the same price as the first one, no matter how narrow the pattern is.
tgrep takes the opposite position. It pre-builds a trigram index, so a query only touches the small set of files that could possibly contain a match. The README's summary of the workflow is a single line: start a server once, search instantly forever.
The audience is narrow and specific. This is for people who run regex searches repeatedly against the same large checkout, and for tooling that does so on a user's behalf. The README says tgrep is integrated into GitHub Copilot CLI to power fast grep searches across large repositories, which tells you the primary consumer is an agent issuing many queries in sequence rather than a human typing one search and walking away.
HybridIndex, LiveIndex and the flush cycle
The architecture diagram in the README shows a client talking to `tgrep serve` over TCP, and the server owning a HybridIndex. That hybrid is two layers: an IndexReader mmap'd from disk, and a LiveIndex held in memory.
The IndexReader is zero-copy and does a binary search over a sorted trigram lookup table. The LiveIndex is an overlay for files modified after the server started, or files the background indexer is still working through. When the two disagree, the overlay wins.
Freshness comes from the `notify` crate. Native subscriptions update LiveIndex in real time when they are available; if registration fails or a budget is exhausted, the server falls back to polling. The README does not state the polling interval.
Memory is bounded by a flush policy: every 50,000 files or 5 minutes, whichever comes first, the in-memory index is written to disk and the reader is swapped. The background indexer builds in parallel batches of 1,024 files, with extra splitting by byte size; resumed partial indexes use batches of 500. Queries work during the build, falling back to filesystem scans until the index is ready.
The transport is JSON-RPC 2.0 over newline-delimited TCP, one thread per connection, so several clients can be connected at once. A 50,000-entry content cache behind an RwLock serves concurrent reads without contention.
Installing tgrep and running a first indexed search
The repository is a Cargo workspace with two members, `tgrep-core` and `tgrep-cli`, at version 1.0.10 and edition 2024. The Makefile is the shortest path to a working binary: `make install` depends on `make release`, then copies `target/release/tgrep` into `~/.cargo/bin/tgrep`.
make installIf you would rather drive Cargo directly, the equivalent is a release build of the workspace followed by a copy into your Cargo bin directory.
cargo build --workspace --release
cp target/release/tgrep ~/.cargo/bin/tgrepWith the binary on your path, the README's three-line workflow is the first real use. `tgrep index .` builds the trigram index for the current directory, `tgrep serve .` starts the server and watches for file changes, and `tgrep "fn main" .` runs the search. The README notes that the search auto-connects to a running server.
tgrep index .
tgrep serve .
tgrep "fn main" .When a build finishes, tgrep prints elapsed time and peak memory. The README's example output is `Indexed in 22.6s using external strategy (peak memory 160.1 MiB)`. That figure counts private and committed bytes, not resident set, because mapped pages are file-backed and reclaimable. When the working set is much larger, the output names it too, as in `peak memory 77.8 MiB private, 1.99 GiB working set incl. memory-mapped files`.
For indexing a specific tree or excluding directories, the README gives these forms.
tgrep index /path/to/repo
tgrep index . --index-path /tmp/idx
tgrep index . --exclude vendor --exclude third_partyOne more install path exists for agent users. From a checkout, `bash install-agent.sh` installs MCP search tools and startup hooks for Codex or pi, and the agent integration guide under `scripts/agent/` covers install, doctor, repair and uninstall. That script requires Linux or macOS and Python 3.11 or newer.
Where tgrep loses, and where it is the wrong tool
The README does not claim a clean sweep, and that honesty is worth reading carefully. Across the 18 measured cells, tgrep wins 17. The exception is Kubernetes on Linux, described as a near-tie at 0.93x. The README also gives the reason the margin moves: the speedup depends on repository size and on how many matches a query returns. A search returning tens of thousands of matches spends more time delivering them than the index saves on finding them.
The Linux column is the weakest overall. On gecko-dev the measured speedup is 7.36x on Linux against 51.9x on macOS arm64. On chromium it is 3.81x on Linux against 15.8x on macOS arm64. If your work happens on Linux, the numbers you should expect are the smaller ones.
Three concrete constraints matter more than the benchmarks. First, `.gitignore` files only take effect inside a git repository, and this matches ripgrep. Index a Perforce, Source Depot or plain-directory enlistment and the root `.gitignore` is read by nothing. The only symptom is an index far larger than expected. tgrep prints a warning in that case, but the warning is the whole safety net.
Second, there is a 64 MiB size cap applied to both indexing and searching, and extension-based binary rejection covers more than 50 formats alongside an 8KB content check. Files above the cap are outside the index unless you pass `--no-max-filesize`, and removing the cap changes the memory profile the README is careful about.
Third, the design assumes a long-lived process. The README's pitch is start a server once, search instantly forever. If your usage is one search in a directory you will never revisit, the index build is pure overhead, and grep or ripgrep will be faster in wall-clock terms because they skip the setup entirely.
How tgrep differs from ripgrep and from an IDE index
ripgrep is the comparison the README itself makes, and the difference is architectural rather than a matter of tuning. ripgrep is a single process that walks the tree and reads files on demand. It holds no state between invocations, which is why it starts instantly and why its cost scales with the size of the tree on every run. tgrep splits the work into a client and a server, pays a one-time indexing cost, and then answers from a precomputed trigram lookup table.
That trade has a shape. ripgrep is always available, has no daemon to manage, and behaves identically whether you run it once or a thousand times. tgrep is faster only after the index exists and only while the server is running. The README's own framing puts the index build at 22.6 seconds in one example, which is a real cost before any query returns.
The second comparison is to editor and IDE search, which also maintains an index. Those indexes are scoped to a project the editor has open and are not reachable from a shell or from another process. tgrep's TCP server with JSON-RPC 2.0 is reachable by any client that speaks the protocol, and the README says multiple clients can connect simultaneously. That is what makes it usable by an agent that is not an editor.
Licence, releases and what maintenance costs you
The workspace declares `license = "MIT"` in `Cargo.toml`, and the repository carries a LICENSE file at the top level. MIT is permissive: it allows use, modification and redistribution with the licence text retained. This is a statement of what the files say, not legal advice; if you redistribute tgrep inside a product, read the LICENSE file yourself.
The version is 1.0.10, set once in `[workspace.package]` and inherited by both members, so the CLI and the core library move together. Recent releases are close together: v1.0.8 on 2026-09-12, v1.0.9 on 2026-09-18, and v1.0.10 on 2026-09-21. The last push to the repository was on 2026-09-21.
Upgrade cost is mostly the index format. The README does not document index compatibility across versions, and it does not document a migration command. The practical consequence is that a version bump may mean rebuilding the index, which the README's own example puts at tens of seconds for a large tree. The Makefile's `clean` target removes `.tgrep/` alongside `cargo clean`, which suggests the index lives in a `.tgrep` directory by default when no `--index-path` is given.
Running a server also means running a process. The client auto-connects to a running server, and the README does not document rollback or what happens when the server is stopped mid-query. Plan for the server being a piece of infrastructure you start, not a command you invoke.
Editorial conclusion
Adopt tgrep when you search the same large checkout many times a day and can afford to keep a server process running; the README's own numbers show the margin is smallest on Linux and on queries that return tens of thousands of matches. Do not adopt it for one-off searches in small directories, for repositories where you cannot write an index, or on a platform where you cannot build the Rust workspace. Before committing, verify these three things on your own tree: that `tgrep index` finishes in an acceptable time and peak memory on your largest repository, that a `.gitignore` outside a git repository does not silently inflate the index, and that the 64 MiB file size cap does not exclude files you need to search.
Frequently asked questions
How do I install microsoft/tgrep?
Clone the repository and run `make install`, which builds the workspace in release mode and copies `target/release/tgrep` into `~/.cargo/bin/tgrep`. You can also run `cargo build --workspace --release` and copy the binary yourself. Agent users on Linux or macOS with Python 3.11 or newer can run `bash install-agent.sh` from the checkout.
Does microsoft/tgrep replace ripgrep?
Not universally. The README reports tgrep winning 17 of 18 measured cells, with Kubernetes on Linux a near-tie at 0.93x, and notes the margin depends on repository size and on how many matches a query returns. ripgrep has no index to build and no server to run, so it stays the simpler choice for one-off searches.
Why is my tgrep index much larger than expected?
The README warns that `.gitignore` files only take effect inside a git repository, matching ripgrep. If you index a Perforce, Source Depot or plain-directory enlistment, the root `.gitignore` is not applied and the only symptom is an oversized index. tgrep prints a warning when it detects a `.gitignore` outside a git repository.
What is the file size limit in microsoft/tgrep?
There is a 64 MiB size cap applied to both indexing and searching, alongside extension-based binary rejection covering more than 50 formats and an 8KB content check. The README states that `--no-max-filesize` removes the cap.
Is microsoft/tgrep already used in production tooling?
The README states that tgrep is integrated into GitHub Copilot CLI to power fast grep searches across large repositories. That is the only deployment the repository documents.
Community notes