Skip to content
System One

jev-router (gargpratyush)

Automatic per-turn model routing for Claude Code and OpenAI Codex. Jev sends simple work to the fast model tier and difficult work to the strong tier while preserving each CLI's native tools, sessions, permissions and authentication.

gargpratyush/jev-router on GitHub

Stars
376
Forks
42
Language
JavaScript
License
MIT
Last push
19 Sep 2026

Read from GitHub on . Counts change daily.

jev-router wraps Claude Code and Codex with two commands, jev-claude and jev-codex, that launch the real CLI underneath and let Jev pick the model for each fresh user turn. Each command starts a local proxy that forwards the CLI’s existing authorization. Login, tools, sessions, permissions, /compact and /resume all stay native. Selecting a specific model in /model pauses routing until the user selects Jev Router again.

One Jev call per turn does the routing. A choice question asks for the cheapest exact model in the account’s catalog that can fully complete the request in one pass, and score questions rate task complexity, reasoning required and tool complexity. The models map to four tiers: fast, balanced, strong, and an opt-in long tier. A policy layer then applies rules in code: an explicit request such as “use opus” wins, a failed or unrecognised answer keeps the current model, and low confidence never downgrades. Tool-loop continuations keep the tier chosen at the start of the turn, so Jev adds latency only to a turn’s first request.

Claude Code shows the chosen model in an injected status line; Codex shows it as a commentary line. A /jev-explain skill ($jev-explain on Codex) renders the factors behind the last routing decision locally, from the saved request and response, without asking Jev again. No separate Anthropic or OpenAI key is needed when the underlying CLI is already logged into a subscription.

How it uses Jev

  const result = await getClient().systemOne(request, { signal: abort.signal });
  const { model: answer, task_complexity, reasoning_required, tool_complexity } = result.answers;
  return {
    ...answer,
    request,
    response: result,
    metrics: {
      taskComplexity: task_complexity.score / COMPLEXITY_MAX_SCORE,
      reasoningRequired: reasoning_required.score / COMPLEXITY_MAX_SCORE,
      toolComplexity: tool_complexity.score / COMPLEXITY_MAX_SCORE,
      contextSize: Math.min(contextTokens / CONTEXT_WINDOW_TOKENS, 1),
    },
    ms: Date.now() - started,
  };
} catch (err) {

View in src/router.mjs

Open on GitHub

More like this

Use cases this is tagged with