Documentation

Jevia documentation

View .md

Jevia is an adaptive, outcome-based router for coding harnesses. Start with the CLI, connect the models and agents you already use, then feed recorded observations and optional known outcomes into later routing decisions.

With jevia run, the CLI handles execution and recording automatically. Extra verification and feedback are optional. See automatic CLI execution below for setup, release availability, and verification limits.

01

Install and validate

Install the CLI, create local policy, and verify one live Jev request.

CLI quickstart
curl -fsSL https://jevia.dev/install.sh | shjevia --versionjevia initexport TYPESAFE_API_KEY="your-key"jevia checkjevia route "fix the flaky integration test"
Windows PowerShell quickstart
irm https://jevia.dev/install.ps1 | iexjevia --versionjevia init$env:TYPESAFE_API_KEY = "your-key"jevia checkjevia route "fix the flaky integration test"
Two diagnostics

jevia doctor checks local configuration and storage without calling Jev. jevia check performs one live routing round trip without saving a synthetic run.

02

Route, run, and inspect

Use routing on its own, or let Jevia supervise the complete harness workflow.

Core CLI workflow
jevia route "investigate the failing integration test"jevia route --json "investigate the failing integration test"jevia run agent "investigate the failing integration test"jevia runsjevia runs show <run-id>jevia stats --json
route <task>

Select a capability tier and save the routing decision as a new run.

run <harness> <task>

Route, launch, and record automatically; extra verification is opt-in.

runs [--json]

List recent runs, lifecycle state, quality evidence, and execution observations.

runs show <run-id>

Inspect one complete versioned record, including execution and outcome evidence.

stats [--limit N] [--json]

Summarize routing decisions, trusted outcomes, manual feedback, and cache hits.

Automation

Add --json where supported for stable machine-readable output. Run jevia <command> --help for every command-specific option.

03

How adaptive routing works

Recorded activity informs routing without pretending every completed run is a successful task.

01 Route

Jevia selects one configured capability tier for the current task.

02 Execute

Your chosen harness maps that tier to a concrete model and performs the work.

03 Observe

Record process facts and supported native activity automatically; keep uncertain outcomes unknown.

04 Optional outcome

Add feedback or extra verification only when wanted; neither is required for passive history.

05 Adapt

Use recorded observations and known outcomes as separate context for later routing decisions.

Observed is not verified

Jevia does not decide that its own output is good. A completed verifier or explicit application or human feedback can supply a known outcome. Without either, recorded activity still informs routing as passive context.

04

Connect any harness

Map stable capability tiers to the model names your harness accepts.

Preview a harness adapter
jevia harness presetsjevia harness setup codex --preset codex \  --model fast=your-fast-model \  --model balanced=your-balanced-model \  --model strong=your-strong-model

Built-in shell-free templates cover Codex, Claude Code, OpenCode, and Gemini CLI. A preset supplies only the command and non-interactive argument shape; you still choose model IDs, credentials, permissions, and verification. The preview is offline and changes no files.

Apply, validate, and run

Harness workflow
# Review the generated TOML, then save itjevia harness setup codex --preset codex \  --model fast=your-fast-model \  --model balanced=your-balanced-model \  --model strong=your-strong-model --apply
# Validate templates and local executable paths without launching anythingjevia harness check codexjevia harness check codex --json
# Route and launch the configured harnessjevia run codex "investigate the failing integration test"

Changing an existing adapter also requires --replace. Extra arguments for the configured harness can follow -- on jevia run. Jevia executes argument arrays directly without shell expansion. Use explicit --command and repeated --arg values when a preset does not match your installed harness or when connecting another agent.

Agnostic by design

This works with Claude Code, Codex, OpenCode, Gemini CLI, Cursor Agent, Copilot CLI, Aider, Goose, Amp, or a custom runner. Jevia learns from outcomes, while the adapter owns the tier-to-model mapping.

Automatic CLI pipeline

Configure your installed harness, credentials, and model mappings once. Then jevia run routes the task, launches the agent, and records execution facts and supported native events in your selected storage backend. No manual feedback or runs complete step is needed. Recorded history informs later routing automatically, even when task success is unknown.

Run a configured harness
jevia run codex "fix the failing test"

CLI 0.1.6: additional verification is opt-in. CLI 0.1.4–0.1.5 enabled test discovery by default; existing explicit checks are preserved. Set auto_verify = true only if you want root Rust/Node test discovery, or configure your own optional verifier. Recording itself works with Python, Go, and mixed-language projects without tests. Passing tests is evidence, not proof of every requirement.

CLI 0.1.6 native capture supports Claude Code 2.1.251+, tested Codex 0.158.x on macOS/Linux (with normal hook trust), and OpenCode v1 ≥ 1.18.33. Unsupported versions and remote sessions keep process-level observations. Capture is best-effort: reported models, switches, and tool activity do not prove which model solved a task. Raw prompts, tool contents, and transcripts are not retained. Inspect execution.observations for coverage and recorded events. Back up history and upgrade to CLI 0.1.6 and SDK 0.1.2 together for schema 6. See the capture contract and limits.

Optional verification runs when the agent process/session finishes, not after each internal message or tool call. Jevia does not install the agent or test runner, supply credentials, bypass agent permission prompts, or retry failed work. Prepare project dependencies first. See the CLI setup and verification reference for supported tests, deadlines, and opt-in settings.

05

Use the Node.js SDK

Embed the same routing and feedback loop directly inside a harness.

Install the Node.js SDK
npm install jevia
Programmatic harness integration
import { JeviaClient } from "jevia";
const jevia = new JeviaClient({ cwd: process.cwd() });const task = "fix the flaky integration test";const route = await jevia.route(task);
const result = await runYourHarness({  task,  tier: route.tier,  runId: route.run_id,});
// Optional: your adapter may expose a known outcome; no verifier is required.if (result.outcome === "success" || result.outcome === "failure") {  await jevia.feedback(route.run_id, result.outcome);}
// Recorded outcomes are included automatically in the next decision.const next = await jevia.route("fix another parser regression");

SDK 0.1.2: optionally call recordExecution() after app-owned work finishes to save execution facts and bounded events. These are application-reported observations, not verified success. Later route() calls automatically reuse the history; feedback and extra verification remain optional. Exact retries are idempotent; existing supervised executions cannot be overwritten. Do not call this after jevia run, which records automatically. Requires CLI 0.1.6+ and SDK 0.1.2+ with schema 6. See the SDK recording example.

For SDK integrations, map Jevia's tier to your harness model and let your application run the work. Feedback and verification are optional. SDK routing does not launch an agent or run tests. If your application knows the result, it can report it without a verifier; no human feedback prompt is required. Skipping feedback still records the route with an unknown outcome and does not block later routing.

Your adapter can call Codex, Claude Code, OpenCode, Gemini CLI, Cursor Agent, Copilot CLI, Aider, Goose, Amp, or a custom runner. The optional result.outcome field above comes from your own adapter; Jevia does not infer it from a successful function return. Report only known outcomes, and do not submit feedback again after a supervised CLI run.

Recorded outcomes inform the next route

The SDK does not require Jevia's built-in verifier. Your application can use tests, acceptance checks, or a user-approved result and record success or failure. This is labeled manual evidence (application-reported), not CLI verification. Use unknownwhen the result is uncertain. The next route() automatically includes eligible recorded outcomes from the same JSONL, SQLite, or PostgreSQL history, including CLI-verified results, plus a separate window of passive execution observations. No manual cache clearing is needed: evidence is part of the cache key.

Unknown outcomes are not quality labels. Finished process-only runs still supply observations; active and routed-only runs do not. The SDK does not instrument agents your application launches outside jevia run. [router].history_limit bounds each history window: default 20, maximum 100, or 0 to disable it. This is decision context, not model training or a guarantee of better choices. Live requests send eligible historical task text, outcome metadata, and bounded native summaries to Jev; feedback reasons, session IDs, and raw event lists stay in storage. [privacy].store_task_text = false omits task text from new records, not older history or the current routing request.

The SDK invokes the local CLI through its shell-free JSON interface. Install the CLI first and keep it on PATH; npm installation never runs a binary downloader. Pass an AbortSignal in method options when the caller needs cancellation.

version(options?)

Return the installed Jevia CLI version after validating its output.

route(task, options?)

Choose a capability tier using recent eligible recorded outcomes automatically, and return the typed route record.

feedback(runId, outcome, options?)

Optionally record an application-reported outcome. No verifier is required; omitting feedback leaves the outcome unknown.

runs(options?)

List recent route records with a configurable positive result limit.

show(runId, options?)

Read one complete record, including lifecycle and outcome evidence.

complete(runId, outcome, options)

Finish externally executed work after confirming it has stopped; requires CLI 0.1.4 or newer.

setupStorage(target, options?)

Preview SQLite or PostgreSQL setup and apply it only with confirmation.

checkStorage(options?)

Check selected storage or deeply validate it without a write probe.

Configure storage from Node.js

Node API availability

These methods are available in jevia@0.1.1. They require CLI 0.1.2 or newer and an existing jevia init project. Creating a client never connects to a database or changes storage.

SDK: SQLite setup
// Relative paths resolve from the client cwd; absolute paths also work.const target = { backend: "sqlite", path: ".data/jevia/history.db" } as const;
// Preview only: no database connection or file changes.console.log(await jevia.setupStorage(target, { importJsonl: true }));
// Stop project writers and supervisors before applying.await jevia.setupStorage(target, {  apply: true,  confirmStopped: true,  importJsonl: true,});console.log(await jevia.checkStorage());console.log(await jevia.checkStorage({ deep: true }));
SDK: PostgreSQL setup
// Set JEVIA_DATABASE_URL before creating the client.const target = {  backend: "postgres",  project: "my-app",  urlEnv: "JEVIA_DATABASE_URL",} as const;
console.log(await jevia.setupStorage(target)); // Preview first.

Setup stays preview-first and returns human-readable reports. Keep database credentials in the named environment variable, use signal for cancellation, and raise the client's timeoutMs for large imports. After cancellation or failure, inspect the config and destination before retrying.

Cancellation and errors

SDK error handling
import { JeviaClient, JeviaCommandError } from "jevia";
try {  await jevia.route(task, { signal: controller.signal });} catch (error) {  if (error instanceof JeviaCommandError) {    console.error(error.message, error.exitCode, error.signal);  }}
Log the safe fields

Log the message, exit code, and signal. Raw command, stdout, and stderr can contain sensitive values and are for private debugging only. Invalid JSON or invalid complete records raise JeviaProtocolError.

06

Verify and report outcomes

Only trusted, known results teach later routing decisions.

These commands are for externally executed work or corrections. A supervised jevia run records its outcome automatically; no manual feedback step is needed afterward.

Record and inspect feedback
jevia feedback <run-id> successjevia feedback <run-id> failure --reason "The integration test still fails"jevia feedback <run-id> unknown --reason "No reliable verification result"jevia runs show <run-id>
verification

A configured or detected verifier completed and produced a known result. Eligible for learning.

manual

An application or person explicitly recorded success or failure. Eligible for learning.

process_exit

The harness process exited. Useful passive context, but not proof of task success.

unknown

No trusted result is known. It stays out of the adaptive evidence set.

Corrections stay visible

Changing a known outcome requires --reason. Jevia keeps the prior value in its feedback history. Setting unknown removes the run from learning without erasing its execution evidence.

07

Choose and configure storage

Start with local JSONL, then move deliberately when your history needs more.

JSONL · default

No setup required. Local history lives in .jevia/runs.jsonl and is ignored by Git.

SQLite · local database

Defaults to .jevia/jevia.db; choose another project-relative or absolute file with --path.

PostgreSQL · shared evidence

Records live in your configured database under the selected project namespace.

What a stored run looks like

Every backend preserves the same logical record. JSONL writes one compact JSON object per line to .jevia/runs.jsonl; this example uses explicitly enabled verification and is expanded for readability. SQLite and PostgreSQL store the equivalent fields while keeping the same lifecycle and outcome-evidence semantics.

One completed run · expanded JSONL
{  "schema_version": 6,  "run_id": "7b65a69a-0a6f-4a89-bd73-88f090954dd9",  "tier": "balanced",  "suggested_tier": "balanced",  "confidence": 0.84,  "probabilities": {    "fast": 0.1,    "balanced": 0.84,    "strong": 0.06  },  "fallback_applied": false,  "jev_model": "jev-latest",  "created_at_ms": 1790700000000,  "source": "live",  "task": "fix the flaky integration test",  "outcome": "success",  "execution": {    "harness": "codex",    "model": "provider/standard",    "duration_ms": 48231,    "exit_code": 0,    "observations": { "source": null, "status": "unsupported", "events": [] },    "verification": {      "command": "pnpm",      "launched": true,      "duration_ms": 6842,      "exit_code": 0    }  },  "lifecycle": {    "state": "completed",    "started_at_ms": 1790700001120,    "finished_at_ms": 1790700056193  },  "outcome_evidence": {    "source": "verification",    "recorded_at_ms": 1790700056193  }}
The verifier supplies the outcome

Jev selects the tier, but it does not declare its own work successful. Here, the verifier exited successfully, so outcome_evidence.source is verification. Set privacy.store_task_text = falseto persist task: null instead of the raw task.

Move a project to SQLite

SQLite setup
# Choose a project-relative or absolute SQLite file; preview writes nothingjevia storage setup sqlite \  --path .data/jevia/history.db \  --import-jsonl
# Stop Jevia writers and supervisors, then apply the same reviewed pathjevia storage setup sqlite \  --path .data/jevia/history.db \  --import-jsonl --apply --confirm-stoppedjevia storage checkjevia stats

Without --path, SQLite uses .jevia/jevia.db. Relative paths resolve from the discovered project root, even when the command runs in a subdirectory; absolute paths are also accepted. Omit --import-jsonlwhen the current JSONL history is empty. The source file is never deleted or rewritten.

Saved in .jevia/config.toml
[storage]backend = "sqlite"url = "sqlite://.data/jevia/history.db"
Protect custom locations

Files under .jevia are ignored automatically. If you choose a path elsewhere, add the database, its WAL/SHM sidecars, and run-lock files to your ignore rules and protect the containing directory.

Share evidence with PostgreSQL

PostgreSQL setup
export JEVIA_DATABASE_URL="postgresql://..."
# Preview first; the URL stays in the environmentjevia storage setup postgres --project my-project --import-jsonl
# Stop writers and supervisors before applyingjevia storage setup postgres --project my-project --import-jsonl --apply --confirm-stoppedjevia storage check

Keep credentials in the environment, never in config or CLI arguments. Pass--url-env MY_DATABASE_URL to name a different variable. Jevia requires a direct or session-pooled connection, not a transaction-mode pooler.

Check, export, and import

Storage tools
jevia storage checkjevia storage check --deepjevia storage export --output .jevia/snapshot.jsonljevia storage import-jsonl --from <file>jevia storage import-jsonl --from <file> --apply
Preview before apply

Setup and import commands do no writes until --apply. A deep check reads complete history without a write probe or automatic repair. Stop writers before migration and keep the source as a recovery copy.

08

Cache, diagnostics, and recovery

Keep routing responsive while preserving explicit operational control.

Routing cache

Cache controls
jevia cache statusjevia cache clearjevia route --no-cache "force one live routing decision"

The default cache holds 256 decisions for 15 minutes. Each hit still gets a fresh run ID. New outcomes and policy, model, or harness changes produce new cache keys; cache errors fail open to a live routing request.

Run lifecycle and recovery

routed → running → verifying → completed

Lifecycle records execution progress separately from whether the task actually succeeded.

runs recover <run-id>

Mark an abandoned active run interrupted after confirming no supervisor still owns its lease.

run … --non-interactive

Enable process-tree supervision and bounded execution or verification timeouts for headless work.

Bounded headless run
jevia run agent "fix the parser" --non-interactive --timeout-seconds 300 --verification-timeout-seconds 120

History maintenance

Preview-first maintenance
# Preview and repair a recoverable JSONL tailjevia runs repairjevia runs repair --apply
# Preview and archive older eligible terminal recordsjevia runs archive --keep 1000jevia runs archive --keep 1000 --apply
Nothing is automatic

Repair is JSONL-only. Archive works with every backend and writes recovery files before removing eligible old records. Neither command applies changes until you repeat the reviewed command with --apply.