jgrep
September 19, 2026 Β· View on GitHub
jgrep
grep for what code does, not what it's called.
jgrep "catches an error and silently ignores it" src/
No index. No embeddings. No LLM round-trips. A whole src/ tree in ~2 s for about a cent.
Why
| you want to find⦠| grep / rg | embeddings | an LLM | jgrep |
|---|---|---|---|---|
| an exact name or string | β instant | meh | π’ $$ | use grep |
| "code that swallows errors" | β | β fuzzy | β slow | β 2 s |
| "endpoint with no auth check" in my diff | β | β | β $$ | β Β’ |
| needs an index / vector DB | no | yes | no | no |
jgrep runs on Jev, a System One model: it never
generates text, it answers typed yes/no questions with calibrated
probabilities, in parallel, at $0.042 per million input tokens with output free.
jgrep packs 16 code chunks and 16 questions into one request and turns the
probabilities into file:line hits.
Install
npm i -g jevgrep # installs the `jgrep` command
jgrep init # paste your TypeSafe key, pick where to keep it, done
jgrep init verifies the key against the API, stores it with chmod 600,
and optionally teaches Claude Code / Codex to use jgrep. Get a key at
console.typesafe.ai.
Prefer not to run init?
export TYPESAFE_API_KEY=... # env
echo 'TYPESAFE_API_KEY=...' >> .env # per project
mkdir -p ~/.config/jgrep && echo 'TYPESAFE_API_KEY=...' > ~/.config/jgrep/env # global
Use
Find code by behavior
jgrep "reads user input without validating it" app/
jgrep -C "parses a JWT or decodes a base64 token payload" src/ # -C prints the chunk
jgrep -t 0.9 "builds an SQL string by concatenation" . # stricter
jgrep -a -t 0 "is dead code nothing calls" lib/ | head # everything, best first
Lint a change with rules written in English
jgrep --diff --staged "leaves debug output such as console.log"
jgrep --diff origin/main "adds an HTTP endpoint that has no auth check"
jgrep --diff origin/main "changes billing logic without touching a test"
Exit status is grep's (0 matched, 1 nothing, 2 error), so CI negates it:
- run: npm i -g jevgrep
- run: '! jgrep --diff origin/${{ github.base_ref }} "adds an HTTP endpoint that has no auth check"'
env: { TYPESAFE_API_KEY: "${{ secrets.TYPESAFE_API_KEY }}" }
Score a table (CSV / JSONL), not just code
Every row becomes one state. One description works like grep; a JSON file of Jev questions (noul, choice, score) adds one answer column per question.
jgrep --rows creators.csv "beauty is the main content of this account"
jgrep --rows creators.csv --questions beauty.json --out scored.csv
{
"beauty": { "type": "noul", "instructions": "Is beauty the main content of this account?" },
"category": { "type": "choice", "instructions": "Dominant sub-category?",
"criteria": { "skincare": "skin care", "makeup": "cosmetics", "other": "not beauty" } },
"fit": { "type": "score", "instructions": "Fit for a Korean skincare seeding campaign?",
"criteria": ["no fit", "weak", "moderate", "strong", "ideal"] }
}
Question objects are passed to the API verbatim, so anything Jev accepts works.
Output columns: beauty (probability), category + category_p, fit + fit_conf.
Eight creators and five questions is one request, 3k tokens, well under a cent;
see examples/. This is the "AI map-reduce" shape: scrape N
things, ask k typed questions each, filter in a spreadsheet.
Feed your coding agent
Agents burn most of their tokens looking for code. jgrep hands them a short list of ranges instead of whole files. On a 115 KB module the agent read 6 KB of matching chunks instead of everything.
jgrep init # tick "Claude Code" / "Codex" to install the skill
jgrep --json "spawns a child process" src/ | jq '.[].file'
The skill also has the agent run a few --diff --staged rules on its own
change before committing: a second model checking the first one's work, for
a fraction of a cent.
All options
jgrep init interactive setup
jgrep [options] "<description>" [path ...]
jgrep [options] --diff [ref] "<description>"
jgrep [options] --rows <file.csv|.jsonl> "<description>"
jgrep [options] --rows <file> --questions <q.json> [--out scored.csv]
-t, --threshold <p> print chunks with probability >= p (default 0.7)
-C, --show print the matching chunk body under each hit
-a, --all print every chunk with its probability, best first
--json machine-readable output
--diff [ref] grep git diff hunks (working tree, or against <ref>)
--staged with --diff: staged changes only
--rows <file> grep rows of a CSV / JSONL file instead of code
--questions <f> with --rows: JSON of Jev questions asked of every row
--out <file> with --questions: write the CSV here instead of stdout
-b, --batch <n> chunks per request (default 16)
-c, --concurrency <n> parallel requests (default 16)
--no-cache ignore and do not write ~/.cache/jgrep
How it works
- Files come from
git ls-files(untracked included, ignored excluded), or a directory walk. Binaries and files over 1 MB are skipped. - Chunks: each file is split at column-0 line starts into 5 to 60 line
pieces. With
--diff, each hunk is a chunk and keeps its+/-markers. - One request, 16 chunks, 16 questions:
state.chunks[]plus a Noul question per chunk, "look only at chunk c3, does it match: β¦". - Threshold: probabilities at or above
-tare printed in file order. Answers are cached by(model, question, chunk)in~/.cache/jgrep/, so the same query again is free and instant.
| repo | chunks | time | cost |
|---|---|---|---|
TypeScript CLI, src/ | 896 | 1.8 s | $0.010 |
| same query again (cache) | 896 | 0.0 s | $0 |
one module, app/lib/ | 521 | 1.6 s | $0.006 |
Tips
- Write the description in English and describe the code, not the feature: "decides whether to alert based on OCR confidence" beats "alert feature". Jev's accuracy is lower on non-English text.
- One behavior per query. Split compound questions and combine in your head
(or in a script with
--json). - Chunks are judged in isolation, so cross-file flow ("does this eventually hit the DB") will not match. Ask about the local code.
p >= 0.9is reliable,0.7-0.9is worth a look.
Develop
bun test src/ # unit tests, no network
bun run build # dist/jgrep.js, plain node, deps bundled
If jgrep saved you a file-hunting session, a β on GitHub is the best thanks.
MIT