~/satyajit

jevgrep: Jev does the reading, and the 40% leaves its bill out

mdjsonmcp

2026-09-27 · 17 min · explainer · agents · retrieval · context-management · benchmarks · llm

@dzhng's launch post reads: "Introducing jevgrep - a research agent CLI powered by jev from @typesafeai that reduces your coding agent cost by 40% (verified on SWE-bench). Make sure to use the built in skill so your coding agent knows to use jg for context collection".

I cloned dzhng/jevgrep at v0.3.0 (commit 762028f) and read the 2,995 lines of TypeScript in packages/core/src and apps/cli/src, the skill, the SWE-bench harness and the records of five ten-task runs. I did not run it. Measured below means I computed it from a repo file or a public price list, reported means it is the repo's own figure, and reasoned means it is my arithmetic on the other two.

The short version:

Why finding code is the expensive part

A coding agent is a loop. On each turn the model receives the whole transcript as input and emits a short output, usually one tool call. The tool's result (a file, a grep listing, a test log) is appended, and the next turn sends everything again. A file read on turn 3 of a 40-turn run is billed once as fresh input and 37 more times as cached input.

That is why research costs more than its size suggests: it happens first, so it rides along longest. The benchmark's coding model, GPT-5.6 Sol, lists at $4 per million fresh input tokens, $0.40 per million cached, and $20 per million output (reported, Vercel AI Gateway's model list, 27 September). A 20,000-token read on turn 3 of 40 costs $0.08 fresh plus 37 × $0.008 cached, $0.38 in all, nearly five times its sticker price (reasoned). Deciding what to open next is output, at five times the input price. Arranging context so caching works and dropping it are two answers; jevgrep's is to move the reading to a model whose input costs $0.042 per million.

A figure circulating with the launch puts context collection at 30-60% of an agent's tokens and attributes it to the README. I could not find it: not in the README at v0.1.0, v0.2.0 or v0.3.0, not on npm, not in the specs, not in the launch video's source, whose opening caption is the nearest thing ("Coding agents burn tokens just finding the right code."). I treat it as unsourced. The repo's data bounds it from one side: if the whole 40.70% cut came from research, research was at least 40.70% of the baseline bill (reasoned). It could also come from fewer wrong turns later, and the harness does not split bills by phase.

How jg walks a repository

An explainer graphic. Headline: 40% lower coding-agent cost, one 10-task SWE-bench repeat. Three steps: ask a repo question (a speech bubble asking where pooling is configured), Jev finds relevant code (a file tree with db/connection.py, db/pool.py and tests/test_connection.py highlighted), and the agent implements and tests (a code card showing create_engine with pool_size=10 and a green tick). Below: Baseline 7.62 dollars, with jg 4.52 dollars; task solves 8/10 baseline to 7/10 with jg; footnotes saying full Sol task cost including failed tasks, Jev cost excluded, and single repeat on a tuned Python subset, savings not guaranteed.
The project's own summary of the pipeline and the result, disclosures included. It is generated artwork and the example code is illustrative. (jevgrep README, explainer graphic.)

jg "question" root calls retrieve() in packages/core/src/retrieve.ts. It does not upload the tree up front. It walks a frontier, one level per round:

  1. List, and look one level ahead. A seed directory is listed, and so are its immediate subdirectories, without asking Jev anything. A wrapper like src/ cannot hide src/db/ behind a bad first impression.
  2. Ask about what that reaches. A grandchild directory is judged from a preview: up to 64 child names and kinds, at most 4,096 bytes, plus counts of files, directories and extensions. A file is judged from its content, never its name alone: its whole text, cut into 12,000-byte chunks, one question per chunk. A file scores its best chunk.
  3. Batch. Up to 128 questions or 38,000 bytes of JSON per request, with 32 requests in flight.
  4. Decide. A directory above 0.5 becomes a seed for the next round. At or below 0.5 it is remembered as pruned. A file above 0.25 is admitted.
  5. Anchor once. When the walk runs dry, jg goes through the admitted files above 0.5, best first, and takes the first that declares a class with methods. Every pruned directory is asked again, now with samples of its files' content (16,000 characters shared among them, three windows per file): does this code declare, subclass, override or directly use that class? Directories that say yes are walked.

The guards are 100,000 directory entries, 50,000 requests and 15 seconds per request; a file over 1,000,000 bytes is judged from a 16 KB preview. .gitignore, hidden paths, node_modules, dist, .env and key files are skipped by default. Step through it on a toy repository; the scores are made up, the order of operations is the tool's:

jg "Where is pooling configured? I need a pool of 10 connections." .toy repo · illustrative scores
0 · the question

The agent runs jg with a question and a root. Nothing has been read yet. Jev will only ever be asked yes-or-no questions, and every answer is a probability.

  • my-repo/listed, no question
  • docs/
  • guide.md
  • README.md
  • src/
  • api/
  • routes.py
  • db/
  • connection.py
  • models.py
  • pool.py
  • utils/
  • strings.py
  • tests/
  • test_connection.py
  • test_models.py

What this costs is volume. Every file under a walked directory is sent in full. In the repeat, Jev read 24,317,486 input tokens across ten tasks in 5,173 client calls: about 4,700 tokens per call and 517 calls per task, ranging from 63 on Requests to 1,041 on Matplotlib (measured, from the aggregate). That is affordable only because Jev's input price is 95 times below Sol's fresh input and about 10 times below Sol's cached input (reasoned).

What Jev decides, and what it never does

Every question jg sends is type: "boolean", and Jev answers each with a probability. The directory question reads: "Is directory … worth exploring for this query? Use childPreview filenames and sample metadata as evidence. A truncated preview is not proof useful descendants are absent." The file question ends: "Multiple files can be useful; there is no count target." Jev decides four things: explore a directory (above 0.5), admit a file (above 0.25), select a declaration (above 0.5 for source, above 0.25 for a lead), and label a file's roles (five booleans above 0.5: implementation, caller, test, fixture, helper).

Of the four problems the five Jev harnesses each had to solve, jg solves three with no model at all: the enumerator is the filesystem and two parsers, the question is a fixed template per item kind, and the thresholds are constants. The fourth, getting a string out of a model that cannot write one, never arises, because the output is the repository's own text.

Against the four gates, every question is one boolean about one item, so there is no multi-option choice for the relational failure to break; the one relational question, the follow-up pass below, puts the related evidence in the shared state. Gate four is where jg lives. Code branches on every probability at fixed cut-offs, and I found no calibration check of Jev on source code in the repo, only the end-to-end result.

What goes back to the agent

Each admitted file then goes through selection.ts:

The packet is one stdout stream. The summary and any incompleteness come first, then the ranked file list with roles and leads, then the source blocks. This is the repo's recorded example, a fixture rather than a live run:

specs/done/jevgrep/assets/stdout-example.txt (first 16 lines)
Jevgrep: 3 relevant files.
AGENTS.md lookup (root and returned-file ancestors): none found.
- "src/backend/events.ts" — implementation, caller, test, fixture, helper; selected source and structural context below
  Reading lead source: lines 1-1
  Reading lead BackendTelemetry.recordEvent: lines 4-6
- "src/telemetry.ts" — implementation, caller, test, fixture, helper; selected source and structural context below
  Reading lead Telemetry.recordEvent: lines 3-5
- "tests/telemetry.test.ts" — implementation, caller, test, fixture, helper; selected source and structural context below
  Reading lead source: lines 1-1
  Reading lead testEventName: lines 3-5
End file list.
 
Source block "src/backend/events.ts" lines 1-8:
1: import { Telemetry } from '../telemetry';
2: // Backends preserve the same event contract.
3: export class BackendTelemetry extends Telemetry {

Two properties matter for cost. There is no default size cap (--max-source-bytes defaults to 0, unlimited), and every admitted file is listed even without an excerpt: the Django packets in the two shipped-package runs listed 51 and 42 files (reported). And the packet is context like any other read, re-sent on every later turn. In the repo's paired traces, Sphinx's packet shrank from 31,851 to 14,005 bytes as its bill fell from $1.24 to $0.40, and Xarray's grew from 2,787 to 17,524 bytes as its bill rose from $0.32 to $0.51. The repo says this does not isolate a cause (reported).

How the skill gets the agent to call it

jg skill runs npx skills add dzhng/jevgrep --skill jevgrep, which finds Claude Code, Codex, OpenCode and other agents and installs skills/jevgrep/SKILL.md. Its trigger line: "Find files for unfamiliar repository behavior and regression tests before coding." It tells the agent to:

In the benchmark the skill was not left to the agent's judgment. The treatment prompt is the baseline prompt with $jevgrep in front, Codex's syntax for invoking a skill, and the harness checks that a jg search ran: "benchmark invocation is required to isolate retrieval's effect", while "Production skill invocation is selective". The number measures always calling jg, not the skill deciding when to.

The clock differs too. The treatment's 900-second work budget excludes time spent waiting on jg; the baseline had a flat 900-second deadline. The change followed an earlier trial in which Sol cancelled jg at 702 seconds to save time for coding (reported). The baselines finished in 74.5 to 596.4 seconds (reported), so the asymmetry changes the instructions, not the bill directly.

Which model, through which provider

packages/core/src/providers.ts has three presets behind one adapter: @ai-sdk/typesafe-ai 3.0.8, called through the AI SDK's experimental_evaluate.

ProviderBase URLModel id
Vercel AI Gatewayhttps://ai-gateway.vercel.sh/typesafe/v1typesafe-ai/jev
TypeSafehttps://api.typesafe.ai/v1jev-1.13.0
OpenRouterhttps://openrouter.ai/api/v1jev-1.13

jg auth saves one provider and key to ~/.config/jevgrep/credentials.json, mode 0600; since 0.3.0 environment keys are ignored. There is no endpoint override, so a local server that speaks Jev's wire format, like the one in week two of the alternatives, needs a code change. Answers are cached under ~/.cache/jevgrep, keyed by the exact request, provider, model and prompt version, so a repeated search repeats its answers, which Jev itself does not promise.

Every benchmark run went through Vercel; the other two routes are checked by replaying requests. Jev lists at $0.042 per million input tokens, output free, with at most 32,000 tokens of state plus the longest question per request (reported, gateway model list). In all three retained aggregates the known Jev cost equals known input tokens times $0.042 per million, to the ninth decimal (measured).

The 40%, checked

Every result file compares against the same saved baseline: Codex driving openai/gpt-5.6-sol at medium reasoning effort, run once per task, $7.6220690 in all, 8/10 solved (reported; I re-summed the per-task rows in fixed-baselines.json and got the same total). Five ten-task cohorts sit against it:

CohortSolvedAgent billCutJev, knownCut with Jev
Accepted spike (frozen experiment, not the package)8/10$4.742111237.78%not retained—
Package, bundled-CPython run7/10$4.933820635.27%$1.06755528621.26%
Package before the freshness fix8/10$5.090781433.21%$1.025938219.75%
Shipped package, first run6/10$5.541077627.30%$1.03578262213.71%
Shipped package, repeat (the headline)7/10$4.519553240.70%$1.02133441227.30%

The bills and cuts are reported, except the spike's 37.78%, which is my arithmetic on its reported bill. The last column is reasoned, and it is an upper bound because the known Jev figure is a lower bound. The headline is the best of the five cuts. The same code produced 27.30% one run earlier.

Checking the common reading line by line:

What Jev's bill takes back. The repeat saved $3.1025158 of agent spend. Jev's known cost was $1.021334412, and three tasks (Django, Xarray, Matplotlib) have incomplete metadata, so the true figure is higher. Counted, the ten-task bill is at least $5.54 (by coincidence, the first run's agent bill before Jev), Jev takes back at least 32.9% of the saving, and the net cut is at most 27.3%; per task, Jev's $0.102 is 13.4% of the $0.762 baseline bill (reasoned). Across the four package cohorts Jev's bill barely moves, $1.02 to $1.07, and takes back 32.9% to 49.8% of the saving (reasoned). The repo states the exclusion openly; the post drops it.

Where the saving comes from. Pytest went from $2.34 to $0.61, which is 56% of the saving on its own. Sphinx ($1.06 to $0.40) and Django ($1.51 to $0.95, failed) bring the three largest to 95%. Three solved tasks cost more with jg: scikit-learn 27.2%, Xarray 3.6% and Requests 1.4%. The median task is 13.3% cheaper, and without pytest the cut is 25.9% (measured). Pytest's baseline is the outlier, 62 generations for $2.34, and jg brought it to $0.59-$1.02 in all four package runs, so that part looks durable. Django, the task jg failed, supplies 17.8% of the saving (measured).

What one fewer solve means at n=10. Seven of eight baseline solves were kept and none were added. An exact McNemar test on one discordant pair against zero gives p = 1.0: the loss cannot be told from noise, and a real loss cannot be ruled out either. The 95% intervals are 35-93% for 7/10 and 44-97% for 8/10. Detecting a drop from 80% to 70% with 80% power takes roughly 290 tasks per arm, more than half of SWE-bench Verified's 500 (all reasoned). The baseline was run once, deliberately ("Never rerun a baseline to favor a variant"), which guards against cherry-picking but leaves its own variance unmeasured; the identical treatment moved from 6 to 7 solves and from $5.54 to $4.52 between runs. One way to price the lost solve is to rerun Django with the baseline agent at its baseline price: $4.52 plus $1.51 is 21.0% below baseline, and 7.6% below once Jev is counted (reasoned).

Is "verified" the right word? For the split, yes. All ten task ids are in the 500-row SWE-bench Verified test split, and the official grader scored them (measured against the dataset). For the evidence, no. The repo's audit calls it a "Small purposive Python-only sample" and says "All ten tasks were observed during development." It is one run with one agent: Claude "is deferred", and TypeScript has a parser but no benchmark. The README's own sentence is the one to quote: "This is a cost reduction with a quality tradeoff, not evidence of equal or better solve quality." The README is careful; the post is where the qualifiers fall off.

A ledger for your own numbers

The ledger is anchored on the repeat's per-task means. Its four inputs are the share of the agent's bill jg removes, the coding model's price, Jev's cost per call and the solve count.

cost ledger · one average SWE-bench task · anchored on the repo’s repeat cohort
coding-model input price, $ per million$4.00 · ·
baseline · agent alone$0.762
with jg · agent $0.452 + Jev $0.102$0.554
per attempted task
27.3% lower
per solved task
$0.791 vs $0.953
Jev as a share of the saving
32.9%

A saving survives, but it is 27.3%, not 40%.

  • break-even share removed: 13.4% of the agent bill · to keep “40% lower” true: 53.4%
  • break-even coding-model price: $1.31 per million input (32.9% of Sol)
  • solves needed for cost per solve to match the baseline: 5.8 of 10

Bills are the repeat cohort’s per-task means. The price knob scales the whole agent bill by its input price relative to Sol’s $4 per million and holds the trajectory fixed, which a cheaper model would not. Jev’s known cost is a lower bound: three of ten tasks in the repeat have incomplete Jev metadata.

The break-evens it draws, all reasoned from the numbers above:

What I would do with it

The design is sound. A classifier does the part of the job that is classification, code owns the enumeration, the output is verbatim, and incomplete discovery is labelled incomplete rather than passed off as absence. The repo is unusually candid: every weakness in this piece comes from its own files. Next to tgrep, which makes exact search cheap, jg covers the other case, when you cannot name the symbol yet.

I would use it on an unfamiliar Python repository with an expensive coding model, scoped to the code folder, with --max-source-bytes set, and skip it when rg would find the symbol. Before repeating "40% cheaper" I would want Jev billed in, an untouched task set well past ten, a baseline run more than once and one agent that is not Codex. How far Jev's scores travel off their home benchmark is a question the site has already had to ask.

Cite this article

For attribution, please use the following reference or BibTeX:

Satyajit Ghana, "jevgrep: Jev does the reading, and the 40% leaves its bill out", ai.thesatyajit.com, September 2026.

bibtex
@misc{ghana2026jevgrep,
  author = {Satyajit Ghana},
  title  = {jevgrep: Jev does the reading, and the 40% leaves its bill out},
  url    = {https://ai.thesatyajit.com/articles/jevgrep},
  year   = {2026}
}
share