A fuzzy linter for coding agents.

Your agent writes a file; 0.3 seconds later it hears which of your team's rules it just broke, and fixes them before anyone reviews the code.

Paste it into Claude Code from the repo you want checked. It installs the hook, then proposes rules for your repo. Nothing is written until you approve.

A hook for Claude Code and Codex · open source, MIT

2.38 → 1.21
rule violations per task, Claude Code (96 runs)
~0.3 s
per check, while the agent works
170
tested rules in 5 packs, plus yours
~$2
per 10,000 edits checked

Your team has rules no linter can check.

// don't use useEffect to derive state
// a test must be able to fail
// never trust a client-sent userId

There's no regex for "this effect only derives state". So rules like these wait for code review, by a human or an agent, and every miss costs a round trip.

Today

agent writesreviewagent fixesreview again

+1 round trip. The code goes back, the agent fixes it, and the fix is reviewed again.

With jev-lint

agent writesjev-lint · 0.3 sagent fixesreview

Fixed while the file is still open. Review sees cleaner code.

Here's that loop, start to finish.

40 seconds, from mistake to fix.

The editor scene is an illustrative session; the numbers are measured. Sound on.

Under the hood, it's small on purpose.

One hook. One call. Two tiers.

  1. after every edit

    The hook sends only the new code.

    A PostToolUse hook in Claude Code or Codex sends the code the agent just added to TypeSafe Jev, a fast judgment model: one yes/no question per rule, in one call. A keyword gate skips rules that can't apply.

  2. about 0.3 s later

    Findings go straight back.

    p ≥ 0.8 likely violations: fix these
    0.5–0.8 possible: double-check
  3. never in the way

    It fails open.

    On a timeout, an API error or an unknown file type it exits silently and the edit goes through. It complements linters, type checkers and review; it doesn't replace them.

Does it work? We measured it in real agent runs.

Agents act on it.

Rule violations left in the final code, per task, with the hook off and on.

hook offhook on

Claude Code96 runs · original rules

2.38violations per task with the hook off
1.21with the hook on

Claude Code48 runs · all 170 rules

2.71violations per task with the hook off
1.54with the hook on

Codex48 runs

1.67violations per task with the hook off
0.92with the hook on

With every pack on, the drop holds: −43% (2.71 → 1.54); that baseline is higher because more rules are checked. All three drops are statistically significant. Measured 26–27 Sep 2026; method and caveats in the experiment notebook.

Fewer comments for the reviewer to send back.

With the hook on, review comments that one of our rules covers fell from 1.33 to 0.79 per task. Each is a comment the agent never has to read, work out how to fix, fix, and send back for another review.

rule-covered review comments per task, hook off

1.33

hook on

0.79 −41%

caught at the edit

edit→hook→fix
~+$0.04

and a few seconds per task: the agent fixes it with the file still open

caught in review

review→fix→re-review← back to fix
≈$0.18~70 s

per review → fix → re-review round, and you pay for the review itself either way: per AI review, or in a person's time

With human reviewers the saving is direct: they never see these problems at all.

Reviews still find logic and design issues that no rule covers (about 3.6 comments per task in our tests), so the review doesn't go away; it gets smaller and cleaner. Review comments: all 170 rules, 48 Claude Code runs, 95% CI of the change −1.08 to −0.04 per task. Costs measured on our agent runs, 26–27 Sep 2026 (notebook Entries 5–7).

Fast enough that the agent never waits.

0.300 s

one typical check: the code your agent just added, every applicable rule, one call to TypeSafe Jev

You've been on this page long enough for jev-lint to check 0 edits.

With the warm connection: ~0.23 s (median 228 ms, measured on a quiet Mac).

Twice the rules, same speed.

Doubling the applicable rules per file moved the median check by 8 ms. The keyword gate only asks the ~12 rules whose patterns appear in the new code.

23 applicable rules per file

299 ms

48 applicable rules per file

307 ms

About $2 per 10,000 edits, under a cent per 40 edits. It never blocks the agent: if anything fails, the edit goes through unchanged.

Median check times from our benchmark. Cost measured at $1.51 per 10,000 edits before the larger packs; they add about 30% tokens, so ~$2 is an estimate.

What it checks on day one.

Opinionated out of the box.

170tested rules in 5 packs, each switched on only after passing a held-out evaluation written by a separate author.
TypeScript / ReactSwift / SwiftUIKotlinRustPythonRubyBazel

On held-out edits each pack scored 91–100% precision per language, and flagged 0–4% of clean edits. 110 of 117 new candidate rules passed; 12 of 12 new security rules passed. The rest stay candidates the hook doesn't ask. Every rule, with a good and a bad example →

users.test.tsflagged
test("returns 404 for an unknown user", async () => {
  const res = await app.request("/users/does-not-exist");
  expect(res.status).toBe(200);
  expect(await res.json()).toEqual({ user: null });
});

ts-test-title-contradicts-assertions

The title promises a 404; the assertion checks 200. Agents under pressure flip assertions until tests pass. This catches the residue.

Fix: make the assertion check the behavior the title promises, or fix the code. Never flip an assertion just to make the test pass.

Your rules, not just ours.

  • Defaults, not dogma. Turn any pack or rule off, scope it to some folders, or add rules for your team in .jev-lint/. They live in your repo, so the whole team shares them.
  • Onboards itself. A skill reads your agent instructions, docs, skills and linter configs, then proposes rules for you to approve. Nothing a linter already checks.
  • Learns what agents get wrong. Every check is logged. The learning skill finds the mistakes agents keep making, proposes a few targeted fixes, and measures whether they worked.

Try it on your repo.

One paste. Your agent does the rest.

Needs bun and a TypeSafe API key. Paste this into your agent from the repo you want checked.

prompt.txt
Set up jev-lint for me: https://github.com/ckorhonen/jev-lint
Clone it to ~/Repos/jev-lint if it isn't there, then follow its jev-lint-setup skill
(.agents/skills/jev-lint-setup/SKILL.md): check my TypeSafe key, show me the dry run, install
the hook once I confirm, and run the smoke test. Then use its jev-lint-rules skill on this
repo: read all of our agent instructions, skills, docs and linter configs, and propose rules
for me to approve before writing anything.
I'm using Claude Code, so install the hook for Claude Code (--claude-only).
or install by hand →

jev-lint

a fuzzy linter for coding agents

github.com/ckorhonen/jev-lint

Claude Code + Codex hook · powered by TypeSafe Jev · MIT