Quick start · How it works · User guide · Architecture · Contributing
JEV Router picks the Claude model for each new turn of your Claude Code session. Renaming a variable doesn't need Opus; debugging a race condition does. JEV Router asks TypeSafe's Jev — a fast decision model — which of your models fits the turn, then runs it there. Claude Code keeps working exactly as usual: same UI, tools, permissions, sessions and streaming.
pip install jev-model-router
jev-claude # that's it — Claude Code, with per-turn routing
✨ Features
- Per-turn routing — every new message is judged on its own, so a session can move from Haiku to Opus and back as the work changes.
- Native Claude Code — a local proxy in front of Claude Code's API; nothing to configure in
Claude Code, no fork, no plugin.
/resume, permissions, tools and streaming are untouched. - You stay in control — pick a model in
/modeland routing steps aside; pick JEV Router again to resume. Say "use opus" in a prompt to force it for one turn. - Tool loops stay on one model — Jev is asked once per turn; every file read, edit and command in that turn reuses the chosen model.
- Fails open — no key, a Jev timeout or an error never blocks you; Claude Code carries on with a safe model within ~3 seconds.
- Explainable — a status-line readout of every decision,
jev-explainfor the full reasoning, and a one-line log per turn. - Private by design — your key and prompts are never logged; local files are owner-only.
- Zero dependencies — pure Python standard library.
🎬 Demo
Left: "JEV Router" in Claude Code's own /model picker. Right: a rename routed to Haiku — the status line shows the model Jev picked.
More screenshots — hard turn on Opus, manual override, jev-explain, decision log
A harder turn moves up to Opus — Jev is asked again on the next message:
Picking a model yourself pauses routing — the status line shows ⏸ manual:
jev-explain shows why a turn got its model:
One safe log line per turn — no prompt, no keys:
Captured from a real Claude Code 2.1.282 session through jev-claude; Jev's answers came from the local stand-in scripts/fake_jev.py.
🚀 Quick start
Requirements: Python 3.11+, Claude Code installed and logged in (a claude.ai subscription or an API key — no extra Anthropic key needed), and a TypeSafe API key.
1. Install
pip install jev-model-router
Latest development version: pip install git+https://github.com/himanshu231204/jev_model_routers
2. Add your TypeSafe key — TYPESAFE_API_KEY, the name TypeSafe's docs and SDK use:
echo "TYPESAFE_API_KEY=your_key" > ~/.jev-router.env # or: export TYPESAFE_API_KEY=...
Windows PowerShell: Set-Content "$HOME.jev-router.env" "TYPESAFE_API_KEY=your_key"
3. Run
jev-claude # interactive, routing each new turn
jev-claude -p "fix the failing test" # every Claude Code argument is passed through
jev-claude --resume # sessions work as usual
The session starts on JEV Router. Watch the status line — e.g.
claude-haiku-4-5-20251001 (p=0.97) — to see which model each turn got. The full guide, with
troubleshooting, is in docs/quickstart.md.
🧠 How it works
flowchart LR
A["Claude Code"] -->|"model = jev-router"| B["JEV Router<br/>(local proxy)"]
B -->|"new turn: ask Jev"| J["Jev<br/>(TypeSafe System One)"]
J -->|"best model + confidence"| B
B -->|"model = claude-haiku / sonnet / opus"| C["Anthropic API"]
C -->|"streamed back, unchanged"| B --> A
jev-claudestarts Claude Code with a local proxy as its API endpoint and a JEV Router entry in/model.- When you send a message, the proxy asks Jev which of your account's models — newest Haiku, Sonnet or Opus — can handle it, with a confidence score.
- A small local policy makes the final call: explicit choices win, low confidence never downgrades, and a long conversation isn't downgraded (switching would re-read it all).
- Only the request's model is rewritten; Claude's response streams straight back.
- Tool calls, retries and Claude Code's background requests in the same turn reuse that model.
Jev doesn't write code — Claude does. Jev answers one quick structured question per turn, the
kind of "route this to one of a fixed set of destinations, and know how confident you are"
decision it is built for. Design details: ARCHITECTURE.md.
⚙️ Configuration
Everything works with just the key. Optional environment variables:
| Variable | Effect |
|---|---|
TYPESAFE_API_KEY |
TypeSafe key for Jev. Required for routing; without it jev-claude runs plain Claude Code. |
JEV_ALLOW_FABLE=1 |
Also offer Fable (bills extra usage credits). |
JEV_NO_STATUSLINE=1 |
Don't add the routing status line (your own status line is never overridden). |
JEV_DEBUG=1 |
Request-level tracing in ~/.jev-claude.log, including prompt excerpts. |
JEV_CLIENT=sdk |
Call Jev through the official typesafe-sdk (pip install "jev-model-router[typesafe]"). |
Routing thresholds (confidence floor, cache protection, timeouts) live in one file:
src/jev_router_live/config.py.
🧰 Commands
| Command | What it does |
|---|---|
jev-claude [claude args…] |
Run Claude Code with per-turn routing. |
jev-codex [codex args…] |
Run OpenAI Codex with per-turn routing (experimental). |
jev-explain <session-id> |
Show why the last turn got its model. |
❓ FAQ
Does it replace Claude?
No. Claude still does all the work. Jev only chooses which Claude model handles each turn.
What happens if Jev is down or my key is wrong?
Routing fails open: the turn runs on a safe model (Opus on the first turn, otherwise the model already in use) within about three seconds, and the reason is logged. Claude Code never stops.
What does Jev see?
The prompt of each new turn (with Claude Code's injected system context removed), the current model, a rough context size, and the list of models to choose from. Not your files, tool output or conversation history.
Will it change my Claude Code settings?
No. "JEV Router" is selected for the session only and never saved as your default; if Claude
Code persists it anyway, jev-claude restores your previous default on exit. Plain claude is
unaffected.
Claude Code prints [claude-code:unrecognized_model] {"model":"jev-router"} at startup.
Harmless — it's Claude Code noting the extra "JEV Router" entry. Requests are still routed.
📍 Project status
Beta. Verified end to end against Claude Code 2.1.282 (interactive and -p): the picker entry,
per-turn routing, tool-loop pinning, manual override, fail-open and streaming, with 94 automated
tests on Python 3.11 and 3.12. OpenAI Codex support (jev-codex) is experimental. Known
limitations are listed in ARCHITECTURE.md.
🤝 Contributing
Contributions are welcome — see CONTRIBUTING.md for setup and conventions and
AGENTS.md for the invariants a change must keep. Please report security issues
privately as described in SECURITY.md.
git clone https://github.com/himanshu231204/jev_model_routers.git && cd jev_model_routers
pip install -e ".[test]"
python -m pytest -q
📄 License
MIT © 2026 Himanshu Kumar
JEV Router is an independent open-source project and is not affiliated with Anthropic or TypeSafe. Claude and Claude Code are products of Anthropic; Jev is a model by TypeSafe.
Release files for jev-model-router 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| jev_model_router-0.1.0.tar.gz | 34.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| jev_model_router-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 76.9 kB
Release files / jev_model_router-0.1.0.tar.gz
| Download URL | jev_model_router-0.1.0.tar.gz |
|---|---|
| Size | 34.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
38d12e4df0affcd685b59c742c37ce30da21d09eb5bb5adb587799d45e160b6a
|
|
BLAKE2b-256 checksum How to use checksums |
3abd255d741aaf28385ec2e979ad9a260538a9d3d3aebaf38a27d9078a333420
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 25, 2026.
Transparency logRelease files / jev_model_router-0.1.0-py3-none-any.whl
| Download URL | jev_model_router-0.1.0-py3-none-any.whl |
|---|---|
| Size | 42.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
31eeee10f1e94792150055fb21d8cddec344efaaf1535baa02343bd9cfe54432
|
|
BLAKE2b-256 checksum How to use checksums |
af1fa5cd9406b945569843b9a705bb20b9d935170942178c2e5b4af0995a813b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 25, 2026.
Transparency log