jevgrep (dzhng)
★ 3.1k▲ 239dzhng/jevgrep
Finds code by what it does rather than what it matches: a CLI for coding agents that asks which files and which regions are relevant to a description. Unrelated to the JevGrep above, which has the same name.
Semantic grep that packs sixteen chunks and sixteen questions per request, with grep's exit codes and a --diff mode for linting a change against a rule written in English.
Hands-on review
Semantic grep that packs sixteen chunks and sixteen questions per request. We counted the packing, and every failure we could force now exits 2.
Good for
Watch out for
Tested Sep 23, 2026 at 9961c60b834c · oven/bun in Docker, its tests, then the CLI over 40 files against a stand-in, reached by changing one line
How we reviewed this: we ran its suite under Bun, then pointed it at a stand-in by changing one line — ENDPOINT in src/jgrep.ts, nothing else — and drove it over forty files while breaking the provider five ways. We made no Jev calls.
jgrep "code that swallows errors" src/ — grep where the pattern is a description. No index, no embeddings, no vector database, and the model never generates text: chunks and questions go out together and probabilities come back as file:line hits.
It also does two things beyond search: --diff lints a change against a rule written in English, and --tests picks the tests a change can affect — the same job as jev-test-filter, reviewed the same day.
The README says it “packs 16 code chunks and 16 questions into one request”. Over forty files:
requests: 3
questions per request: 16, 16, 8
40 hits / 40 chunks (0 cached)
Sixteen, sixteen, eight. Exactly as advertised, and the kind of claim worth checking because it is the difference between one cheap call and forty expensive ones.
This is the part we liked. Against a stand-in we broke five ways:
| what the provider did | exit |
|---|---|
| matches found | 0 |
| nothing matched | 1 |
| HTTP 500 | 2 — TypeSafe API 500: boom |
| a non-JSON body | 2 — JSON Parse error: Unrecognized token '<' |
| connection refused | 2 — Unable to connect. Is the computer able to access the url? |
| no API key | 2 — Run jgrep init (or export TYPESAFE_API_KEY) |
An error is an error, not an absence of results. We spent the same afternoon finding a tool that reports a clean document from zero answers with exit 0, so this deserves saying out loud.
A 200 whose answers object was empty used to print 0 hits / 40 chunks and exit 1 — “I looked, the tree is clean”. Every other malformed response was a 2; that one was the answer a guard must never give by accident.
The README’s own CI recipe made it worse rather than better:
- run: '! jgrep --diff origin/main "adds an HTTP endpoint that has no auth check"'
! collapses every non-zero code to success. ! (exit 1) is 0, and ! (exit 2) is 0 too, so an outage, an expired secret or a 500 all made that step pass — and the careful three-code table two lines above it was discarded by the pattern it recommended.
Both reported and both fixed the next morning, in v0.4.0. We re-ran the same stand-in over the same forty files at 131ae04:
-- provider answers {"model":"jev-1.13.0","answers":{}} exit=2
malformed_response: /tree/file13.ts:1-2 provider returned no usable answer for this chunk
… and 35 more
-- provider answers normally exit=1
0 hits / 40 chunks (0 cached) · 15 tokens · $0.0000
An id that does not come back is now a malformed_response per chunk, and one bad chunk fails the whole run with 2. The README now carries the case $? shape, so the three exit codes reach the check that reads them.
The distinction the table was protecting is worth restating, because it is the single most common defect we find in this category: an error is an error, not an absence of results. Four other tools we looked at the same week report a clean document from zero answers with exit 0.
MIT, published to npm as jevgrep, zero runtime dependencies, built with Bun. Its tests pass, covering the CSV row parser, the batching cap, the cache, and the test-selection logic — including that direct filename matches skip Jev entirely rather than paying to ask.
jgrep init verifies the key against the API before storing it, writes it chmod 600, and offers to teach Claude Code and Codex to use the tool. A cache keyed per chunk made a repeat run free.
Fifteen stars, one author.
Well built, honest about cost, and it gets the exit codes right where it counts — which is not a low bar in this category.
The caveat is crowding rather than quality. This is the fourth semantic grep in this directory, alongside jegrep, jgrep (keltokhy) and JevGrep, and they all work. Pick on the edges: this one for the --diff CI guard and the --tests selection, once the two exit-code issues above are closed.
If you are using it as a merge gate today, do not negate it with !. Branch on the code.
For the test-selection job done as its own tool, see jev-test-filter; for a grader that does report a clean document from no answers, slop-grader.
See how it compares with other tools in Best Jev tools, tested hands-on.
Review updated Sep 23, 2026. Numbers quoted from the project are its author's own; we don't publish our own measurements of Jev.
dzhng/jevgrep
Finds code by what it does rather than what it matches: a CLI for coding agents that asks which files and which regions are relevant to a description. Unrelated to the JevGrep above, which has the same name.
dorkitude/webctl
Search CLI for agents: results from up to three backends are scored by Jev against your query and an explicit --goal, and only the relevant ones reach the agent's context. Its benchmark excludes an arm it could not observe.
uehaj/sys1grep
Greps by meaning rather than pattern, scoring every line against a description and combining meanings with AND, OR and NOT; a single dependency-free Node file. Japanese and English. Formerly jev-semgrep.
New Jev releases, pricing changes, and the best new projects, once a week. No spam; unsubscribe anytime.
Powered by Buttondown. See our privacy policy.