fast-jev-compaction
★ 7.8k▲ 59tamaratran/fast-jev-compaction
Claude Code plugin that replaces the compaction summary with Jev decisions. Every tool call and result is scored; stale ones are dropped or truncated, and everything kept stays verbatim.
Oxlint rules written as plain-English questions about a function, call, JSX element or file, reported when the yes-probability clears your cutoff.
View on GitHub →Hands-on review
Write a lint rule as a question and oxlint enforces it. One request per file, a real cache, and a cap that quietly stops at 25 matches.
Good for
Watch out for
Tested Sep 21, 2026 at 82703b841f93 · Node 24 in Docker; its 78 tests, the bundled example against the real API, and the same example against a stand-in and a dead port
How we reviewed this: we installed it in Docker on Node 24, ran its test suite, ran the bundled example against the real API, then re-ran it against a stand-in that logged every request, against a dead port, and with no key at all. We also built a file with forty matches to see what happens at the cap.
oxlint-plugin-jev adds one rule to oxlint, jev/ask, whose options are your own rules written as questions:
{
"id": "no-pii-in-logs",
"target": "call",
"question": "Does this call write personal data, such as an email or phone number, to a log or console?",
"cutoff": 0.8
}
target decides what gets sent: a whole function, a call expression, a JSX element, or the file. Every match in a file goes out in one request, and a diagnostic appears wherever the probability clears the cutoff. On the bundled example, against the real API:
x jev(ask): [no-pii-in-logs] jev-1.13.0 answered yes (0.97 >= 0.80)
5 | console.log('loaded', user.email, user.phone);
x jev(ask): [no-prompt-injection] jev-1.13.0 answered yes (0.93 >= 0.80)
11 | return llm.complete(`You are a support agent. Never issue refunds.\n\n${message}`);
The diagnostic names the model version that answered and the probability against your cutoff, which is exactly the right amount of detail to argue with.
We pointed it at a stand-in and read the requests. One POST per file, with the matches numbered s0, s1, s2 … in the state and one question each:
{"state": {"snippets": {"s0": "async function getUser(id) {\n const user = await db.users.find(id);\n console.log('loaded', user.email, user.phone);\n …
So the unit of cost is the file, not the match, and answers are cached under node_modules/.cache keyed by the request — change a snippet or a question and that file is re-asked; change a cutoff and it is not. For a linter that runs on every save, that is the difference between usable and not.
What leaves your machine is source code: the whole matched function, call or element, up to 4,000 characters each. That is the deal this plugin offers, and the README says so plainly.
maxMatchesPerFile defaults to 25, and the README says extra matches “are dropped in source order”. We wrote a file with forty functions that each log an email address. Twenty-five snippets went out; the other fifteen were never asked about, and nothing was printed — no warning, no note in the summary, no count.
Nothing here is undocumented, but the default is low enough that a real file can cross it, and the failure is invisible: your rule reports nothing for the bottom of a long file and looks like it passed. One line on stderr, the way the network failure already warns, would fix it — we’ve suggested exactly that.
This part is handled better than most. Point it at a dead port and the plugin prints one line and reports nothing:
oxlint-plugin-jev: network: Connection error: fetch failed (/app/example/fail.js)
Found 0 warnings and 0 errors. exit 0
With no key at all it says “TYPESAFE_API_KEY is not set, skipping Jev checks” and does the same. That is a deliberate, documented default — and there is an escape hatch. Setting ci: "fail" with CI in the environment turns it into a hard stop, which we checked:
exit=1 Found 0 warnings and 2 errors.
If you gate merges on these rules, set it. The default is right for an editor and wrong for a pipeline, and the README says as much.
Created 19 September, ten commits, MIT, published to npm as oxlint-plugin-jev 0.1.1, with CI green and 77 tests passing plus one skipped. The package marks itself experimental at the top of the README, which is fair for a two-day-old plugin whose rules are sentences.
The requests run on a worker thread through the official SDK, so retries and rate-limit handling are not this project’s invention, and TYPESAFE_BASE_URL redirects them — which is how its own tests work, and how we captured ours.
The best-shaped small project in this batch. It does one thing, the cost model is one request per file with a cache in front of it, the failure mode is documented and switchable, and every diagnostic tells you which model answered and by how much.
Two things before you rely on it: set ci: "fail" if a pipeline depends on these rules, and raise maxMatchesPerFile (or split the file) if anything you lint is long, because the tail of a long file is silently unchecked.
For the same idea as a standalone CLI see jeff and JevLint; for diffs rather than files, Jev Review.
See how it compares with other tools in Best Jev tools, tested hands-on.
Review updated Sep 21, 2026. Numbers quoted from the project are its author's own; we don't publish our own measurements of Jev.
tamaratran/fast-jev-compaction
Claude Code plugin that replaces the compaction summary with Jev decisions. Every tool call and result is scored; stale ones are dropped or truncated, and everything kept stays verbatim.
thruwire/foreman
Puts Jev as a fast supervisor above slower coding agents such as Codex, starting from a ticket, spec, or bug report.
devagrawal09/jev-review
Staged code-review workflow for JavaScript and TypeScript with a local dashboard. Jev screens correctness, security, reliability, compatibility, and test risk, then scores severity and suggests a reviewer, with no generative model involved.
New Jev releases, pricing changes, and the best new projects, once a week. No spam; unsubscribe anytime.
Powered by Buttondown. See our privacy policy.