tgrep
Trigram-indexed grep with a client/server architecture for fast regex search in large codebases.
tgrep is integrated into GitHub Copilot CLI to power fast grep searches across large repositories.
Quick start
Install tgrep, then start a server:
tgrep serve . # builds the index if needed; runs in the foreground
In another terminal:
tgrep -- "fn main" . # automatically connects to the server
tgrep status . # show indexing and refresh status
Without a server, run tgrep index . to build an on-disk index. Searches use
the server when available, then the local index, or scan the filesystem if no
usable index exists. Indexes are stored in .tgrep/ by default; add this
directory to .gitignore.
Indexes can lag filesystem changes. The server updates asynchronously;
without a server, rerun tgrep index . after changes. Use --no-index when a
search must read the current files. Queries scan during an initial build until
complete coverage is available.
For coding agents, see AGENTS.md. To install MCP search tools and
startup hooks for Codex or pi, run bash install-agent.sh from this checkout
(Linux/macOS, Python 3.11+). See the
agent integration guide.
Performance
A trigram index narrows each query to files that could match, then verifies those files with the regex engine in parallel. Patterns without useful trigrams may still require searching every indexed file.
In the August 24, 2026 benchmark sweep, tgrep was faster than ripgrep in 17 of 18 repo/platform combinations, with speedups from 0.93x to 51.9x. These measure client/server search latency with the index already built, not indexing time. Results depend on the query, repository, storage, and match volume. See BENCHMARKS.md for measurements and methodology.
Usage
Build the index
tgrep index . # index current directory
tgrep index /path/to/repo # index a specific repo
tgrep index . --index-path /tmp/idx # custom index location
tgrep index . --exclude vendor --exclude third_party # skip directories
Each build reports elapsed time and, where available, peak memory:
Index built successfully at /tmp/idx
Indexed in 22.6s using external strategy (peak memory 160.1 MiB)
Windows reports peak private committed bytes; Linux samples anonymous resident memory. Both exclude file-backed mappings and report the working set separately when it is substantially larger. macOS reports resident memory instead.
Repositories without a .git directory
Like ripgrep, tgrep applies .gitignore only inside a Git repository. It warns
when a root .gitignore is present but not applied. Use --no-require-git on
indexing, serving, and searching to apply those rules outside Git:
tgrep index . --no-require-git
tgrep serve . --no-require-git
tgrep --no-require-git -- "pattern" .
Case-insensitive repositories
When Git's core.ignorecase is enabled, tgrep applies an additional
case-insensitive exclusion pass for the repository's root .gitignore and
.git/info/exclude. Git-tracked paths are exempt from this additional pass,
but not from ordinary traversal, binary, or size filtering.
Nested .gitignore files and global ignore rules do not get this additional
pass. --no-ignore disables it along with the normal ignore rules.
Keep index and serve flags in step
Use the same --no-require-git, --no-ignore, --max-filesize (or
--no-max-filesize), and --exclude settings for index and serve.
Startup reconciliation removes indexed files excluded by the server's current
settings. For example, serving an uncapped index with --max-filesize 8M
removes files larger than 8 MiB from that index.
Pass the same size policy, --no-require-git, and any custom --index-path
to searches too. --exclude is o