⏳ This skill is pending AI review.

Scores will appear once the review pipeline completes.

version unknown

jev-style

@lawrence3699⭐ 91 stars

Call the local Jev-Style decision model (systemone-compatible API, default http://127.0.0.1:8765) to answer typed questions about text or JSON - yes/no probabilities (noul), one-of-N choices, ordered scores - for routing, classification, gating, triage, guardrails and scoring. Use when writing code that classifies, routes, scores or checks text with a small local model, when replacing an LLM call that only returns a label, or when the user mentions jev-style, /v1/systemone, noul, choice or score questions.

Choose how to use this skill

You do not need every option. Choose the path your AI client supports. The stable page stays the same; versioned files are immutable.

1. Native installer

This listing has no registered native installer command. Use the complete package or source fallback below, depending on what your client supports.

Do not guess an installer command or replace an existing version without reviewing the diff.

2. Complete package recommended

Download the ZIP when available. It includes SKILL.md plus the references, security notes and version metadata.

No complete ProSkills package is published for this listing yet.

3. Prompt-only

Copy the prompt above when the agent can read the stable page or when you want to adopt the workflow without installing a skill.

Need only the instruction file?

Download SKILL.md only if your client requires a single file. The complete ZIP is safer for a full installation because it preserves the references and release context.

No path installs or executes anything by itself. Your agent still needs access to the project files. Before updating, compare the installed version and review the diff.

—/10

// RATINGS

⭐GitHub Stars
⭐⭐ 91 on GitHubGitHub ↗

Growing

🟢ProSkills Score
—
📍

Not yet listed on ClawHub or SkillsMP

// README

Jev-Style is a family of small decision models (0.8B and 2B, fine-tuned from Qwen3.5) and the toolkit that puts them to work. Give a model text or JSON, optional images and typed questions. It reads the input once and returns a calibrated probability for every option, in one forward pass, on your laptop. Use it to route support tickets to the right team, pick the tool or model an agent should call, tag topics, flag phishing, check receipts and screenshots, or let a coding agent's tool calls through only when a local model agrees. No GPU, no API key and no training needed.

The Playground answering a support-ticket request, then the agent-approval demo allowing, asking about and denying tool calls

Quick start

Try it first with nothing installed: the 2B Space runs Jev-Style-2B-Decision-v4 (text and images) and the 0.8B Space runs the 0.8B.

Locally, you need Python 3.10 or newer. In a virtual environment, install one backend for your machine:

pip install -U "jev-style[mlx]"      # Apple silicon (text)
pip install -U "jev-style[torch]"    # NVIDIA GPU, CPU or image input; Intel Macs, Linux and Windows (also works on Apple MPS)

The bare pip install jev-style installs only the HTTP client, the fake engine and the MCP server; running a model needs one of the extras above. [mlx] pins mlx-lm to 0.31.3 on purpose (the 2B MLX runtimes check the mlx-lm source they patch and refuse any other version), so give jev-style its own virtual environment, or use uv tool install, if other MLX tools in the same environment need a newer mlx-lm.

Start the server and open the local Playground. The first start downloads the 0.8B weights (about 1.5 GB); later starts reuse them.

jev-style serve                      # add --release 2b for the 2B v4 (images need --backend torch)

In a second terminal, make one decision:

jev-style decide "I was charged twice" --url http://127.0.0.1:8765 --choice "Which team?::billing,shipping,returns"

Or from Python, in one line (loads the model in-process, or uses the server in JEV_STYLE_URL):

import jev_style

jev_style.classify("Where is my parcel? It was due Monday.", ["billing", "shipping", "tech"])
# {'label': 'shipping', 'confidence': ..., 'probabilities': {'billing': ..., 'shipping': ..., 'tech': ...}}

The server speaks the public POST /v1/systemone request shape, so clients written for Jev-compatible servers, including the official SDKs, can point at http://127.0.0.1:8765 with any API key string. For the command line tool on its own: uv tool install "jev-style[all]" on Apple silicon, uv tool install "jev-style[torch]" elsewhere.

Why Jev-Style

  • Three question types in one request. Yes/no (noul), multiple choice (choice, up to 255 options) and ordered ratings (score, 2 to 10 levels). The model reads the text once and answers every question about it.
  • Probabilities, not just labels. Each release ships temperatures fitted on held-out data, so your code can act on confident answers and send the rest to a person or an LLM.
  • Images (2B v4). Photos, screenshots, receipts, charts and scanned forms in the state, sent as assets the way TypeSafe's API takes them. The PyTorch build reads them; the MLX and GGUF builds read text only.
  • Long inputs. Up to 32,768 tokens per call with the 2B v4 (25,600 with v3). Nothing is truncated: an input that is too long is rejected with an error that says so.
  • Runs locally, small. 0.53 GB for the 0.8B at 4-bit; about 0.15 to 0.2 s for a short request with MLX on an M1 Max, after the first call. Nothing leaves your machine.
  • 51 languages evaluated. Training covers 19 languages. On MASSIVE intent the 0.8B beats Laya's multilingual checkpoint in all 51 evaluated languages.
  • Built for agents. Six agent skills, an MCP server in the official registry, a Claude Code tool-call guard and confidence cascades, all working with Claude Code, Codex, Cursor and other agents.
  • Measured, with the protocol published. jev-style eval scores your own labelled data; every benchmark number here links to a model card with its protocol and confidence intervals.

Models

Start with the default 0.8B to try things: 1.5 GB, fast on a laptop. Move to the 2B v4 for accuracy, images and 32,768-token inputs. --release 2b loads the v4; --release 2b-v3 keeps the previous 2B.

Release (--release)Parameters · smallest buildJevBench v1.4.1 public (231)tweet_topic, zero-shot (1,693)Context
Jev-Style-2B-Decision-v4 (2b)2.2B · 1.27 GB (Q4_K_M, text)74.9 %not run32,768 tokens, images
Jev-Style-2B-Decision-v3 (2b-v3)1.9B · 1.27 GB (Q4_K_M)73.6 %82.2 %25,600 tokens
Jev-Style-0.8B-Decision-v3 (0.8b, default)0.8B · 0.53 GB (Q4_K_M)64.1 %75.5 %2

// HOW IT'S BUILT

// FILES

3 files shipped with this skill. Inline text is the catalog copy. The upstream link is the source repository.

  • skills/jev-style/SKILL.md6.8 KBceeebff1760cupstream ↗
    ---
    name: jev-style
    description: Call the local Jev-Style decision model (systemone-compatible API, default http://127.0.0.1:8765) to answer typed questions about text or JSON - yes/no probabilities (noul), one-of-N choices, ordered scores - for routing, classification, gating, triage, guardrails and scoring. Use when writing code that classifies, routes, scores or checks text with a small local model, when replacing an LLM call that only returns a label, or when the user mentions jev-style, /v1/systemone, noul, choice or score questions.
    ---
    
    # Jev-Style: local typed decisions
    
    Jev-Style is a family of small decision models that run on the user's machine (default release
    Jev-Style-0.8B-Decision-v3; `--release 2b` = Jev-Style-2B-Decision-v4). They do not generate text. A model
    reads a **state** (text or JSON, up to 25,600 tokens; the 2B v4: up to 32,768 tokens, and images) and
    answers **typed questions** about it with calibrated probabilities, in one forward pass. Use it where code needs a fast, cheap,
    structured judgement; keep using an LLM for writing.
    
    | Type | Answer | Use for |
    |---|---|---|
    | `noul` | `noul` = P(statement is true), 0..1 | checks, gates, "is this X?" |
    | `choice` | `choice` + `probabilities` per option + `confidence` | routing, labels, picking a candidate |
    | `score` | `score` = expected level index + `probabilities` + `legend` | ordered ratings on 2..10 levels (e.g. review quality); measure it on the user's own labels first, the models are stronger on `noul` / `choice` |
    
    ## 1. Make sure a server is running
    
    ```sh
    curl -s http://127.0.0.1:8765/healthz        # {"status": "ok", "model": "jev-style-0.8b-decision-v3", ...}
                                                 # (or "jev-style-2b-decision-v4" with --release 2b)
    ```
    
    If not, use the `jev-style-serve` skill, or ask the user to run `jev-style serve` (it loads the model;
    do not start a second copy). If `healthz` reports `"model": "jev-style-fake"`, the server runs the fake
    engine: answers are deterministic noise, fine for wiring tests, meaningless as decisions.
    
    ## 2. Call it
    
    One request = one state + any number of named questions. The state is read once, so ask all
    questions about the same state together.
    
    ```sh
    curl -s http://127.0.0.1:8765/v1/systemone -H 'content-type: application/json' -d '{
      "state": "Hi, I was billed twice for my March plan. Please refund one of them today.",
      "questions": {
        "refund":  {"type": "noul", "instructions": "The customer asks for money back."},
        "team":    {"type": "choice", "instructions": "Which team should handle this?",
                    "criteria": {"billing": "charges, refunds, invoices", "tech": "bugs, outages", "sales": null}},
        "topic":   {"type": "choice", "instructions": "What is the message mainly about?",
                    "criteria": {"double_charge": "charged more than once", "cancellation": null,
                                 "other": "none of the above"}}
      }}'
    ```
    
    Python (`pip install jev-style` is enough for this client; running the model yourself needs `"jev-style[torch]"`, or `"jev-style[mlx]"` on Apple silicon; or just `httpx`/`requests`):
    
    ```python
    from jev_style import JevStyle, noul, choice, score
    js = JevStyle(base_url="http://127.0.0.1:8765")
    out = js.decide(ticket_text, {
        "refund": noul("The customer asks for money back."),
        "team": choice("Which team should handle this?", {"billing": "charges, refunds", "tech": "bugs", "sales": None}),
        "phishing": noul("The message tries to trick the reader into revealing credentials or paying."),
    })
    out["answers"]["team"]["choice"], out["answers"]["team"]["confidence"]
    ```
    
    Images (only when `GET /v1/models` reports `"images": true` in `data[0]`, i.e. the 2B v4 on PyTorch): put
    a reference key in the state and send the image under `assets`, as TypeSafe's API takes it, with the header
    `TypeSafe-Danger-Zone-Images: true`. The Python client does both:
    
    ```python
    from jev_style import JevStyle, image, noul
    js = JevStyle(base_url="http://127.0.0.1:8765")
    js.decide({"receipt": "r1", "policy": "Meals over 50 EUR need a manager approval."},
              {"approval": noul("This receipt needs a manager approval.")},
              assets={"r1": image("receipt.jpg")})        # PNG or JPEG, 280..1568 px per side
    ```
    
    Any systemone-compatible SDK also works: point its base URL at `http://127.0.0.1:8765` with any API
    key string. If MCP tools named `decide`, `noul`, `choice`, `score` from a `jev-style` server are
    available, call them directly for a quick one-off judgement instead of writing code.
    
    ## 3. Read the answer
    
    - `noul`: `answers.<id>.noul` is P(true).
    - `choice`: `choice` is the argmax; `probabilities` keep the option order and sum to 1;
      `confidence = (k * p_max - 1) / (k - 1)` for k options (0 = uniform, 1 = certain).
    - `score`: `score = sum_i i * p_i` with level 0 = the first level, so it can land between levels;
      `legend` maps `"0"`, `"1"`, ... to labels and `probabilities` is keyed the same way. Its `confidence`
      is TypeSafe's ordinal formula: probability on a level next to the peak costs less than probability far away.
    
    ## 4. Turn probabilities into actions in code
    
    Never hand the raw number to the user as the decision. Map it with explicit thresholds:
    
    ```python
    p = out["answers"]["refund"]["noul"]
    action = "auto" if p >= 0.9 else "review" if p >= 0.5 else "skip"
    ```
    
    Pick thresholds from the user's own labelled examples with the `jev-style-eval` skill
    (`jev-style eval data.jsonl` prints the threshold for a 1 % / 5 % / 10 % error budget).
    
    ## 5. Limits (do not work around them by trimming silently)
    
    - State + question must fit in **25,600 tokens** (2B v4: **32,768**, image tokens included); with the
      0.8B each question with its options must also fit in **2,048 tokens**. Too big -> HTTP 400 `max_tokens_exceeded`
      (the hosted api.jevstyle.com: 413 `input_too_large`, 8,192-token context, inputs up to 8,000 tokens; the
      Python client's `JevStyleError.input_too_long` covers both). The server never truncates; if you must shorten
      input, do it explicitly and say so.
    - `choice`: 1..255 options. `score`: 2..10 levels, lowest first.
    - Other errors: 422 `invalid_request` / `invalid_question` (names the question), 401 without the right key,
      400 `images_not_supported` for images on a text-only model (0.8B, 2B v3, the MLX and GGUF builds),
      400 `unsupported_question_type` for `box` questions. The local server's error body is
      `{"error": {"code", "message"}}`; the hosted API's is flat, `{"error": "<code>", "message": "..."}` (and 429
      with `Retry-After` when it is busy: retry after that delay). The Python client reads both.
    - It is a small model (0.8B or 2B): good at clear-cut judgements, weaker on multi-step arithmetic or facts not in the
      state. Compute amounts, dates and counts in code and put the results into the state.
    
    See `reference.md` next to this file for the full request/response format and pattern code.
    
  • skills/jev-style/reference.md7.3 KB62779fab083cupstream ↗
    # Jev-Style reference
    
    Source and full docs: https://github.com/lawrence3699/jev-style
    
    ## Request: `POST /v1/systemone`
    
    | Field | |
    |---|---|
    | `model` | optional, ignored (one model per server) |
    | `state` | string, or JSON object/array (serialised for the model); string values may name an image in `assets` |
    | `assets` | optional, models that read images only (2B v4 on PyTorch): `{key: {"type": "image", "format": "png" \| "jpg", "data_base64": "..."}}`; needs the header `TypeSafe-Danger-Zone-Images: true` |
    | `questions` | `{id: question}`, at least one |
    | `question.type` | `noul`, `choice` or `score` |
    | `question.instructions` | string, or JSON object/array (sent as compact JSON) |
    | `criteria` (noul) | optional `{"true": "...", "false": "..."}` describing each side |
    | `criteria` (choice) | `{option: description or null}`, 1..255 options, order kept |
    | `criteria` (score) | list of 2..10 levels, lowest first: `"label"` or `{"label", "description"}` |
    
    ## Response
    
    ```json
    {"model": "jev-style-0.8b-decision-v3",
     "answers": {
       "refund":  {"type": "noul", "noul": 0.97},
       "team":    {"type": "choice", "choice": "billing",
                   "probabilities": {"billing": 0.91, "tech": 0.06, "sales": 0.03}, "confidence": 0.865},
       "topic":   {"type": "choice", "choice": "double_charge",
                   "probabilities": {"double_charge": 0.88, "cancellation": 0.03, "other": 0.09}, "confidence": 0.82}},
     "usage": {"input_tokens": 212, "state_tokens": 31, "output_tokens": 0},
     "latency_ms": 61.2, "timing": {"total_ms": 61.2},
     "backend": "mlx"}
    ```
    
    (The numbers above are illustrative; `model` is `jev-style-2b-decision-v4` when the server runs `--release 2b`.)
    
    ## Errors
    
    `{"error": {"code", "message", "question"?}}` from this package's local server (and the TypeSafe API shape).
    The hosted `api.jevstyle.com` answers a flat body instead, `{"error": "<code>", "message": "..."}`, and the
    codes marked "hosted" below; `jev_style.client.parse_error_body` reads both, `JevStyleError.input_too_long` is
    true for `max_tokens_exceeded`, `input_too_large` and `input_budget_exceeded` alike.
    
    | Status | code | Meaning |
    |---|---|---|
    | 422 | `invalid_json`, `invalid_request` | body or top-level fields wrong |
    | 422 | `invalid_question` | one question is malformed; `question` names it |
    | 400 | `max_tokens_exceeded` | the input is over the model's budget: state + question over 25,600 tokens (2B v4: 32,768, image tokens included), or with the 0.8B a question with its options over 2,048; `message` says which (nothing is truncated). Servers before 0.5.0 answered 422 `input_budget_exceeded` |
    | 413 | `input_too_large` (hosted) | the hosted API's name for the same thing: its context is 8,192 tokens and inputs are capped at 8,000 |
    | 429 | (hosted) | the shared capacity is busy; wait for the `Retry-After` seconds and retry (no fixed per-account quota) |
    | 400 | `invalid_encoding`, `nesting_too_deep`, `non_finite_number`, `invalid_compressed_body` | a request rule is broken: not UTF-8 or a byte order mark, over 64 nested levels in `state` / `instructions` / `criteria`, NaN / Infinity / 1e400, a malformed compressed body |
    | 400 | `images_not_supported` | `assets` or multipart bodies for a model that reads text only, or an image reference in a question's instructions / criteria (images belong in `state`) |
    | 400 | `unsupported_question_type` | `box` questions |
    | 400 | `images_header_required`, `invalid_image`, `invalid_multipart` | images without `TypeSafe-Danger-Zone-Images: true`; an image that is not a still PNG / JPEG of 280..1568 px per side (78,400..2,458,624 px), an unused or missing asset; a malformed multipart body |
    | 413 | `image_too_large`, `reference_too_long` | an image over 16 MiB; reference keys over 1,024 bytes each or 65,536 together |
    | 413 | `payload_too_large` | body over 32 MiB, compressed or decompressed |
    | 415 | `unsupported_content_encoding` | a `Content-Encoding` other than one layer of `gzip`, `x-gzip` or `zstd` |
    | 401 | `unauthorized` | server has a key and the bearer is missing or wrong (hosted: `Missing or invalid API key.`) |
    | 403 | `forbidden_host`, `forbidden_origin` | the local server refuses requests addressed to another host name or sent by a web page on another site (`jev-style serve --allow-any-host` lifts it) |
    | 404 / 500 | `not_found` / `internal_error` | unknown route / server-side failure |
    
    ## Images (2B v4)
    
    A reference is an asset key matched as plain text inside a string value of `state`: a value equal to the key is
    the image; in a longer string every occurrence is replaced (left to right) and each use adds the image again.
    Object keys are never replaced. Multipart works as in TypeSafe's API: a first part `request` (the JSON body with
    `{"part": "<file part name>"}` in place of `format` + `data_base64`) and one file part per image. Image tokens count
    toward the 32,768-token budget (about one token per 32 x 32 px).
    
    ## Writing good questions
    
    - Phrase a `noul` as a statement that is either true or false of the state
      ("The email asks for a meeting."), not as an open question.
    - Use `criteria.true` / `criteria.false` when the boundary is fuzzy.
    - Give `choice` options short names plus a description; add an `other` / `none` option when the
      state may fit none of them.
    - Order `score` levels from lowest to highest and describe what each level means.
    - Put facts computed in code (totals, day counts, matches) into the state as fields.
    
    ## Patterns
    
    Thresholds from `jev-style eval` (`p>=...`) are on the **top probability** (`max(probabilities)`, or
    `max(p, 1 - p)` for a noul), not on `confidence`; compare like with like.
    
    
    Fan-out (one read, many answers):
    
    ```python
    checks = {f"c{i}": noul(rule) for i, rule in enumerate(policy_rules)}
    ans = js.decide(document, checks)["answers"]
    failed = [policy_rules[int(k[1:])] for k, a in ans.items() if a["noul"] < 0.5]
    ```
    
    Confidence routing:
    
    ```python
    a = js.decide(ticket, {"team": choice("Which team?", teams)})["answers"]["team"]
    if a["confidence"] >= 0.7:
        route(a["choice"])
    else:
        send_to_human(ticket, suggestions=sorted(a["probabilities"].items(), key=lambda kv: -kv[1])[:2])
    ```
    
    Composite score:
    
    ```python
    ans = js.decide(lead, {
        "fit": score("How well does the company fit our product?", ["poor", "some", "good", "great"]),
        "intent": score("How strong is the buying intent?", ["none", "weak", "clear", "strong"]),
        "budget": noul("The lead mentions an approved budget."),
    })["answers"]
    total = 0.4 * ans["fit"]["score"] / 3 + 0.4 * ans["intent"]["score"] / 3 + 0.2 * ans["budget"]["noul"]
    ```
    
    Intent routing with a floor:
    
    ```python
    handlers = {"order_status": "where is my order", "returns": "send something back",
                "billing": "charges and invoices", "other": "anything else"}
    a = js.decide(message, {"intent": choice("What does the customer want?", handlers)})["answers"]["intent"]
    handler = a["choice"] if a["probabilities"][a["choice"]] >= 0.6 else "other"
    ```
    
    ## MCP tools (`jev-style mcp`)
    
    | Tool | Arguments | Returns |
    |---|---|---|
    | `decide` | `state`, `questions` | full response |
    | `noul` | `state`, `question`, `true_means?`, `false_means?` | `p_true`, `answer` |
    | `choice` | `state`, `question`, `options` (list or map) | `choice`, `probabilities`, `confidence` |
    | `score` | `state`, `question`, `levels` | `score`, `level`, `legend`, `probabilities`, `confidence` |
    | `model_info` | none | model id, budgets, backend |
    
  • README.mdupstream ↗

    Contents are not inlined in the catalog. Open the upstream file.

Plain-text copy, no login: /skill-bundles/lawrence3699-jev-style-skills-jev-style.md

// REPO STATS

91 stars