[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-96426":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":10,"language":11,"languages":10,"totalLinesOfCode":10,"stars":12,"forks":13,"watchers":14,"openIssues":15,"contributorsCount":16,"subscribersCount":16,"size":16,"stars1d":17,"stars7d":18,"stars30d":18,"stars90d":16,"forks30d":16,"starsTrendScore":19,"compositeScore":20,"rankGlobal":10,"rankLanguage":10,"license":21,"archived":22,"fork":22,"defaultBranch":23,"hasWiki":24,"hasPages":22,"topics":25,"createdAt":10,"pushedAt":10,"updatedAt":26,"readmeContent":27,"aiSummary":10,"trendingCount":16,"starSnapshotCount":16,"syncStatus":28,"lastSyncTime":29,"discoverSource":30},96426,"jev-router","gargpratyush\u002Fjev-router","gargpratyush","Route to the cheapest model in claude code for your task using jev-router","",null,"JavaScript",243,25,1,4,0,56,124,236,4.24,"MIT License",false,"master",true,[],"2026-09-21 02:04:32","# jev-router\r\n\r\nAutomatic per-turn model routing for Claude Code and OpenAI Codex. Jev sends simple work to\r\nthe fast tier and difficult work to the strong tier, while preserving each CLI's native\r\ninterface, tools, sessions, permissions, and authentication.\r\n\r\n| Command | Interface | Authentication | Routing decision |\r\n| --- | --- | --- | --- |\r\n| `jev-claude` | Claude Code | Existing `claude login` | Status line |\r\n| `jev-codex` | OpenAI Codex | Existing `codex login` | Commentary line |\r\n\r\nBoth commands launch the real upstream CLI. Jev only chooses the model for a fresh user turn.\r\n\r\n## Quick start\r\n\r\nRequires Node.js 20.12+ and at least one supported CLI:\r\n[Claude Code](https:\u002F\u002Fcode.claude.com\u002Fdocs\u002Fen\u002Fsetup) or\r\n[OpenAI Codex](https:\u002F\u002Fdevelopers.openai.com\u002Fcodex\u002Fcli).\r\n\r\n### 1. npm package\r\n\r\n```bash\r\nnpm install -g jev-router\r\necho \"JEV_API_KEY=...\" > ~\u002F.jev-router.env\r\n```\r\n\r\n### 2. Local repository\r\n\r\n```bash\r\ngit clone https:\u002F\u002Fgithub.com\u002Fgargpratyush\u002Fjev-router.git\r\ncd jev-router\r\nnpm install\r\nnpm link\r\necho \"JEV_API_KEY=...\" > ~\u002F.jev-router.env\r\n```\r\n\r\nOn Windows PowerShell:\r\n\r\n```powershell\r\nSet-Content \"$HOME\\.jev-router.env\" \"JEV_API_KEY=...\"\r\n```\r\n\r\nGet a key from [TypeSafe](https:\u002F\u002Fdocs.typesafe.ai). Then launch either interface from any\r\nrepository:\r\n\r\n```bash\r\njev-claude\r\njev-codex\r\n```\r\n\r\nNo Anthropic or OpenAI API key is required when the corresponding CLI is already logged in\r\nwith a subscription. Every CLI argument is forwarded:\r\n\r\n```bash\r\njev-claude --resume\r\njev-claude -p \"fix the failing test\"\r\njev-codex resume --last\r\njev-codex exec \"fix the failing test\"\r\n```\r\n\r\nFor a local checkout, `npm link` installs both commands. Without it, run\r\n`node bin\u002Fjev-claude.mjs` or `node bin\u002Fjev-codex.mjs`.\r\n\r\n## Claude Code interface\r\n\r\n![Jev Router in the Claude Code model picker](docs\u002Fmodel-picker.png)\r\n\r\n`jev-claude` launches Claude Code with **Jev Router** selected in `\u002Fmodel`. Selecting another\r\nmodel pauses routing; selecting **Jev Router** resumes it.\r\n\r\nThe injected status line shows the model used for the last turn:\r\n\r\n```text\r\n⚡ haiku p=0.98 · my-project · 8% context\r\n⏸ manual Opus 4.6 · my-project · 21% context\r\n```\r\n\r\nClaude Code otherwise remains unchanged, including its keybindings, tools, permission prompts,\r\n`\u002Fcompact`, `\u002Fresume`, and session handling. An existing custom `statusLine` is preserved;\r\nset `JEV_NO_STATUSLINE=1` to disable Jev's status line.\r\n\r\nThe explanation skill is bundled with the npm package and loaded automatically: run\r\n`\u002Fjev-explain` in `jev-claude`, or `$jev-explain` in `jev-codex`, to see the factors behind\r\nthe last routing decision:\r\n\r\n```text\r\n┌─────────────────────────────────┐\r\n│ Jev Router                      │\r\n│                                 │\r\n│ Jev request                     │\r\n│ Prompt: explain the router      │\r\n│ Current tier: HAIKU             │\r\n│ Context tokens: 6200            │\r\n│                                 │\r\n│ Jev response                    │\r\n│ Task complexity     0.82        │\r\n│ Reasoning required  0.91        │\r\n│ Tool complexity     0.64        │\r\n│ Context size        0.31        │\r\n│                                 │\r\n│ Recommended tier: SONNET        │\r\n│ Selected model: SONNET          │\r\n│                                 │\r\n│ Confidence: 94%                 │\r\n│ Decision: Jev recommendation    │\r\n└─────────────────────────────────┘\r\n```\r\n\r\nThe report is rendered locally from the exact prompt, System One request, and System One\r\nresponse saved when routing occurred. Recent decisions are retained per CLI session; invoking\r\nthe explanation skill does not ask Jev to score the prompt again.\r\n\r\n### Explanation data location\r\n\r\nBoth `jev-claude` and `jev-codex` keep up to 20 recent routing exchanges in one JSON file per\r\nCLI session under Node.js's operating-system temporary directory:\r\n\r\n| Platform | Default location |\r\n| --- | --- |\r\n| Windows | `%TEMP%\\jev-claude\\\u003Csession-id>.json` |\r\n| macOS | `$TMPDIR\u002Fjev-claude\u002F\u003Csession-id>.json` (normally under `\u002Fvar\u002Ffolders\u002F...\u002FT`) |\r\n| Ubuntu\u002FLinux | `${TMPDIR:-\u002Ftmp}\u002Fjev-claude\u002F\u003Csession-id>.json` |\r\n\r\nPrint the exact directory selected on the current machine with:\r\n\r\n```bash\r\nnode -e \"console.log(require('node:path').join(require('node:os').tmpdir(), 'jev-claude'))\"\r\n```\r\n\r\nClaude filenames use Claude Code's session UUID. Codex filenames use\r\n`codex-\u003Cjev-codex-process-id>.json`. These temporary files contain prompt text and Jev's exact\r\nrequest and response, so they are readable only by you (the directory is created with mode 700 and each\r\nfile with 600). Files not updated for 7 days are deleted automatically, and the operating system\r\nmay also remove them during normal temporary-file cleanup.\r\n\r\n> Choosing a model with `Enter` can save it as Claude Code's default. `jev-claude` restores\r\n> the previous default on exit so `jev-router` cannot break plain `claude`.\r\n\r\n## OpenAI Codex interface\r\n\r\n![Jev Router in the OpenAI Codex model picker](docs\u002Fcodex-model-picker.png)\r\n\r\n`jev-codex` launches Codex with a temporary **Jev Router** provider and selects `jev-router`.\r\nThe native `\u002Fmodel` picker still contains the models available to the account. Selecting a\r\nconcrete model pauses routing; selecting **Jev Router** resumes it.\r\n\r\nEach fresh decision appears as Codex commentary:\r\n\r\n```text\r\n[Jev] routed this turn to gpt-5.6-sol (jev, confidence 0.91).\r\n```\r\n\r\n`jev-codex` installs or refreshes the packaged `$jev-explain` skill when it starts, so it is\r\navailable from any repository without separate setup.\r\n\r\nCodex's footer shows `jev-router` because it displays the selected picker entry,\r\nnot the model chosen behind that provider. If Jev is unavailable, the commentary names the\r\nfallback model and explains how to set `JEV_API_KEY`.\r\n\r\n## How it works\r\n\r\nEach command starts a loopback proxy, launches the real CLI, and forwards the CLI's existing\r\nauthorization headers without reading, storing, or modifying them.\r\n\r\n```text\r\nyou -> Claude Code -> jev-claude proxy -> Anthropic\r\n                         |\r\n                         +-> Jev: choose a tier\r\n\r\nyou -> OpenAI Codex -> jev-codex proxy -> OpenAI\r\n                         |\r\n                         +-> Jev: choose a tier\r\n```\r\n\r\nClaude Code uses `ANTHROPIC_BASE_URL`; Codex uses a temporary custom provider with\r\n`requires_openai_auth=true`. Claude and Codex both use `jev-router` as the\r\nrouting sentinel.\r\nAny concrete model selected by the user passes through unchanged.\r\n\r\n## Routing policy\r\n\r\nOne Jev call per fresh user turn selects a shared abstract tier:\r\n\r\n| Tier | Claude Code default | Codex default |\r\n| --- | --- | --- |\r\n| Fast | Haiku | `gpt-5.6-luna` |\r\n| Balanced | Sonnet | `gpt-5.6-terra` |\r\n| Strong | Opus | `gpt-5.6-sol` |\r\n| Long | Fable | `gpt-6-astra` |\r\n\r\n`src\u002Fpolicy.mjs` then applies these rules:\r\n\r\n- explicit requests such as `use opus`, `use luna`, or `use strong` win;\r\n- failure, timeout, or an unrecognised Jev answer keeps the current model;\r\n- low confidence never downgrades and caps upgrades at the balanced tier;\r\n- large conversations refuse downgrades that would waste more prompt-cache work than they save;\r\n- unavailable tiers step upward rather than silently choosing a weaker model;\r\n- the long tier is disabled unless `JEV_ALLOW_FABLE=1`.\r\n\r\nTool-loop continuations keep the tier chosen at the start of the turn. Main conversations and\r\nsub-agents are pinned separately. Routing is fail-open: Jev failure never blocks the CLI.\r\n\r\n## Configuration\r\n\r\n| Variable | Interface | Effect |\r\n| --- | --- | --- |\r\n| `JEV_API_KEY` | Both | Enables routing. `TYPESAFE_API_KEY` also works. |\r\n| `JEV_ALLOW_FABLE` | Both | Enables the opt-in long tier. |\r\n| `JEV_DEBUG` | Both | Logs decisions and rewrites to `~\u002F.jev-claude.log` in interactive sessions. |\r\n| `JEV_DUMP` | Both | Dumps request bodies for debugging wire-format changes. |\r\n| `JEV_NO_STATUSLINE` | Claude | Disables the injected Claude status line. |\r\n| `JEV_CODEX_FAST_MODEL` | Codex | Fast model; defaults to `gpt-5.6-luna`. |\r\n| `JEV_CODEX_BALANCED_MODEL` | Codex | Balanced model; defaults to `gpt-5.6-terra`. |\r\n| `JEV_CODEX_STRONG_MODEL` | Codex | Strong model; defaults to `gpt-5.6-sol`. |\r\n| `JEV_CODEX_LONG_MODEL` | Codex | Long model; defaults to `gpt-6-astra`. |\r\n\r\nExisting environment variables have highest precedence, followed by `.env` in the launch\r\ndirectory, `~\u002F.jev-router.env`, and the legacy `~\u002F.jev-claude.env`.\r\n\r\nTier definitions, Jev's question, confidence thresholds, and timeouts live in `src\u002Fconfig.mjs`.\r\nBoth launchers send Jev the exact models in the signed-in account's native catalog, so model\r\nversions such as `claude-opus-4-8` and `claude-opus-5` remain separate choices. Static model\r\nids are used only until the CLI fetches its catalog.\r\n\r\n## Compatibility notes\r\n\r\n- Claude Code needs schema normalisation for older MCP JSON Schema fields when a custom base\r\n  URL is active.\r\n- Claude request fields unsupported by a routed tier, such as adaptive thinking on Haiku,\r\n  are removed before forwarding.\r\n- Codex's current request format stores tool definitions inside its Responses API input.\r\n- Codex's ChatGPT backend may stream SSE without a `Content-Type` header; the proxy detects\r\n  the event stream from its first frame.\r\n- Codex workspace-specific enterprise origins are internal to its built-in provider and\r\n  cannot be reproduced by a custom provider.\r\n\r\n## Development\r\n\r\n```bash\r\nnpm install\r\necho \"JEV_API_KEY=...\" > .env\r\n\r\nnpm test\r\nnode test\u002Flive-routing.mjs\r\nnode bin\u002Fjev-claude.mjs -p \"what is 2+2?\"\r\nnode bin\u002Fjev-codex.mjs exec \"what is 2+2?\"\r\n```\r\n\r\nThe test suite covers shared policy, both request formats, model rewriting, capability\r\nhandling, settings restoration, Codex authentication forwarding, native model-picker\r\ninjection, and decision display.\r\n\r\n## Limitations\r\n\r\n- The user's prompt text is sent to TypeSafe for the routing decision. Nothing else is.\r\n- Jev adds latency only to the first request of a turn; tool-loop continuations add none.\r\n- Claude Code and Codex request formats are not public contracts. Use `JEV_DUMP` to diagnose\r\n  upstream changes.\r\n- Developed and tested on Windows against Claude Code v2.1.101 and OpenAI Codex v0.154.0.\r\n\r\n## Contributing\r\n\r\nIssues and pull requests are welcome. Use [Issues](https:\u002F\u002Fgithub.com\u002Fgargpratyush\u002Fjev-router\u002Fissues)\r\nto report bugs, request improvements, or ask questions. Include the relevant Claude Code or\r\nCodex version, reproduction steps, expected behavior, and useful logs with secrets removed.\r\n\r\nFor a pull request:\r\n\r\n1. Open an issue first - all PRs by contributors should be linked with an approved issue. Explain the problem and validation in the issue description.\r\n2. Fork the repository and create a focused branch from `master`.\r\n3. Make the smallest change that solves the problem.\r\n4. Run `npm test` and include tests for non-trivial behavior changes.\r\n5. Claude\u002FCopilot\u002FCodex shall not be the contributors. \r\n\r\nPlease do not commit API keys or other secrets. All contributions require review, and only the\r\nrepository owner can merge pull requests.\r\n\r\n## License\r\n\r\nMIT\r\n",2,"2026-09-19 02:30:08","CREATED_QUERY"]