hgrep prints grep matches as syntax-highlighted code blocks
Grep with human-friendly search results
At a glance
- What is it?
- hgrep is a MIT licensed Rust tool that searches files and prints the matched regions with syntax highlighting, so results read like the code search on GitHub rather than a list of line numbers. It can use its own ripgrep-based search or read grep and rg output from stdin, and it ships two printers, one built on syntect and one on bat.
- Who is it for?
- Adopt hgrep if you read search results as code rather than as line numbers, since the highlighted snippets remove the step of opening each hit in an editor. Skip it if you are scripting in a pipeline where the machine-readable grep output matters more than the display, since piping through hgrep changes the format.
- 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 99 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 October 20, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The idea: grep output with the code around it
hgrep is a grep tool to search files with a given pattern and print the matched code snippets with human-friendly syntax highlighting, and the README says plainly that it brings search results like the code search on GitHub to your local machine. The framing is that it is something like searching files with ripgrep and showing results with bat. Mechanically it is closest to the -C option of the grep command, so hgrep is useful to survey matches with context around them. The difference from grep -C is in how the context is chosen. When some matches are near enough, hgrep prints the lines within one code snippet, and unlike grep -C it adopts some heuristics around blank lines to determine an efficient number of context lines. That heuristic is the whole idea: a blank line is a natural boundary, so two matches separated by a blank line do not need to be printed as one long block.
Two ways to feed it: built-in ripgrep or stdin
There are two input paths, and the README shows both in one small block.
# Use built-in subset of ripgrep (optional)
hgrep pattern ./dir
# Read results of grep command via stdin
grep -nH pattern -R ./dir | hgrep
rg -nH pattern ./dir | hgrepThe built-in implementation is a subset of ripgrep used as a library, and the README recommends it because it is optimised for the use case. When a pattern is given, hgrep searches files in the given paths, searching recursively when a directory is included, and searching the current directory when no path is given. The README claims the built-in path is faster than piping rg in some cases and explains why, noting that receiving inputs from grep or rg via pipe is fast to handle so many matches in the same process, and that in combination with the syntect printer feature matched regions can be highlighted in a searched text colour. The stdin path exists for the cases the built-in subset cannot cover, and the README is direct about its limits: the built-in grep implementation is a subset of ripgrep, and if you need full functionality you should use rg and feed its output to hgrep via stdin.
Two printers, and the feature flags that choose them
hgrep provides two printers and the README points at a section comparing them. The syntect printer is the default, described as the project's own implementation using the syntect library, with performance, output layout and colour themes more optimised. The bat printer is built on top of bat's pretty printer implementation, which the README describes as battle-tested and providing some unique features. The Cargo.toml shows the three features and how they map to dependencies. The ripgrep feature pulls in grep-matcher, grep-pcre2, grep-regex, grep-searcher, ignore, regex-syntax and rayon. The syntect-printer feature pulls in syntect, rayon, unicode-width, bincode, flate2 and ansi_colours. The bat-printer feature pulls in bat and dirs. All features are optional and enabled by default, and at least bat-printer or syntect-printer needs to be enabled. The ability to drop bat and keep only syntect is worth knowing about at install time, since it dramatically reduces the number of dependencies, installation time and binary size.
Installing from binaries, a tap or a package manager
There are a lot of installation routes and the README covers each. Binary releases are on the releases page, as zip files per platform, which you unarchive and put the executable in some $PATH directory. The supported targets are Linux on x86_64-gnu, x86_64-musl and aarch64-gnu, macOS on x86_64 and aarch64, and Windows on x86_64-msvc and aarch64-msvc, and you can open an issue to request a binary for another platform. Homebrew works by adding the repository as a tap, and that formula supports x86_64 and aarch64 macOS and x86_64 Linux.
brew tap "rhysd/hgrep" "https://github.com/rhysd/hgrep"
brew install hgrepIf your Homebrew lives in a non-default location you may see errors, and the README suggests installing through cargo instead in that case. MacPorts works on macOS with a selfupdate and an install. NetBSD has a pkgin route for pre-built binaries, or a source build in the pkgsrc tree. Debian and Ubuntu users download a .deb from the releases page and install it with dpkg, which also installs the manual page and Bash completion. And cargo install hgrep builds from source, which is the route that lets you pick features.
cargo install hgrepTrimming the build with cargo feature flags
Because cargo builds from source, the README points out that you can choose your favourite features and drop others by feature flags, with the example being a user who always runs hgrep against grep output from stdin and never uses the bat printer, in which case enabling only syntect-printer dramatically reduces the number of dependencies, installation time and binary size.
cargo install hgrep --no-default-features --features syntect-printerThat is a real advantage over the prebuilt binaries, which ship with everything enabled, and it matters most on a constrained machine or in a distribution where you would rather not pull in bat and its dependency tree. The trade is that you give up the bat printer's extra features. Everything else in the project is built the same way, with the binary named hgrep from src/main.rs, thin link-time optimisation for both the release and bench profiles, and a workspace that includes a bench directory and the assets builder.
Context lines, heuristics and the built-in grep restrictions
The context behaviour is configurable and the default is deliberately fuzzy. By default hgrep shows at least 3 lines and at most 6 lines as context of a match, and the number of context lines is determined by some heuristics around blank lines for space efficiency. The minimum can be set with -c and the maximum with -C, and if you do not want the heuristics you give the same value to both options, for example -c 6 -C 6. You can widen the range when you are surveying unfamiliar code.
# At least 10 context lines and at most 20 context lines
hgrep -c 10 -C 20 pattern paths...Like ripgrep, the built-in grep filters files by default, looking at ignore files such as .gitignore and ignoring hidden files, and --no-ignore and --hidden turn those filters off, with -u as a shortcut for both.
# Same as `hgrep --no-ignore pattern paths...`
hgrep -u pattern paths...The documented restrictions on the built-in subset are the practical limit. A preprocessor is not supported, so you cannot search inside zip files, the pattern file option of rg is not supported, and sorting is not supported. Each of those is a reason to fall back to running rg yourself and piping its output in, which the README recommends once you need full functionality.
Editorial conclusion
Adopt hgrep if you read search results as code rather than as line numbers, since the highlighted snippets remove the step of opening each hit in an editor. Skip it if you are scripting in a pipeline where the machine-readable grep output matters more than the display, since piping through hgrep changes the format. Before you install, decide between the two printers, because the bat printer and the syntect printer differ in features and the syntect one is the default.
Frequently asked questions
What does hgrep do differently from grep?
It prints the matched regions with human-friendly syntax highlighting instead of bare matching lines, closer to the code search on GitHub. It is similar to the -C option of grep, but unlike grep -C it applies heuristics around blank lines to decide how many context lines to show, merging nearby matches into one snippet.
Can hgrep read the output of grep or ripgrep from stdin?
Yes. You pipe grep or rg output into hgrep, for example `grep -nH pattern -R ./dir | hgrep` or `rg -nH pattern ./dir | hgrep`. That route is also the recommended one when you need ripgrep features the built-in subset does not implement, such as a preprocessor, a pattern file or sorting.
What are the two printers in hgrep?
The default syntect printer is the project's own implementation built on the syntect library, with performance, output layout and colour themes more optimised. The bat printer is built on bat's pretty printer implementation, which the README describes as battle-tested and offering some unique features.
How do I install hgrep with fewer dependencies?
Install through cargo with feature flags, for example `cargo install hgrep --no-default-features --features syntect-printer`, which drops the bat printer and dramatically reduces the number of dependencies, installation time and binary size. Prebuilt binaries and the package manager installs ship with all features enabled.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/rhysd-hgrep)Was this useful?