btx-skill-jev-judge
A Claude Code plugin with one skill, jev-judge, and the Python package behind it,
btx-skill-jev-judge. When the same judgment repeats over many items, such as labeling 600 support
tickets, Claude hands it to TypeSafe's Jev through a tested
command-line tool. That beats reading every item into its own context or calling a large model
once per item.
Jev returns typed answers with probabilities: yes/no, one of a set of options, or a position on a
scale. Input is billed per token and output is free; run reports the run's cost, estimated from the
per-million-token price set in the code (PRICE_PER_MTOK in domain/summary.py).
Install in Claude Code
The repository is its own plugin marketplace, so installing takes two steps: register the marketplace once, then install the plugin from it. Set up the prerequisites (uv and a TypeSafe key) first; the plugin installs without them, but the skill cannot run.
In a Claude Code session
/plugin marketplace add bitranox/btx-skill-jev-judge
/plugin install btx-skill-jev-judge@btx-skill-jev-judge
/plugin install opens the plugin panel, where you choose the scope:
| Scope | Who gets it | Recorded in |
|---|---|---|
| user | you, in every project | ~/.claude/settings.json |
| project | everyone working in this repo | .claude/settings.json (commit it) |
| local | you, in this repo only | .claude/settings.local.json |
With project scope, committing the settings file turns the plugin on for your collaborators but does not download it: each of them runs the install command once.
Closing the panel loads the plugin into the open session. If it does not appear, run
/reload-plugins.
From your shell
Useful in a setup script:
claude plugin marketplace add bitranox/btx-skill-jev-judge
claude plugin install btx-skill-jev-judge@btx-skill-jev-judge # user scope
claude plugin install btx-skill-jev-judge@btx-skill-jev-judge --scope project # or project scope
Plugins installed this way load in the next session, or after /reload-plugins in an open one.
Check that it works
claude plugin list shows btx-skill-jev-judge@btx-skill-jev-judge. In a session, describe a matching task
("tag these 600 support tickets by product area") and Claude loads the skill, or invoke it
directly with /btx-skill-jev-judge:jev-judge. Its first step runs check-key,
which tells you whether the TypeSafe key is usable without printing it.
Updates
Auto-update is off by default for marketplaces other than Anthropic's own. Update by hand:
claude plugin marketplace update btx-skill-jev-judge
claude plugin update btx-skill-jev-judge@btx-skill-jev-judge
or turn auto-update on in /plugin, on the Marketplaces tab. An open session keeps the version
it loaded until you run /reload-plugins.
Uninstall
claude plugin uninstall btx-skill-jev-judge@btx-skill-jev-judge # add --scope project for a project install
claude plugin marketplace remove btx-skill-jev-judge # also uninstalls its plugins
From a local clone
To try a change before it is pushed, register the directory instead of the GitHub repository.
Start a relative path with ./, or Claude Code reads it as owner/repo:
/plugin marketplace add ./btx-skill-jev-judge
/plugin install btx-skill-jev-judge@btx-skill-jev-judge
Prerequisites
-
uv. It fetches Python and the CLI's dependencies on first use.
-
A TypeSafe API key from https://console.typesafe.ai/keys. Lookup order: an exported
TYPESAFE_API_KEY, then a.envin the current directory or a parent, then~/.credentials/typesafe.keywith mode 600 (see SECURITY.md). To create the file, run this, then paste the key in with an editor:mkdir -p -m 700 ~/.credentials && install -m 600 /dev/null ~/.credentials/typesafe.key
Installation
The command-line tool is the PyPI package btx-skill-jev-judge. It installs three command names for
one program: jev-judge, btx-skill-jev-judge and btx_skill_jev_judge.
uvx --from btx-skill-jev-judge jev-judge --help # run once, nothing installed
uv tool install btx-skill-jev-judge # or install it on your PATH
jev-judge --version
pip, pipx and other methods are in INSTALL.md. Python 3.10 or newer is required.
Why we recommend uv: supply-chain protection
This repository commits a uv.lock. It pins every package the project needs, transitive
dependencies included, to an exact version and to the hashes of that version's files. The
exclude-newer setting under [tool.uv] in pyproject.toml adds a cooldown: uv leaves any
release younger than that out of the lock. CI installs from the lock, so a hijacked release that
gets pulled again within the cooldown never reaches our builds, and a file whose hash does not
match is refused.
That protection stays in this repository. The installable package declares only lower bounds
(>=) for its dependencies, so a plain pip install takes the newest release of every transitive
dependency at the moment you run it. If one of them was hijacked an hour earlier, you get the
hijacked version. pipx install and uv tool install without options do the same.
To install the command line tool with a cooldown of your own (uv then skips any release younger than 7 days, transitive ones included), or to run the exact tree our CI tests:
uv tool install --exclude-newer "7 days" btx_skill_jev_judge
git clone https://github.com/bitranox/btx-skill-jev-judge.git && cd btx-skill-jev-judge && uv sync --locked && uv run btx_skill_jev_judge --help
If you depend on btx_skill_jev_judge in your own project, give that project the same cooldown (7 days here, as
an example) and commit the uv.lock that uv add btx_skill_jev_judge writes:
[tool.uv]
exclude-newer = "7 days"
Quick Start
Write one JSON object per item, with an id and a state of named fields:
{"id": "t-1", "state": {"title": "Login loops after SSO", "body": "I sign in and land on the login page again."}}
{"id": "t-2", "state": {"title": "Add dark mode", "body": "Please add a dark theme."}}
Write the questions once. noul is Jev's yes/no type and answers with the probability of yes:
[{"id": "is_bug", "type": "noul", "instructions": "Does `body` describe something that is broken?"}]
Then check the key, try ten items, run all of them and summarize:
jev-judge check-key
jev-judge run --items items.jsonl --questions questions.json --out rows.jsonl --pilot 10
jev-judge run --items items.jsonl --questions questions.json --out rows.jsonl
jev-judge summarize --rows rows.jsonl
| Command | Purpose |
|---|---|
run |
Asks the same questions about every item and writes one result row per item |
summarize |
Shows each question's spread, flags questions whose answers never move, lists rows to check |
check-key |
Reports whether a usable key is configured and where it came from, without printing the key |
run, summarize and check-key take --json for an {ok, command, data, skipped} envelope on stdout, or
--json-bare for the data alone (also on failure). Diagnostics always go to stderr.
| Exit code | Meaning |
|---|---|
| 0 | Yes: every item answered, no flat question, a key is present |
| 1 | No: some row failed, a question looks flat, or check-key found no key |
| 2 | Usage, input or IO error (also an out-of-range flag); stderr says jev-judge: <reason> |
| 78 | Broken configuration, such as attempts above 10; stderr says Error: <reason> |
A click usage error (a bad option type, an unknown option, --json together with --json-bare)
exits 2 and prints no JSON, even under --json-bare.
Before any item leaves the machine, every string in its state is redacted: common secret formats
such as tokens, private keys and passwords in URLs, plus the API key itself. Requests share one
rate limiter; the default 20 requests per second stays under Jev's documented 40, and rate
is configurable. Transient failures (rate
limits, overloads, 5xx errors, timeouts, dropped connections) are retried with backoff, and
Retry-After is respected. Any other failure becomes a row that records the reason.
<command> --help lists every option.
Configuration
Defaults for run and summarize live in the [judge] and [summary] sections of a layered
configuration (files, .env, environment variables). A command-line flag always wins. The API key
(exported TYPESAFE_API_KEY, else a .env in the current directory or a parent, else
~/.credentials/typesafe.key; see SECURITY.md) is never a configuration value: a
judge.api_key entry is refused with exit 78. Environment variables look like
BTX_SKILL_JEV_JUDGE___JUDGE__RATE=5. Every key, default and layer is in CONFIG.md.
Architecture
The package follows a layered ports-and-adapters layout, and import-linter enforces it in the
test run:
| Layer | Package | Holds |
|---|---|---|
| Composition | composition/ |
Wires adapters to ports |
| Adapters | adapters/ |
CLI, Jev HTTP client, key lookup, files, configuration, logging |
| Application | application/ |
The judge use case and the port protocols |
| Domain | domain/ |
Questions, items, rows, redaction, summary; no I/O |
pyproject.toml defines two contracts. "Clean Architecture layers" lets each layer import only
the layers below it, in the order composition, adapters, application, domain. "Domain is pure"
also keeps the domain from importing adapters or composition. Tests use real seams: a loopback
HTTP stub stands in for Jev, CliRunner drives the CLI, and a fake client drives the use case. See
docs/systemdesign/module_reference.md.
Further Documentation
- INSTALL.md: every way to install the CLI
- CONFIG.md: configuration sections, layers and environment variables
- DEVELOPMENT.md: the dev loop, gates and releasing
- CONTRIBUTING.md: how to send a change
- SECURITY.md: key handling, redaction and reporting a vulnerability
- docs/systemdesign/module_reference.md: module map
- docs/measurements.md: one live check against the real API
- CHANGELOG.md: what changed in each release
- ai-stance.md and ai-transparency.md: why and where AI was used here
License
MIT
Metadata
Release files for btx-skill-jev-judge 0.2.6
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| btx_skill_jev_judge-0.2.6.tar.gz | 335.3 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| btx_skill_jev_judge-0.2.6-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 432.3 kB
Release files / btx_skill_jev_judge-0.2.6.tar.gz
| Download URL | btx_skill_jev_judge-0.2.6.tar.gz |
|---|---|
| Size | 335.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
d2a13e775daec6e7d7a456efc7b21bd0ebcd910c191aead5fe4c2b1e7ce0b512
|
|
BLAKE2b-256 checksum How to use checksums |
a9d5e1f53150c92afcaf0ce1e7b749a1e7791ed708e7837f0eb79033867e21bc
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 13, 2026.
Transparency logRelease files / btx_skill_jev_judge-0.2.6-py3-none-any.whl
| Download URL | btx_skill_jev_judge-0.2.6-py3-none-any.whl |
|---|---|
| Size | 97.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
1db1b5b9722040bf4d7909c7ce218e662a9c635134762609a74d7c60630b32dd
|
|
BLAKE2b-256 checksum How to use checksums |
9801b4044e80acc0d1c9de351e701b394ff2bff3a27132536dd5ffc0eeefe7f1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 13, 2026.
Transparency log