Skip to main content
Glama

jev-classifier connects your coding agent to Jev, a model that predicts which tool to use next. Start by watching its suggestions. Then, where supported, let it choose the tool your agent calls. Every decision goes into a log you can review.

Keep using your agent's model and login. Configure a separate key for Jev during setup.

The original idea and inspiration for jev-classifier come from jev-eval-agent by vinilana. This project brings that approach to a local gateway and MCP tools for coding agents.

Connection

Agents

How it works

Proxy

Codex, Claude Code, Grok Build, OpenCode

Requests pass through jev-classifier on their way to the model

MCP tool

Cursor, Antigravity

The agent calls Jev when it wants a suggestion

Codex Responses Lite records suggestions without forcing a tool. OpenCode supports API keys with its v1 configuration. Cursor and Antigravity choose when to ask Jev and whether to follow it.

Quick start

1. Install

Install Node.js 22 or newer, then install jev-classifier globally from npm:

npm install --global jev-classifier
jev-classifier --help

The global install makes jev-classifier available from every project and keeps desktop startup entries tied to a stable installation. No repository checkout or build step is required.

Install the latest release:

npm install --global jev-classifier@latest

Before uninstalling, stop the gateway and remove its optional desktop startup entry:

jev-classifier stop
jev-classifier startup disable
npm uninstall --global jev-classifier

If no gateway is running or startup was never enabled, the first two commands may report that there is nothing to stop or disable. Your saved settings and logs are left in place.

Use this only when developing the project or testing unreleased changes:

git clone https://github.com/felpsdev/jev-classifier.git
cd jev-classifier
npm ci
npm run build
node dist/cli.js setup

In the commands below, replace jev-classifier with node dist/cli.js when running from source.

2. Configure

jev-classifier setup

Setup walks you through choosing a Jev provider, entering its key, and picking your agent. You don't need to set environment variables. Your choices are saved for all projects.

Choose Observe to watch Jev's decisions first. If you don't have a key yet, choose Offline test to check the connection without calling Jev. Review your settings, then save. Running jev-classifier without a command opens the interactive menu.

3. Connect an agent

Agent

Command

Codex

jev-classifier run codex

Claude Code

jev-classifier run claude

Grok Build

jev-classifier run grok

OpenCode

jev-classifier run opencode

Cursor

jev-classifier connect cursor

Antigravity

jev-classifier connect antigravity

For Codex, Claude Code, Grok Build, and OpenCode, run starts the gateway and opens your agent. If the gateway is already running, it uses that one. Connection settings apply to this session; your agent's configuration files stay as they are.

The gateway keeps running after you close the agent. Stop it with jev-classifier stop. To pass an option to the agent, put it after --:

jev-classifier run codex -- --no-alt-screen

For Cursor and Antigravity, open the editor and reload its MCP servers after connecting.

4. Check that it works

jev-classifier doctor --check
jev-classifier status
jev-classifier logs --follow

doctor --check sends a small request to Jev, which your provider may charge for. In status, watch the request and classification counts increase while your agent works.

For Cursor or Antigravity, ask the agent to call jev_status. To try a prediction, ask it to call jev_choose_next_tool with your task and available tools. Check logs --decisions for the result.

Related MCP server: privatevault-gate

Agent integrations

Codex, Claude Code, and Grok Build

Pick Existing login in setup to use the account you're already signed into. Pick Provider API key to use a separate key for the agent's model. The agent handles sign-in and refreshes its own login. Jev's key is used only for classification.

For manual setup, run jev-classifier config <agent>. You can also expand the connection instructions in Reference. The Grok integration uses the official Grok Build CLI.

OpenCode

Run jev-classifier run opencode. Inside OpenCode:

  1. Use /connect to add an OpenAI, Anthropic, or xAI API key.

  2. Use /models to pick a model from that provider.

  3. Run a task and check the opencode counts in jev-classifier status.

This connection supports OpenCode v1 with API keys. Subscription plugins may send requests directly to the provider and skip the proxy. Other providers and the v2 config format are not supported yet.

The launcher sets OPENCODE_CONFIG_CONTENT for this session. It changes the OpenAI, Anthropic, and xAI base URLs and keeps your other inline options. Managed OpenCode settings can take priority, so check status to confirm that requests reach the proxy.

See OpenCode's provider settings and config priority.

Cursor and Antigravity

Run jev-classifier connect cursor or jev-classifier connect antigravity, then open the editor and reload its MCP servers. The command adds jev-classifier to your global MCP config, keeps other servers, and backs up the file before changing it.

The editor starts jev-classifier when it needs the MCP tools. You don't need to run serve. It reads your saved Jev settings; your editor keeps its own login.

Tool

What to ask

jev_status

"Call jev_status to check the connection."

jev_choose_next_tool

"Ask jev_choose_next_tool which tool to use next. Include my task, available tools, and completed actions."

The agent decides when to ask Jev and whether to follow its suggestion. Jev sees only the context included in the call, which is sent to your chosen provider. It cannot watch the whole session or force the agent's next step.

Use logs --decisions to review suggestions under cursor or antigravity. Restart the editor's MCP server after changing Jev settings. This connection works with local agents; remote cloud agents cannot use the local process.

Editor

Config file

Cursor

~/.cursor/mcp.json

Antigravity

~/.gemini/config/mcp_config.json

If the current Antigravity file is missing, an existing ~/.gemini/antigravity/mcp_config.json is used.

Running connect again leaves an identical entry alone. If the file contains invalid JSON, the command leaves it untouched. Run config <editor> to print the entry and add it yourself. run cursor and run antigravity perform the same setup; open the editor yourself afterward.

MCP suggestions have applied: false in the decision log. They appear in logs, metrics, and the dashboard. The HTTP gateway's counters cover only proxy traffic.

See Cursor MCP and Antigravity MCP.

Run agents without Jev

Turn the proxy off for future run commands, or bypass it for one session:

jev-classifier proxy off
jev-classifier run claude
jev-classifier run codex
jev-classifier proxy on
jev-classifier run claude --no-proxy
jev-classifier proxy status

The main interactive menu also offers Turn Jev proxy on or off. The saved preference applies to Codex, Claude, Grok and OpenCode. Direct launches need no Jev key and do not start or contact its gateway. Agents manage their own authentication; --auth applies only to proxy launches. Codex uses its built-in openai provider in direct mode.

Restart your agent to switch an existing session. Disabling the proxy does not stop a running gateway or change desktop startup; use stop and startup disable for those separately. Cursor and Antigravity use MCP instead of the proxy; disable their Jev entry in the editor's MCP settings to stop using it.

Direct launches remove inherited Jev URLs from agent environment variables and OpenCode's inline provider settings, without changing the parent terminal. If you manually saved Jev URLs in Claude, Grok or OpenCode configuration files, remove those overrides there too. To launch Codex directly outside this wrapper, restore its model_provider from jev to openai in its configuration. Environment and explicit --env-file settings override the saved preference; --no-proxy always bypasses it for that launch.

Where Jev runs

Choose a Jev provider in setup. Your coding agent keeps using its own model provider.

Jev provider

API-key variable

Default Jev model

TypeSafe

TYPESAFE_API_KEY

jev-latest

OpenRouter

OPENROUTER_API_KEY

~typesafe/jev-latest

Vercel AI Gateway

AI_GATEWAY_API_KEY

typesafe-ai/jev

OpenRouter and Vercel AI Gateway handle Jev's predictions only. They don't run your agent's coding model through this tool.

For proxy connections, choose how much control to give Jev:

Mode

What happens

Observe (shadow)

Record Jev's prediction, let the agent choose, and compare the two

Enforce (enforce)

Set tool_choice to Jev's prediction when confidence is high enough

Start with Observe. Change modes in setup, or pass --shadow to observe for a run. Enforce is the default when no mode is configured. It adds a hint instead of forcing a tool when confidence is low.

jev-classifier keeps the full tool list in every request, so that part of the prompt cache stays valid. It also checks whether the requested work is done before accepting Jev's suggestion to respond. If classification fails, the original request continues to the model.

Codex Responses Lite always observes. Requests with duplicate tool names or previous_response_id also fall back to Observe. Check shadowReason in the decision log.

The proxy turns the conversation into a RouterState, asks Jev which tool comes next and whether the work is done, then checks both answers. This follows jev-eval-agent.

In enforce mode, respond_to_user maps to tool_choice: auto. If confidence is below MIN_CONFIDENCE, the proxy adds a hint with the three most likely tools. The done gate can override a suggestion to respond when work remains.

OpenRouter uses its alpha Decisions API with choice and noul questions. Vercel uses its evaluation API with choice and boolean. The boolean probability is used to check completion.

If the provider omits confidence, the chosen option's probability is used. Missing or invalid probabilities count as a classification failure.

Gateway and startup

jev-classifier serve (or start) frees the original terminal and reuses an existing gateway. Use serve --foreground to keep the server in the current terminal.

Platform

Default start

Automatic startup

Windows

Gateway in a separate PowerShell window

Current user's Startup shortcut

macOS

Background gateway with a Terminal log viewer

User LaunchAgent at next sign-in

Linux desktop

Background gateway with a detected terminal log viewer

XDG desktop autostart at next sign-in

Linux headless / SSH

Background gateway; use logs --follow

Desktop autostart does not run without a graphical login

Linux detects x-terminal-emulator, gnome-terminal, konsole, or xterm. If no display or usable terminal is available, the gateway continues in the background. On macOS/Linux, closing the log viewer leaves the gateway running; use stop to end it. On Windows, closing the gateway window also stops its process. Background console output is saved as gateway-console.log alongside the settings; routine activity and errors are also in the rotating event log.

Choose startup behavior in setup or use these commands:

jev-classifier startup               # interactive Enable / Disable menu
jev-classifier startup enable        # register for the next desktop sign-in
jev-classifier startup disable
jev-classifier startup status

Startup applies to your user account and needs no administrator access. It starts the gateway when you sign in to your desktop, using your saved settings. It does not run before login. Disabling startup leaves a running gateway active. Enable it again after moving this checkout or changing where Node is installed.

macOS uses ~/Library/LaunchAgents/ai.jev.classifier.plist. Linux uses $XDG_CONFIG_HOME/autostart/jev-classifier.desktop, or ~/.config/autostart/ by default.

The stop command uses a local control token saved beside your settings. Health responses do not include that token. If a gateway was started with an older version, close it in its original terminal once. The new start/stop commands can then manage the next instance.

Monitoring

Terminal logs use aligned time, level, and agent columns. Event details use labeled fields such as chosen=Read, confidence=98%, and jev=124ms. Long messages wrap under the message column; narrow terminals show the details below the event header. Saved logs include the local date as well as the time. logs --json keeps the original machine-readable records.

Command

Shows

doctor

Installation, saved configuration, and gateway availability

doctor --check

Whether Jev responds to a test request

status --watch

Requests, predictions, errors, and the last decision for each agent

logs --follow

Live gateway and MCP activity; Ctrl+C stops viewing

logs --lines 100

Recent saved activity, including prior runs

logs --decisions

Classification history

metrics

Decision totals grouped by agent, model, and mode

ui

Dashboard at http://localhost:8090

Prefix commands with jev-classifier. Use --json with doctor, status, settings, logs, or startup for machine-readable output. --no-color or NO_COLOR disables colors. Output redirected to a file uses plain text. status --watch --json emits one JSON object per line.

doctor --check tests the settings loaded for that command. If a gateway is already running, it may still have older settings; doctor reports when the provider or model differs. Watch the classification count in status to confirm that requests are reaching Jev. For MCP suggestions, use logs, metrics, or the dashboard.

Gateway and MCP events are saved in gateway.jsonl beside the global settings. It rotates at 5 MB and retains one previous segment. Decision history lives in decisions.jsonl, unless customized. Detached macOS/Linux launches also save console output in gateway-console.log.

Open http://127.0.0.1:8080/__jev/health or run:

Invoke-RestMethod http://127.0.0.1:8080/__jev/health

requests counts incoming proxy traffic; classified counts successful Jev decisions. classificationFailures, noTools, and invalidJson explain requests that passed through without classification. jevConfigured reports whether the selected classifier has a key (not whether authentication succeeded); jevProvider and jevModel identify the classifier backend, without exposing credentials; stub identifies offline routing. Counters reset on restart. Decisions are written after the upstream response ends. The proxy also prints when classification starts and why it skips a request.

Codex 0.154 Responses Lite puts tool declarations in input items with type: "additional_tools", often wrapped in namespaces. The proxy reads those declarations as well as root-level tools, without moving or changing them. Responses Lite currently always uses shadow mode, even when JEV_MODE=enforce: forcing a tool in live Codex sessions coincided with repeated intermediate messages without a final answer. The proxy still asks Jev and logs its prediction, but forwards the original request byte for byte. The exact cause of that behavior remains under investigation. The decision log records mode: "shadow", applied: false, and shadowReason. Duplicate tool names across declarations also fall back to shadow mode.

Settings

Run jev-classifier setup to change preferences. Choices are saved globally:

Platform

Configuration file

Windows

%APPDATA%/jev-classifier/config.json

macOS / Linux

$XDG_CONFIG_HOME/jev-classifier/config.json, or ~/.config/jev-classifier/config.json

Keys are saved as plain text in this file. On macOS/Linux, a new config file is readable and writable only by its owner. On Windows, it uses the user folder's permissions. Setup hides keys on the review screen, and settings --json hides their values too.

Logs live beside the config file by default. Set JEV_CONFIG_HOME to use a different folder.

Your saved settings work from any project. Before you save them for the first time, the CLI can load a local .env and import it during setup. After that, use --env-file .env if you want to load a project's settings.

When the same setting appears in several places, the first one in this list wins:

  1. Command flags.

  2. Existing environment variables.

  3. An explicitly selected environment file.

  4. Saved global preferences.

--global skips automatic .env loading. Restart the gateway or editor's MCP server after changing settings. The CLI trusts certificates installed on your computer when Node supports it; you can change that in advanced settings.

Reference

Login and token refresh stay in the agent. The proxy forwards each request's credentials; it does not read credential files, copy refresh tokens, or implement another browser login. Configure a separate Jev key in setup (TypeSafe, OpenRouter, or Vercel AI Gateway), unless using JEV_STUB=1.

Agent

Local base URL

Session destination

Claude Code

http://127.0.0.1:8080/oauth/claude

https://api.anthropic.com

Codex

http://127.0.0.1:8080/oauth/codex

https://chatgpt.com/backend-api/codex

Official Grok Build

http://127.0.0.1:8080/oauth/grok/v1

https://cli-chat-proxy.grok.com/v1

Claude Code, in PowerShell:

Remove-Item Env:ANTHROPIC_API_KEY -ErrorAction SilentlyContinue
Remove-Item Env:ANTHROPIC_AUTH_TOKEN -ErrorAction SilentlyContinue
$env:ANTHROPIC_BASE_URL = "http://127.0.0.1:8080/oauth/claude"
claude

Use /login if needed. Disable an existing apiKeyHelper when using subscription login. Claude's OAuth capability headers are preserved. Claude gateway authentication.

Codex: merge into the user-level $CODEX_HOME/config.toml (default ~/.codex/config.toml):

model_provider = "jev" # top level, before any [table]

[model_providers.jev]
name = "jev-classifier"
base_url = "http://127.0.0.1:8080/oauth/codex"
wire_api = "responses"
requires_openai_auth = true
supports_websockets = false

No env_key for this flow. Run codex login if needed and use codex login status to confirm ChatGPT login, then start codex. API-key login belongs on /api/codex/v1 instead. Codex authentication.

Official Grok Build, in PowerShell:

Remove-Item Env:XAI_API_KEY -ErrorAction SilentlyContinue
Remove-Item Env:GROK_MODELS_BASE_URL -ErrorAction SilentlyContinue
grok login # only if not already signed in
$env:GROK_CLI_CHAT_PROXY_BASE_URL = "http://127.0.0.1:8080/oauth/grok/v1"
grok

Remove per-model api_key / env_key overrides to use the session. This is the official Grok Build, not third-party CLIs also named grok. Endpoint variable confirmed in the installed Grok 1.0.34 embedded documentation. Grok authentication.

Session routes ignore UPSTREAM, API upstream variables, and UPSTREAM_API_KEY, so gateway settings cannot replace a session token or redirect it to another provider. Trusted deployments can override CLAUDE_OAUTH_UPSTREAM, CODEX_OAUTH_UPSTREAM, or GROK_OAUTH_UPSTREAM explicitly. Auxiliary routes (models, compact, token counting) use the same selected destination. A 401 is passed back to the agent; the proxy does not retry or refresh credentials. Capture files omit auth/account headers and query strings; request bodies can still contain private prompts and code.

Direct OAuth integrations are Claude Code, Codex, and official Grok Build. Their API-key routes are /api/claude, /api/codex, and /api/grok; append the API path such as /v1/responses. env_key is the name of an environment variable, never its secret value. OpenRouter and Vercel AI Gateway are classifier backends only; they are not agent destinations.

Validation uses local mock upstreams (routing, token changes, 401, headers, logging, JSON/SSE). Live subscription inference has not been verified. Codex uses HTTP/SSE here; WebSockets are unsupported.

Use setup for everyday changes. For scripts and automation, you can also use environment variables. For example, save this in a file and load it with --env-file .env:

JEV_PROVIDER=openrouter
OPENROUTER_API_KEY=your-openrouter-key

For Vercel, use JEV_PROVIDER=vercel and AI_GATEWAY_API_KEY. No upstream override is needed. JEV_MODEL selects the classifier model, not the coding model.

Var

Default

Use

JEV_PROVIDER

typesafe

Jev backend: typesafe, openrouter, or vercel

TYPESAFE_API_KEY

(unset)

classifier key for TypeSafe

OPENROUTER_API_KEY

(unset)

classifier key for OpenRouter

AI_GATEWAY_API_KEY

(unset)

classifier key for Vercel AI Gateway

JEV_API_KEY

(unset)

optional override for the selected classifier key

JEV_MODEL

provider-specific

Jev model ID override

JEV_STUB

0

1 routes without Jev, no API key needed

JEV_MODE

enforce

enforce rewrites tool_choice; shadow only logs

JEV_PROXY

1

0 launches agents directly, without the Jev gateway

DONE_THRESHOLD

0.5

minimum probability that the requested work is done

MIN_CONFIDENCE

0.5

below this, no tool is forced

PORT

8080

proxy port

ANTHROPIC_UPSTREAM

https://api.anthropic.com

upstream for /v1/messages

OPENAI_UPSTREAM

https://api.openai.com

upstream for /v1/responses

XAI_UPSTREAM

https://api.x.ai

upstream for /v1/chat/completions

UPSTREAM

Unset

overrides API-key route destinations; ignored on /oauth/*

UPSTREAM_API_KEY

Unset

replaces API-route credentials; ignored on /oauth/*

CLAUDE_OAUTH_UPSTREAM

https://api.anthropic.com

session destination for /oauth/claude

CODEX_OAUTH_UPSTREAM

https://chatgpt.com/backend-api/codex

session destination for /oauth/codex

GROK_OAUTH_UPSTREAM

https://cli-chat-proxy.grok.com

session destination for /oauth/grok

JEV_LOG

global config directory + /decisions.jsonl

decision log

JEV_DEFAULT_AGENT

codex

default for run

JEV_AUTH

oauth

authentication for Codex, Claude Code, and Grok Build

JEV_SYSTEM_CA

1

trust system certificates when supported

JEV_CONFIG_HOME

OS-specific

global settings directory

Metrics and the dashboard read the same decision JSONL. Example record:

{
  "ts": "2026-09-17T12:00:00.000Z",
  "agent": "anthropic",
  "model": "example-model",
  "session": "example-session",
  "mode": "enforce",
  "chosen": "Edit",
  "confidence": 0.82,
  "done": 0.1,
  "gated": false,
  "truncated": false,
  "top3": [
    {
      "name": "Edit",
      "p": 0.82
    }
  ],
  "jevMs": 180,
  "upstreamMs": 2400,
  "toolsCount": 14,
  "applied": true,
  "actual": "Edit",
  "match": true
}

jev-classifier serve --capture saves requests in .jev-classifier/captures/. It removes authentication and account headers, plus query strings. Request bodies can still contain private prompts and code. Review captures before sharing them.

Symptom

Check

No proxy requests appear

Start the agent through run; confirm the gateway port and selected provider

Jev is configured but classifications fail

Run doctor --check; inspect provider/model settings and logs

Changes do not affect the running session

Restart the gateway or editor's MCP server

Cursor or Antigravity has no HTTP counters

Check MCP discovery with jev_status and activity in logs --decisions

Codex reports an observe-mode fallback

Responses Lite intentionally preserves requests; inspect shadowReason

A managed Windows computer reports certificate errors

Check system trust; Node 22.19+ also supports node --use-system-ca dist/cli.js serve

Limits

  • Jev accepts up to 255 choices, including respond_to_user. Larger catalogs are shortened for classification and marked truncated. The full tool list still goes to your agent's model.

  • Each prediction takes time. Check jevMs in the log and the p95 timing in metrics to see how much delay Jev adds.

Development

npm install
npm run typecheck
npm test

CI is configured for Windows, macOS, and Linux with Node 22 and 24. Tests cover protocol forwarding, MCP stdio discovery and calls, configuration merging, process control, and startup-file generation. The new integrations were developed and tested on Windows; native macOS/Linux desktop launches and real Cursor/Antigravity sessions still require platform validation. OpenCode's configuration and mock upstream routing are tested separately from live provider inference.

License

MIT.

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    B
    maintenance
    Exposes codebase memory as native tools for AI agents, enabling queries, feature tracing, impact analysis, and alignment verification.
    4
    AGPL 3.0
  • A
    license
    A
    quality
    C
    maintenance
    Enables AI coding agents to route tool calls through PrivateVault's enforcement engine before execution, so disallowed actions are blocked and every decision is recorded as a verifiable, hash-chained audit record.
    5
    21 npm
    MIT