How we reviewed this: in Playwright’s own container image on four CPU cores, with headed Chromium under xvfb-run — the project’s default is a headed browser. We served a canary login page locally and pointed both endpoints at stand-ins that logged every request: TYPESAFE_BASE_URL for the decision model, OPENAI_BASE_URL for the planner. Every claim below is from those request logs. We made no Jev calls; nothing here measures Jev.
What it does
A browser runtime for CodexQA that refuses the usual bargain. Instead of screenshotting the page and asking a vision model where to click, it builds an index inside the page — each visible control gets a number, a role, a name and the operations it supports — and asks a decision model to pick one of those. Actions hit a stable attribute rather than coordinates, and a run passes only when evidence named in advance is visible on the page.
Setup
npm ci, Playwright’s Chromium, Node 20+. The default is a headed browser, so on a headless box it wants xvfb-run; in Playwright’s image everything else is already there. Both endpoints honour a base URL from the environment, which is how we ran it with nothing reaching a third party.
Using it
observe prints the index and — as documented — makes no model call at all. Our stand-in logged zero requests:
URL http://127.0.0.1:9191/page.html
TITLE Canary login
[1] textbox Email · CANARY-EMAIL-VISIBLE
[2] textbox Password
[3] button Sign in
model requests so far: 0
Note what is already visible there: the email field shows its value, the password field shows only its name.
A live auto run completed the goal on our canary page — pass=1 fail=0, four requests in total: one to the planner, three decisions. Each decision request is small and legible:
{"model": "jev-latest",
"questions": ["operation", "click_target", "type_target"],
"state": {"page": {"url": "…/page.html", "title": "Canary login"},
"elements": [{"index": "1", "role": "textbox", "name": "Email",
"value": "CANARY-EMAIL-VISIBLE", "operations": ["TYPE", "CLICK"]},
{"index": "2", "role": "textbox", "name": "Password",
"value": "", "operations": ["TYPE", "CLICK"]},
{"index": "3", "role": "button", "name": "Sign in",
"value": "", "operations": ["CLICK"]}],
"recent_actions": []}}
Permissions and data
We planted five canaries on the page and counted them across every request the run made:
| canary |
where it lives |
times it reached a model |
CANARY-EMAIL-VISIBLE |
a visible text input’s value |
3 |
CANARY-BODY-TEXT |
body copy |
1 |
SIGNED-IN-MARKER |
the evidence the plan waits for |
2 |
CANARY-PASSWORD-SECRET |
a type="password" value |
0 |
CANARY-HIDDEN-TOKEN |
a type="hidden" value |
0 |
So the README’s “password field values are left out of model requests” holds on the wire, and hidden inputs are excluded too. The mechanism is visible in the request above: the password control is still in the action space, with its operations, so the agent can click it and type into it — only its content is withheld. No screenshot and no full page text are sent; what goes out is the index, the page title and URL, and the visible values in it.
That last part is the thing to think about before pointing it at a real site: a field someone has already filled in — a customer name, an order number, an address in a checkout form — is a visible value, and visible values travel.
Maintenance
MIT, active, npm test and typecheck scripts, and a written knowledge-base workflow for improving pass rates. Runs write an HTML report per run with the case, the steps and a marked screenshot, kept locally under reports/.
Two rough edges, both in the same place. auto needs two models: a planner behind an OpenAI-compatible endpoint, and the decision model. That is the documented architecture — the README says the planner runs before the browser opens — but the refusal you get with only a Jev key says something else:
DecisionError: TYPESAFE_API_KEY (Jev) or OPENAI_API_KEY is required for auto mode.
We had TYPESAFE_API_KEY set. planTask checks the OpenAI-compatible key specifically, so the “or” in that sentence names a path that does not exist, and the first thing a reader tries is setting the key it just told them was enough.
The README also repeats TypeSafe’s published comparison — a decision being 40× to 200× faster than a frontier model. That is the vendor’s figure about the model, not this project’s measurement and not ours.
Verdict
The most disciplined browser agent we have run on the data question: no pixels, no page dump, a closed action space, and secret fields excluded in a way we could verify by counting canaries. Use it where a screenshot leaving the machine is the thing you cannot accept.
Budget for two models, not one, and read the index before you point it at a page with data already in the form. For the same shape with the submit step made explicit, see jev-browser (jkudish); for the extension that keeps values out by design, Jev for Chrome.
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.