Reference

September 20, 2026 · View on GitHub

Every lens takes a plain object and returns typed decisions. Scores, probabilities, confidence, and fallback reasons are available where relevant to the lens. They support inspection and evaluation; none proves that a decision is correct.

Usher.admit — J3

optiondefaultmeaning
goalwhat the expensive model is trying to do
candidates{ id, text, tokens?, meta? }[]
budget4000ceiling on admitted tokens
threshold1.5minimum score on the levels scale
minConfidence0.55below this, the score is not trusted
failOpentrueunsure verdicts and provider failures let material through, subject to budget
checkNeedtruealso ask whether the goal needs context at all
needThreshold0.15turn everyone away below this need probability
levels3 defaultsoverride the relevance rubric
batchSize64maximum candidates per request; byte limits may split earlier

Verdict reasons: admitted · low-confidence-admitted · below-threshold · low-confidence-turned-away · over-budget · goal-needs-no-context · provider-error-admitted

Router.route — J1

optiondefaultmeaning
turnthe user's turn, verbatim
contextrepo facts, open files, recent errors
tiersDEFAULT_TIERS{ id, description, meta? }[] — the description is the rubric
fallbacklast tierused when confidence is below the floor
minConfidence0.55
probeWorktruealso return needsFiles and needsTools

DEFAULT_TIERS: trivial (haiku) · mechanical (sonnet) · judgement (opus) · hard (opus, high effort). Replace the descriptions with your own boundary cases — that is where routing accuracy comes from.

Gate.select — J2

optiondefaultmeaning
turn
catalog{ id, name, summary, detail? }[]
maxSelected1how many to surface
shortlist3how many stage two reads properly; 0 skips stage two
minConfidence0.55
failOpenfalsefails closed — unsure surfaces nothing
checkNeedtrue
batchSize96

Reasons: selected · none-needed · low-confidence · empty-catalog · provider-error

Filter.apply — J4

Everything admit takes, plus:

optiondefaultmeaning
chunkstool output, split into pieces
sourcefile · shell · web · mcp · anything
screenon for web/mcprun J7 before judging relevance
dropBlockedtrueremove blocked chunks rather than passing them flagged

Compactor.triage — J5

optiondefaultmeaning
goalwhat the session is still trying to accomplish
blockstranscript blocks, oldest first
keepBudget8000soft ceiling for trusted verbatim blocks; overflow becomes shorten
minConfidence0.55
failOpentrueunsure → keep verbatim, including over budget
batchSize48

retained combines surviving blocks in original order. keep, shortened, and drop are separate groups for inspection. headChars defaults to 300. Shortened blocks carry updated token estimates; untouched blocks retain caller token counts. keepBudget does not cap total returned context. Protect required instructions and tool call/result pairs in your harness; this API handles plain text blocks.

StopGate.check — J6

optiondefaultmeaning
goalwhat the agent set out to do
workwhat it has done so far
nextActionsharpens the repetition check
metThreshold0.8
loopThreshold0.75

Reasons: goal-met · looping · needs-user · continue · unavailable

Screen.check — J7

optiondefaultmeaning
itemscontent to screen
sourcewhere it came from
blockThreshold0.8
reviewThreshold0.45
batchSize32

Verdicts: pass · review · block · unavailable

Client

new JevUsher({
  apiKey,          // default: JEV_API_KEY, then TYPESAFE_API_KEY
  baseUrl,         // default https://api.typesafe.ai/v1
  model,           // default jev-1.13.0
  timeoutMs,       // default 30_000
  maxRetries,      // default 3 — retries selected transient statuses with backoff
  provider,        // swap the whole transport, e.g. a stub in tests
  prices,          // { jev: 0.042, target: 15 } for the ledger
});

CLI

jev-usher install [--global]    wire the Claude Code hooks
jev-usher uninstall [--global]  remove only jev-usher hooks
jev-usher doctor                key, connectivity, store contents
jev-usher report                estimated selected volume and JEV usage
jev-usher ui [--port 4318]       local test UI on 127.0.0.1
jev-usher claude [--no-route] [--model MODEL] "prompt" [-- Claude options]

jev-usher hook <event>          user-prompt-submit | pre-tool-use | post-tool-use | stop
jev-usher route|admit|gate|screen|stop|compact    JSON in, JSON out
echo '{"goal":"g","candidates":[{"id":"a","text":"..."}]}' | node bin/jev-usher.mjs admit
echo '{"turn":"rename the getter"}' | node bin/jev-usher.mjs route

The examples above run from a built checkout. See local UI and Claude Code setup for configuration and privacy boundaries.

The canonical package and command are jev-usher; the main TypeScript class is JevUsher. The jevusher command and earlier Jevusher, JevusherConfig, and JevusherError exports remain compatibility aliases. Existing JEVUSHER_* environment variables and the ~/.claude/jevusher storage directory retain their names so saved recovery references continue to work.

Optional decision cache

import { DecisionCache, JevClient, JevUsher } from "jev-usher";
const provider = new DecisionCache(new JevClient(), { maxEntries: 128, ttlMs: 60_000 });
const usher = new JevUsher({ provider });

The in-memory cache requires a pinned model such as jev-1.13.0. Its key hashes the entire serialized request, including state, IDs, numbers, instructions, criteria, and model. Reordering object keys can cause a miss; it never removes fields or performs fuzzy matching. Scope each instance to one caller/tenant. It expires decisions and evicts least-recently-used entries. Failed or malformed responses are not cached. The instance retains decisions in memory, not raw state or credentials in files. clear() removes entries; stats() exposes hits, misses, evictions, and entry count. Hits report zero incremental provider usage.

This is opt-in for long-lived applications. It does not improve hit rate across separate command-hook processes and does not coalesce simultaneous misses. Ledger request counts are logical evaluations; use cache stats and provider billing when distinguishing cache hits from actual requests. Replay verifies application behavior; detecting model drift requires fresh model calls on a fixed evaluation set.