# jev-router: sending each Claude Code or Codex turn to a cheaper model

> jev-router is a Node tool that sits between you and Claude Code or OpenAI Codex, asks a Jev model which tier a turn deserves, and rewrites the request to the fast or strong model accordingly, while leaving each CLI's own interface, tools and sessions intact. It suits a developer running a subscription-based CLI who wants routine turns on a cheaper model, and it is the wrong tool if you want a model that never sees your prompts.

**gargpratyush/jev-router** — Route to the cheapest model in claude code for your task using jev-router

- Repository: https://github.com/gargpratyush/jev-router
- Stars: 618 · Forks: 95
- Language: JavaScript
- License: MIT
- Published: 2026-10-22 · Updated: 2026-10-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/gargpratyush-jev-router

## A proxy in front of the real CLI, not a replacement for it

jev-router describes itself as automatic per-turn model routing for Claude Code and OpenAI Codex. Simple work goes to the fast tier and difficult work to the strong tier, while each CLI's native interface, tools, sessions, permissions and authentication are preserved.

The mechanism is a loopback proxy. Each command starts one, launches the real upstream CLI, and forwards the CLI's existing authorization headers without reading, storing or modifying them. The diagram in the documentation makes the shape clear: you talk to Claude Code, Claude Code talks to the jev-claude proxy, and the proxy talks both to Anthropic and to Jev, which is where the tier is chosen.

Two commands are shipped. jev-claude launches Claude Code with Jev Router selected in the model picker, and jev-codex launches Codex with a temporary Jev Router provider and selects jev-router. In both cases selecting a concrete model pauses routing, and selecting Jev Router resumes it. Any concrete model the user picks passes through unchanged.

The routing sentinel is the same string in both cases, jev-router. The difference is in how each CLI is pointed at the proxy. Claude Code uses ANTHROPIC_BASE_URL, and Codex uses a temporary custom provider with requires_openai_auth=true.

The claim that matters most here is that the real CLI still runs. The documentation says both commands launch the real upstream CLI, and that Jev only chooses the model for a fresh user turn. So this is not a client, not a model, and not a wrapper around the API. It is a decision point in front of a client you already have and are already paying for.

## Four shared tiers, and the rules that override them

One Jev call per fresh user turn selects a shared abstract tier, and the same four tier names are mapped onto each CLI's own model names.

The fast tier maps to Haiku on Claude Code and gpt-5.6-luna on Codex. Balanced maps to Sonnet and gpt-5.6-terra. Strong maps to Opus and gpt-5.6-sol. Long maps to Fable and gpt-6-astra. The abstraction is the point: one classification of how hard the work is, translated into whichever model the surrounding CLI actually has.

The policy that turns that tier into a model lives in src/policy.mjs, and the rules listed in the documentation are worth reading in full, because they are what keeps the tool from overruling the user. An explicit request such as use opus, use luna or use strong wins. A failure, a timeout or an unrecognised Jev answer keeps the current model rather than guessing. And a low confidence result never downgrades a model.

That last rule is the one that decides whether you can trust the tool with real work. A router that quietly moved a hard task onto a small model would be worse than no router, and the confidence floor is the guard against it.

The package is a small Node program. The bin entries map jev-claude, jev-codex and jev-explain to the .mjs files in bin/, the runtime dependency list is a single package, @typesafe-ai/sdk at 0.6 or newer, the engines field requires Node 20.12 or newer, and the test script runs the node test runner over test/**/*.test.mjs with a prepublishOnly hook that runs the tests before publishing.

## Why it needs a key at all when your CLI is already logged in

The install steps are short, and there is a wrinkle that looks contradictory until you read the next paragraph.

From npm, the installation is:

```bash
npm install -g jev-router
echo "JEV_API_KEY=..." > ~/.jev-router.env
```

A local checkout works the same way, with git clone, npm install and npm link, and on Windows PowerShell the environment file is written with Set-Content.

The key comes from TypeSafe, and the documentation says that no Anthropic or OpenAI API key is required when the corresponding CLI is already logged in with a subscription. So the JEV_API_KEY is not for talking to Anthropic or OpenAI. It is for the routing decision itself, which is made by asking a Jev model how hard the turn looks. The upstream CLI's own subscription covers the actual model calls.

That is worth understanding before you install, because it is the whole privacy story. Every fresh user turn is sent somewhere to be classified. The documentation is clear that Jev receives the request and the response of the scoring call, and the explanation report is rendered locally from the exact prompt, the System One request and the System One response saved when routing occurred.

The interface also stays native. For Claude Code, the injected status line shows the model used for the last turn, with the tier, a probability, the project and the context percentage, and when routing is paused it shows the manually selected model instead. Keybindings, tools, permission prompts, /compact, /resume and session handling are unchanged, and an existing custom statusLine is preserved, with JEV_NO_STATUSLINE=1 available to turn Jev's status line off. For Codex, each fresh decision appears as a commentary line naming the routed model and the confidence.

## What the explanation skill shows, and where the data ends up

There is a skill bundled with the npm package and loaded automatically, so you can ask why a particular turn went where it did. In Claude Code it is /jev-explain, and in Codex it is $jev-explain. The report shows the factors behind the last routing decision, including task complexity, whether reasoning was required, tool complexity, context size, the recommended tier, the selected model and a confidence percentage.

Two details in how that report is produced matter. It is rendered locally from the exact prompt and the System One request and response saved at routing time, and invoking the skill does not ask Jev to score the prompt again. So the explanation reflects the decision that was actually made, rather than a fresh guess about the same prompt.

The saved exchanges are kept per CLI session, up to 20 recent routing exchanges in one JSON file per session, under the operating system temporary directory. The file name differs by CLI: Claude Code uses its session UUID, and Codex uses codex- followed by the jev-codex process id.

The security note in the documentation is specific. These temporary files contain prompt text and Jev's exact request and response, so they are readable only by you, with the directory created with mode 700 and each file with mode 600. Files not updated for seven days are deleted automatically, and the operating system may remove them during normal cleanup.

The documentation also gives a way to print the exact directory on the current machine, using the node path and os modules, which is the sort of check worth doing if you are running this on a shared host.

## Where jev-router is the wrong choice

The first limitation is the privacy one, and it is not a minor caveat. A router that classifies your work has to see your work, so every turn you send is scored by a third-party service, and the explanation files on disk contain the prompt text and Jev's request and response. For a codebase under an NDA, a work laptop with monitoring, or any context where prompt contents are sensitive, that is a dealbreaker rather than a trade-off, and the local-only alternative is to pick the model yourself.

The second is that the routing decision is a model judgement, so it can be wrong in both directions. The mitigations are real, since explicit requests win, failures keep the current model, and low confidence never downgrades, but the tool still routes on a classification of a prompt it has not understood the way you have. A subtle coding task that reads as simple will go to the fast tier, and nothing in the output tells you that happened unless you read the status line.

The third is the dependency on a third-party service being up. The policy keeps the current model on failure, which is the right behaviour, but it means the tool is a single point of failure for the cheap path and a source of latency on every fresh turn, because a turn now waits for a classification before the model call begins.

The fourth is that the tier table is coupled to model names that will move. The mapping references Haiku, Sonnet, Opus, Fable and the gpt-5.6 and gpt-6 families, so a rename or a retirement upstream is a change this project has to track, and the repository publishes no tagged releases to signal when it has.

The fifth is the scope. It is a router for two specific CLIs, and the Codex side installs a packaged skill into your Codex setup on every start, which is a modification to your tool environment that you should be comfortable with.

## Conclusion

jev-router fits a developer with a metered Claude Code or Codex subscription who wants routine turns to run on a cheaper model without changing how they work, since the CLIs keep their own interface, tools, sessions, permissions and login, and the routing decision is one call per turn made by a separate Jev service. It is the wrong choice if you cannot accept a third-party service seeing your prompts, since every turn is scored remotely, and it is the wrong choice if you need deterministic model selection rather than a judgement call. Before installing, read the routing policy in src/policy.mjs, check where the explanation data is written, and note that the last push was on 2026-09-19 with the package at version 0.3.0 and no tagged releases.

## FAQ

### What does jev-router do?

It performs automatic per-turn model routing for Claude Code and OpenAI Codex. One Jev call per fresh user turn selects a shared abstract tier, and the request is forwarded to the fast, balanced, strong or long model for that CLI, while each CLI keeps its own interface, tools, sessions, permissions and authentication.

### How do I install jev-router?

Run npm install -g jev-router, or clone the repository and run npm install followed by npm link, then write JEV_API_KEY=... into ~/.jev-router.env. It requires Node.js 20.12 or newer and at least one supported CLI, and the key comes from TypeSafe.

### Do I still need an Anthropic or OpenAI API key?

No, not when the corresponding CLI is already logged in with a subscription, because the proxy forwards the CLI's existing authorization headers without reading or storing them. The JEV_API_KEY is only for the routing decision itself.

### What happens if Jev fails or is unavailable?

The policy in src/policy.mjs keeps the current model on a failure, a timeout or an unrecognised Jev answer, and a low confidence result never downgrades a model. In Codex the commentary line then names the fallback model and explains how to set JEV_API_KEY.

### Where does jev-router store the routing data?

Up to 20 recent routing exchanges are kept in one JSON file per CLI session under the operating system temporary directory, named by the Claude Code session UUID or by the jev-codex process id. The files hold prompt text and Jev's request and response, are created with mode 700 for the directory and 600 for the file, and are deleted automatically after seven days without an update.

## Sources

- [gargpratyush/jev-router on GitHub](https://github.com/gargpratyush/jev-router)
- [Issues](https://github.com/gargpratyush/jev-router/issues)
- [License: MIT](https://github.com/gargpratyush/jev-router/blob/master/LICENSE)
- [README](https://github.com/gargpratyush/jev-router/blob/master/README.md)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/gargpratyush-jev-router
