How we reviewed this: in oven/bun on CPU. We ran its own suite and typecheck, exercised the key guard at four different values, and drove the classifier against a stand-in /v1/systemone that logged the request, with TYPESAFE_BASE_URL pointing at it. We made no Jev calls, and nothing here measures Jev.
What it does
One text box. You type dinner with priya friday 8pm on zoom and it becomes an event card; split 2400 between 3 becomes a bill split; buy milk, eggs, bread becomes a checklist. The interesting part is that the classification is not a prompt returning JSON — it is fourteen typed questions asked about your line in one request, and the answers choose the component.
Setup
bun install and it runs. Bun is not optional: the scripts are bun test and bun run check.
One rough edge on a fresh clone: bun run typecheck fails.
src/app/layout.tsx(30,50): error TS2304: Cannot find name 'LayoutProps'.
error: script "typecheck" exited with code 1
LayoutProps is a type Next generates into .next/types, so the check needs next typegen (or a build) first. We ran it and the check is clean afterwards. It matters only because bun run check — the documented one-command gate — runs typecheck first, so a contributor’s first command fails on a red that is not theirs.
Using it
Driven against our stand-in with a plausible key, one line of text produced one request carrying fourteen questions, and came back as a classified intent:
source: jev | model: jev-1.13.0 | questions: 14 | intent: event (0.90)
Its own suite is 172 tests passing across six files, covering the parsers, the signals, the offline classifier and the promotion of a “ghost” card into a committed one.
Permissions and data
The request is the whole answer to what leaves your machine:
{"state": {"text": "dinner with priya friday 8pm on zoom CANARY-TYPED-TEXT"},
"questions": {…14…}, "model": "jev-latest"}
Your line, as typed, and nothing else — no history, no device information, no accumulated session. There is also no redaction: whatever you put in the box is what goes out, which is worth knowing because the box invites exactly the kind of line that carries a name, an amount or an address.
The key guard is better than most. looksLikeKey requires at least twelve characters and rejects anything containing your, xxx, placeholder, changeme or angle brackets, and the mode is reported rather than assumed:
key='your-key-here' offline | no TYPESAFE_API_KEY set
key='sk-abc' offline | no TYPESAFE_API_KEY set
key='ts-live-0123456789abcdef' online | using jev-latest
key='' offline | no TYPESAFE_API_KEY set
So a copied placeholder from a README cannot quietly become a live call, and NEXT_PUBLIC_USE_MOCK=true forces offline even with a real key. The client is built with retry: { maxRetries: 0 } and a 2.5-second timeout, with the reason in a comment: a stale answer is worse than falling back to the offline classifier. On a slow link you get the rules-based answer rather than a wait.
Maintenance
MIT, active, CI-less but with a real suite and a check script. The offline classifier is not a stub — it is a full rules engine that keeps the UI working without an account, which is why the demo can be tried by anyone.
Verdict
The best argument in this directory for typed questions in an interface rather than in a pipeline: fourteen answers about one line, one request, and the component chosen in code. Use it as a pattern even if you do not want the app.
Run next typegen before bun run check, and remember that the box sends what it is given. For typed decisions inside an editor instead of a UI, see jev-feels; for the same one-request-many-questions shape on images, OpenJev-Vision.
See how it compares with other tools in Best Jev tools, tested hands-on.
Review updated Sep 26, 2026. Numbers quoted from the project are its author's own; we don't publish our own measurements of Jev.