---
title: "Jev przez OpenRouter: konfiguracja w 15 minut i pierwszy test w terminalu i Claude Code"
slug: "jev-openrouter-konfiguracja-claude-code"
date: 2026-09-27
lastUpdated: 2026-10-02
description: "Jev od TypeSafe nie pisze tekstu – podejmuje decyzje. Pokazuję, jak skonfigurować go przez OpenRouter bez waitlisty: klucz z limitem, pierwszy test w terminalu i własny skill w Claude Code. Cały test kosztował $0,00023."
author: "Jakub Krysmalski"
canonical: "https://krysmalski.pl/blog/jev-openrouter-konfiguracja-claude-code"
tags:
  - "AI"
  - "Automatyzacja"
  - "Webdev"
---

Większość modeli AI, z których korzystamy na co dzień, pisze tekst. **Jev** od TypeSafe AI robi coś innego: podejmuje decyzje. Dostaje zamknięte pytanie i odpowiada wyborem z listy, oceną w skali albo „tak/nie”, zawsze z prawdopodobieństwem. Nie wymyśli kategorii, której nie podałeś, a jedna odpowiedź kosztuje ułamek centa.

TypeSafe wstrzymał rejestracje kilka dni po premierze. Jev jest jednak dostępny przez **OpenRouter** – bez waitlisty. W tym poradniku:

1. Utworzymy klucz API z limitem wydatków.
1. Zadamy Jevowi pierwsze pytanie w terminalu.
1. Podepniemy go do **Claude Code** jako skill i sprawdzimy, że agent sam z niego korzysta.

## Czym Jev różni się od ChatGPT?

Jev to pierwszy model z rodziny, którą TypeSafe nazywa **System One**: szybkie, „odruchowe” decyzje zamiast długiego rozumowania. Obsługuje trzy typy pytań:

- **choice** – Pytanie: „Która z tych opcji?” (do 255 opcji) · Co zwraca: wybraną opcję, prawdopodobieństwo każdej opcji i `confidence`
- **noul** – Pytanie: „Czy ten warunek jest spełniony?” · Co zwraca: prawdopodobieństwo „tak” (0–1)
- **score** – Pytanie: „Gdzie na tej skali?” (do 10 poziomów) · Co zwraca: wynik na skali, rozkład i `confidence`

W praktyce oznacza to trzy rzeczy:

- **Odpowiedź zawsze mieści się w Twoim schemacie.** Nie trzeba parsować tekstu ani łatać „prawie JSON-a”.
- **Jest szybki i tani:** ok. **$0,042 za milion tokenów wejścia**, a tokeny wyjścia są darmowe.
- **Nie tłumaczy się.** Nie dostaniesz uzasadnienia, tylko liczby. Do pisania i wyjaśniania dalej potrzebujesz zwykłego modelu językowego.

## Dlaczego OpenRouter?

OpenRouter udostępnia oficjalny model `typesafe/jev-1.13` każdemu, kto ma konto i klucz API. Nie potrzebujesz konta w TypeSafe.

Na stronie modelu widać najważniejsze parametry: **$0,042 za milion tokenów wejścia, $0 za wyjście, 32 tys. tokenów kontekstu** i datę wydania wersji 1.13 (18 września 2026). Jest tu też **Playground** z gotowymi przykładami każdego typu pytania (np. `noul` jako „strażnik” przed wywołaniem narzędzia przez agenta). Warto w nim kliknąć jeden przykład, zanim przejdziemy do terminala.

> **Uważaj na podróbki.** Wokół Jeva powstało sporo stron o podobnych nazwach, które wydają własne klucze i przepuszczają zapytania przez nieznane serwery. Oficjalne źródła to **typesafe.ai** i strona modelu na **openrouter.ai**. Nigdzie indziej nie podawaj karty ani kluczy.

## Czego potrzebujesz

- Konta na [openrouter.ai](https://openrouter.ai) z **doładowanymi kredytami**. Jev jest płatny (choć bardzo tani), więc bez środków na koncie API odpowie błędem `402`. Doładujesz je w **Settings → Credits**. Na testy z tego artykułu wystarczy najmniejsza kwota.
- macOS z terminalem i Pythonem 3 (`python3 --version`; jeśli go nie ma: `xcode-select --install`).
- Opcjonalnie [Claude Code](https://docs.claude.com/en/docs/claude-code) do kroku 5.

## KROK 1: Klucz API z limitem

W OpenRouter wejdź w **Keys → Create Key** i wypełnij formularz:

- **Name:** np. `jev-blog-test`. Po nazwie rozpoznasz klucz w statystykach.
- **Expiration:** np. **90 dni**. Klucz testowy sam wygaśnie, jeśli o nim zapomnisz.
- **Credit limit:** *Custom amount*, np. **$2**, z resetem **Daily**. OpenRouter odrzuci zapytania, gdy klucz wyda $2 w ciągu doby (limit odnawia się o północy UTC). Przy cenie Jeva to tysiące zapytań dziennie, a w razie wycieku klucza strata jest z góry ograniczona.

Kliknij **Create**. OpenRouter pokaże nowy klucz (zaczyna się od `sk-or-v1-`) **tylko ten jeden raz**. Skopiuj go od razu – w następnym kroku schowamy go w bezpiecznym miejscu.

> **Wskazówka.** Wolisz twardy limit na cały okres ważności klucza zamiast dziennego? Ustaw w *Reset limit every…* brak resetu. Wtedy $2 to maksimum na całe 90 dni.

## KROK 2: Klucz w pęku kluczy macOS

Zamiast trzymać klucz jawnym tekstem w pliku konfiguracyjnym, zapiszmy go w Keychain:

```bash
security add-generic-password -a "$USER" -s openrouter-jev -w
```

Terminal poprosi o hasło – wklej klucz. Teraz niech każdy nowy terminal odczytuje go do zmiennej `OPENROUTER_API_KEY`:

```bash
echo 'export OPENROUTER_API_KEY="$(security find-generic-password -a "$USER" -s openrouter-jev -w)"' >> ~/.zshrc
source ~/.zshrc
echo ${OPENROUTER_API_KEY:0:8}   # powinno pokazać: sk-or-v1
```

> **Wkleiłeś coś innego niż klucz?** Nadpisz wpis w Keychain (flaga `-U` aktualizuje istniejący) i przeładuj konfigurację:

```bash
security add-generic-password -U -a "$USER" -s openrouter-jev -w
source ~/.zshrc
```

## KROK 3: Pierwsze pytanie do Jeva (curl)

Jev na OpenRouter **nie korzysta z endpointu czatu**. Ma osobne **Decisions API**: `POST https://openrouter.ai/api/alpha/decisions`. Wysyłasz dwie rzeczy:

- `state` – kontekst, czyli fakty potrzebne do decyzji,
- `questions` – słownik pytań, każde z typem, instrukcją i kryteriami.

### Przykładowy projekt: czy warto napisać ten artykuł?

Żeby test miał sens, weźmy realny problem. Prowadzę bloga o SEO i AI i mam dziesiątki pomysłów na wpisy. Zanim zabiorę się za jeden z nich – *„robots.txt w 2026 – jak skonfigurować dla GPTBot i ClaudeBot”* – chcę szybko wiedzieć trzy rzeczy:

1. **Jaką intencję ma czytelnik**, który tego szuka? Od tego zależy format wpisu: definicja, poradnik czy porównanie.
1. **Czy temat w ogóle pasuje do bloga?**
1. **Jak bardzo jest zaawansowany?** Czy piszę dla początkujących, czy dla specjalistów.

Każde z tych pytań to inny typ decyzji Jeva: wybór z listy (`choice`), tak/nie (`noul`) i ocena w skali (`score`). Cały „projekt” to jeden folder z jednym plikiem JSON:

```text
~/Dev/Jev-blog/
└── przyklad-seo.json   ← zapytanie do Jeva (kontekst + 3 pytania)
```

Utwórz folder i plik:

```bash
mkdir -p ~/Dev/Jev-blog && cd ~/Dev/Jev-blog
nano przyklad-seo.json    # albo: code przyklad-seo.json
```

Wklej do pliku poniższą treść i zapisz (w nano: Ctrl+O, Enter, Ctrl+X). Jeśli wolisz obejść się bez edytora, zobacz wskazówkę pod kodem.

```json
{
  "model": "typesafe/jev-1.13",
  "state": {
    "blog": "Blog techniczny o SEO, GEO i AI dla deweloperów",
    "tytul": "robots.txt w 2026 – jak skonfigurować dla GPTBot i ClaudeBot"
  },
  "questions": {
    "intencja": {
      "type": "choice",
      "instructions": "Jaka jest główna intencja wyszukiwania tego tematu?",
      "criteria": {
        "informacyjna": "Czytelnik chce zrozumieć pojęcie.",
        "poradnik": "Czytelnik chce coś zrobić krok po kroku.",
        "porownanie": "Czytelnik wybiera między opcjami.",
        "news": "Czytelnik chce wiedzieć, co się zmieniło."
      }
    },
    "pasuje_do_bloga": {
      "type": "noul",
      "instructions": "Czy temat pasuje do profilu bloga?",
      "criteria": {
        "true": "Temat mieści się w tematyce bloga.",
        "false": "Temat jest poza tematyką bloga."
      }
    },
    "trudnosc": {
      "type": "score",
      "instructions": "Jak zaawansowany technicznie jest ten temat dla czytelnika?",
      "criteria": ["Dla zupełnie początkujących", "Wymaga podstaw", "Dla średniozaawansowanych", "Dla zaawansowanych specjalistów"]
    }
  }
}
```

> **Bez edytora.** Plik możesz też utworzyć jednym poleceniem: wpisz `cat > przyklad-seo.json <<'EOF'`, w kolejnych liniach wklej JSON, a na końcu w osobnej linii wpisz `EOF`. Jeśli curl zgłosi `option -d: error encountered when reading a file`, to znaczy, że pliku nie ma w bieżącym folderze – sprawdź to przez `ls`.

Co jest czym w tym pliku:

- **model** – Co zawiera: `typesafe/jev-1.13` · Po co: który model ma odpowiedzieć
- **state.blog** – Co zawiera: opis profilu bloga · Po co: punkt odniesienia dla pytania „czy pasuje?”
- **state.tytul** – Co zawiera: oceniany temat · Po co: to, o czym Jev podejmuje decyzję
- **questions.intencja** – Co zawiera: `choice` z 4 opcjami · Po co: każda opcja ma klucz (`poradnik`) i opis, po którym Jev ją rozpoznaje
- **questions.pasuje_do_bloga** – Co zawiera: `noul` z opisem „tak” i „nie” · Po co: zwraca prawdopodobieństwo odpowiedzi „tak”
- **questions.trudnosc** – Co zawiera: `score` z 4 poziomami · Po co: poziomy od najniższego (0) do najwyższego (3)

> **Wskazówka.** Nazwy pytań i kluczy opcji wymyślasz sam – Jev zwróci odpowiedź pod tymi samymi nazwami. Najważniejsze są **opisy** w `criteria`: im wyraźniej odróżniają opcje, tym pewniejsza odpowiedź.

Wysyłamy. Flaga `-w` dopisze na końcu kod HTTP, żeby od razu było widać, czy zapytanie przeszło:

```bash
curl -s -w "\nHTTP %{http_code}\n" https://openrouter.ai/api/alpha/decisions \
  -H "Authorization: Bearer $OPENROUTER_API_KEY" \
  -H "Content-Type: application/json" \
  -d @przyklad-seo.json
```

`HTTP 200` oznacza, że wszystko działa. Tak wygląda moja odpowiedź, sformatowana dla czytelności:

```json
{
  "model": "typesafe/jev-1.13-20260917",
  "answers": {
    "intencja": {
      "type": "choice",
      "choice": "poradnik",
      "probabilities": { "news": 0, "porownanie": 0, "poradnik": 1, "informacyjna": 0 },
      "confidence": 1
    },
    "pasuje_do_bloga": { "type": "noul", "noul": 0.95 },
    "trudnosc": {
      "type": "score",
      "score": 2.47,
      "probabilities": { "0": 0, "1": 0.03, "2": 0.48, "3": 0.49 },
      "confidence": 0.47
    }
  },
  "usage": { "input_tokens": 597, "output_tokens": 93, "cost": 0.000025074 },
  "provider": "TypeSafe"
}
```

(pole `legend` z opisami poziomów pominąłem)

Co z tego wynika:

- **Intencja: poradnik, pewność 1.** Jev nie ma żadnych wątpliwości, że ktoś szukający konfiguracji robots.txt chce instrukcji krok po kroku, a nie definicji.
- **Pasuje do bloga: 0,95.** Prawdopodobieństwo odpowiedzi „tak” wynosi 95%.
- **Trudność: 2,47, ale pewność tylko 0,47.** To najciekawszy wynik. Jev rozłożył głosy niemal po równo między „średniozaawansowanych” (0,48) i „zaawansowanych specjalistów” (0,49). Niska `confidence` to sygnał, że **sam temat leży na granicy**, a nie że model „nie wie”. W praktyce: piszę dla średniozaawansowanych i dodaję sekcję dla ekspertów.
- **Koszt: $0,000025** za 597 tokenów wejścia i trzy decyzje. Za dolara to około **40 tysięcy takich zapytań**.

> **Czytelniejszy wynik.** Zamiast `-w "..."` dodaj na końcu `| python3 -m json.tool --no-ensure-ascii`, a odpowiedź zostanie sformatowana w kolumnie. Flaga `--no-ensure-ascii` sprawia, że polskie znaki nie zamieniają się w kody typu `ł`.

Na co patrzeć w odpowiedzi:

- `choice` to zawsze jeden z kluczy podanych w `criteria`.
- `confidence` mówi, jak bardzo Jev jest pewny swojej odpowiedzi. W automatyzacjach to najważniejsza liczba.
- `usage.cost` to realny koszt zapytania w dolarach.

## KROK 4: Czytelny wynik – skrypt jev.py

Surowy JSON jest dobry do debugowania, ale na co dzień wygodniej mieć krótkie podsumowanie. Napisałem do tego mały skrypt `jev.py`: ok. 90 linii, tylko biblioteka standardowa Pythona, bez instalowania paczek. Zapisz go w tym samym folderze co `przyklad-seo.json` (pełny kod poniżej) i uruchom:

```bash
python3 jev.py przyklad-seo.json
```

```text
model: typesafe/jev-1.13-20260917   czas: 560 ms

• intencja [choice] → poradnik   (pewność 1.00; poradnik 1.00, porownanie 0.00, news 0.00)
• pasuje_do_bloga [noul]   → TAK   (P(tak) = 0.94)
• trudnosc [score]  → 2.45   (pewność 0.50; najbliżej: Dla średniozaawansowanych)

tokeny wejścia: 597   koszt: $0.000025
```

Całe zapytanie – połączenie z OpenRouter, trzy decyzje i powrót – trwało **560 ms**.

Zwróć uwagę, że wyniki minimalnie różnią się od poprzedniego testu z `curl`: dopasowanie 0,94 zamiast 0,95, trudność 2,45 zamiast 2,47. Jev jest modelem probabilistycznym, więc takie drobne wahania są normalne. Decyzje z pewnością bliską 1 (jak intencja) są stabilne, a te na granicy (jak trudność) mogą się między wywołaniami lekko przesuwać. To kolejny powód, żeby w automatyzacjach opierać się na progu pewności, a nie na samej odpowiedzi.

Skrypt przyjmuje też zapytanie ze standardowego wejścia (`cat zapytanie.json | python3 jev.py -`), a flaga `--raw` pokazuje pełną odpowiedź JSON. To przyda się za chwilę w Claude Code.

### Pełny kod jev.py

```python
#!/usr/bin/env python3
"""
jev.py - minimalny klient Jev (TypeSafe) przez OpenRouter Decisions API. Tylko biblioteka standardowa.

Użycie:
  python3 jev.py przyklad-seo.json          # zapytanie z pliku
  cat zapytanie.json | python3 jev.py -     # zapytanie ze stdin
  python3 jev.py przyklad-seo.json --raw    # pełna odpowiedź JSON

Plik zapytania: {"state": ..., "questions": {...}}  (pole "model" opcjonalne)
Klucz: zmienna środowiskowa OPENROUTER_API_KEY
"""
import json, os, sys, time, urllib.error, urllib.request

API_URL = os.environ.get("JEV_API_URL", "https://openrouter.ai/api/alpha/decisions")
MODEL = os.environ.get("JEV_MODEL", "typesafe/jev-1.13")

def main() -> None:
    args = [a for a in sys.argv[1:] if not a.startswith("--")]
    raw = "--raw" in sys.argv
    if not args:
        sys.exit(__doc__)
    key = os.environ.get("OPENROUTER_API_KEY")
    if not key:
        sys.exit("Brak OPENROUTER_API_KEY. Ustaw: export OPENROUTER_API_KEY=sk-or-...")

    text = sys.stdin.read() if args[0] == "-" else open(args[0], encoding="utf-8").read()
    try:
        req_body = json.loads(text)
    except json.JSONDecodeError as e:
        sys.exit(f"Niepoprawny JSON zapytania: {e}")
    if "questions" not in req_body or "state" not in req_body:
        sys.exit('Zapytanie musi mieć pola "state" i "questions".')
    req_body.setdefault("model", MODEL)

    req = urllib.request.Request(API_URL, data=json.dumps(req_body).encode(), method="POST", headers={
        "Authorization": f"Bearer {key}",
        "Content-Type": "application/json",
        "X-Title": "jev-cli",
    })
    t0 = time.perf_counter()
    try:
        with urllib.request.urlopen(req, timeout=30) as r:
            resp = json.load(r)
    except urllib.error.HTTPError as e:
        hint = {401: "zły lub brak klucza", 402: "brak kredytów na koncie OpenRouter",
                429: "limit zapytań - odczekaj chwilę"}.get(e.code, "")
        sys.exit(f"Błąd API {e.code} {hint}\n{e.read().decode(errors='replace')[:500]}")
    except (urllib.error.URLError, OSError) as e:
        sys.exit(f"Brak połączenia z API: {getattr(e, 'reason', e)}")
    ms = (time.perf_counter() - t0) * 1000

    if raw:
        print(json.dumps(resp, ensure_ascii=False, indent=2))
        return

    print(f"model: {resp.get('model', '?')}   czas: {ms:.0f} ms\n")
    for name, a in resp.get("answers", {}).items():
        kind = a.get("type")
        if kind == "choice":
            probs = sorted(a.get("probabilities", {}).items(), key=lambda kv: -kv[1])[:3]
            top = ", ".join(f"{k} {v:.2f}" for k, v in probs)
            print(f"• {name} [choice] → {a['choice']}   (pewność {a.get('confidence', 0):.2f}; {top})")
        elif kind == "score":
            legend = a.get("legend", {})
            lvl = str(round(a["score"]))
            print(f"• {name} [score]  → {a['score']:.2f}   (pewność {a.get('confidence', 0):.2f}; "
                  f"najbliżej: {legend.get(lvl, lvl)})")
        elif kind == "noul":
            p = a["noul"]
            print(f"• {name} [noul]   → {'TAK' if p >= 0.5 else 'NIE'}   (P(tak) = {p:.2f})")
        else:
            print(f"• {name}: {json.dumps(a, ensure_ascii=False)}")
    u = resp.get("usage", {})
    print(f"\ntokeny wejścia: {u.get('input_tokens', '?')}   koszt: ${u.get('cost', 0):.6f}")

if __name__ == "__main__":
    main()
```

## KROK 5: Jev w Claude Code

Claude Code świetnie pisze i analizuje, ale do setek powtarzalnych klasyfikacji szkoda dużego modelu. Damy mu więc Jeva jako narzędzie w formie **skilla**, czyli folderu z instrukcją (`SKILL.md`) i skryptem. Claude Code sam po niego sięgnie, gdy zadanie będzie tego wymagało.

> Istnieje kilka społecznościowych serwerów MCP dla Jeva, ale każdy z nich dostaje Twój klucz API. Tutaj wystarczą dwa pliki, które przeczytasz w minutę.

Instalacja skilla (dla wszystkich projektów):

```bash
mkdir -p ~/.claude/skills/jev
cp claude-skill/jev/SKILL.md jev.py ~/.claude/skills/jev/
ls ~/.claude/skills/jev
```

`SKILL.md` mówi Claude Code, **kiedy** używać Jeva (klasyfikacja, tak/nie, ocena w skali), **jak** zbudować zapytanie i jakich zasad pilnować, np. żeby nigdy nie wysyłać sekretów w `state`. Pełna treść:

```markdown
---
name: jev
description: Szybkie, tanie decyzje zamknięte modelem Jev (TypeSafe) przez OpenRouter - klasyfikacja do listy kategorii, odpowiedź tak/nie lub ocena w skali, z prawdopodobieństwem. Użyj, gdy użytkownik prosi o "użyj Jev", "zapytaj Jev", albo trzeba sklasyfikować/ocenić wiele elementów według tych samych kryteriów.
---

# Jev – decyzje przez OpenRouter

Jev nie generuje tekstu. Odpowiada wyłącznie na **pytania zamknięte** i zwraca prawdopodobieństwa. Wywołujesz go skryptem `jev.py`, który leży w tym samym folderze co ten plik (`~/.claude/skills/jev/jev.py`).

## Kiedy używać

- Klasyfikacja elementów do z góry znanej listy kategorii (intencja, klaster, zespół, priorytet).
- Pytania tak/nie z jasno opisanym warunkiem.
- Ocena w skali z opisanymi poziomami.
- Wiele elementów oceniane według tych samych kryteriów: jedno wywołanie na element.

Nie używaj do pisania tekstu, streszczeń, uzasadnień ani pytań otwartych. To robisz sam.

## Jak wywołać

1. Zbuduj plik JSON zapytania w katalogu tymczasowym (np. `/tmp/jev-req.json`):

```json
{
  "state": { "tytul": "robots.txt dla GPTBot i ClaudeBot", "blog": "SEO techniczne i AI" },
  "questions": {
    "intencja": {
      "type": "choice",
      "instructions": "Jaka jest główna intencja wyszukiwania?",
      "criteria": { "informacyjna": "Chce zrozumieć pojęcie.", "poradnik": "Chce coś zrobić krok po kroku." }
    },
    "pasuje": {
      "type": "noul",
      "instructions": "Czy temat pasuje do bloga?",
      "criteria": { "true": "Pasuje.", "false": "Nie pasuje." }
    },
    "trudnosc": {
      "type": "score",
      "instructions": "Jak zaawansowany jest temat?",
      "criteria": ["Początkujący", "Średni", "Zaawansowany"]
    }
  }
}
```

2. Uruchom: `python3 ~/.claude/skills/jev/jev.py /tmp/jev-req.json` (dodaj `--raw`, jeśli potrzebujesz pełnych prawdopodobieństw).
3. Przedstaw wynik użytkownikowi: odpowiedź, pewność i koszt. Jeśli pewność jest poniżej 0,6, zaznacz wyraźnie, że wynik jest niepewny.

## Zasady budowania pytań

- Typy: `choice` (klucze opcji → opis, maks. 255 opcji), `noul` (kryteria `true`/`false`), `score` (lista poziomów od najniższego, maks. 10).
- Klucze pytań i opcji: krótkie, `snake_case`, bez spacji.
- Każda opcja ma opis, który jednoznacznie ją odróżnia od pozostałych.
- `state` zawiera tylko fakty potrzebne do decyzji. Limit to 32 tys. tokenów.
- Nigdy nie wysyłaj w `state` sekretów, kluczy API ani danych osobowych.
- Jeśli skrypt zgłosi brak `OPENROUTER_API_KEY`, poproś użytkownika o uruchomienie Claude Code z terminala, w którym zmienna jest ustawiona. Nie proś o wklejenie klucza do czatu.
```

Zapisz ją w folderze projektu jako `claude-skill/jev/SKILL.md`. Cały projekt wygląda teraz tak:

```text
~/Dev/Jev-blog/
├── przyklad-seo.json
├── jev.py
└── claude-skill/
    └── jev/
        └── SKILL.md
```

Uruchom Claude Code **z tego samego terminala**, żeby widział zmienną `OPENROUTER_API_KEY`:

```bash
claude
```

Prompt testowy:

```text
Użyj Jev: dla każdego z tych tytułów określ intencję (informacyjna / poradnik / porownanie / news),
czy pasuje do bloga o SEO technicznym, GEO i AI dla deweloperów, oraz trudność w skali 1–4.
Pokaż wynik w tabeli z pewnością i łącznym kosztem.

1. Google Tag Manager: praktyczny poradnik krok po kroku
2. Ahrefs: przewodnik po narzędziu dla początkujących
3. Voice search: wyszukiwanie głosowe a pozycjonowanie
4. Favicon: wizytówka strony w SERP i przeglądarce
5. Pozycjonowanie WordPress: kompletny poradnik SEO
```

Claude Code rozpoznaje zadanie i sam wczytuje skill (`Skill(jev) – Successfully loaded skill`). Potem buduje pięć zapytań – po jednym na tytuł – i uruchamia je równolegle przez `jev.py`:

> **Uwaga.** U mnie działał tryb *auto*, więc Claude Code nie pytał o zgodę. W domyślnym trybie poprosi o zatwierdzenie polecenia `python3 ~/.claude/skills/jev/jev.py` – zatwierdź je.

Po niespełna minucie dostajemy tabelę:

- **1** – Tytuł: Google Tag Manager: praktyczny poradnik krok po kroku · Intencja (pewność): poradnik (1,00) · Pasuje do bloga (P): ⚠️ raczej nie (0,53) · Trudność 1–4 (pewność): ⚠️ 1,86 → 2 (0,56)
- **2** – Tytuł: Ahrefs: przewodnik po narzędziu dla początkujących · Intencja (pewność): poradnik (0,97) · Pasuje do bloga (P): nie (0,63) · Trudność 1–4 (pewność): 1,06 → 1 (0,94)
- **3** – Tytuł: Voice search: wyszukiwanie głosowe a pozycjonowanie · Intencja (pewność): informacyjna (0,92) · Pasuje do bloga (P): tak (0,78) · Trudność 1–4 (pewność): 2,84 → 3 (0,65)
- **4** – Tytuł: Favicon: wizytówka strony w SERP i przeglądarce · Intencja (pewność): informacyjna (0,99) · Pasuje do bloga (P): ⚠️ raczej tak (0,55) · Trudność 1–4 (pewność): ⚠️ 1,48 → 1–2 (0,52)
- **5** – Tytuł: Pozycjonowanie WordPress: kompletny poradnik SEO · Intencja (pewność): poradnik (1,00) · Pasuje do bloga (P): ⚠️ raczej tak (0,53) · Trudność 1–4 (pewność): ⚠️ 2,39 → 2–3 (0,37)

⚠️ – pewność poniżej 0,6. Łączny koszt pięciu ocen: **$0,000151**, czyli ok. $0,00003 za tytuł.

Co z tego wynika:

- **Intencja jest pewna we wszystkich przypadkach (0,92–1,00).** Tytuł z „poradnikiem” czy „krok po kroku” Jev bez wahania klasyfikuje jako poradnik, a „co to jest”-owe tematy (voice search, favicon) jako informacyjne.
- **Dopasowanie do bloga to najciekawsza kolumna.** Jedynie *Voice search* pasuje z wyraźną pewnością, a *Ahrefs* raczej odpada. Trzy tematy wypadły niemal 50/50. Jev nie „zgaduje” – mówi wprost, że profil bloga opisany jednym zdaniem nie wystarcza do decyzji. Dla mnie to podpowiedź: albo doprecyzować `state.blog`, albo przesunąć kąt tematu pod dewelopera, np. *„GTM server-side”*, *„favicon i manifest w Next.js”*, *„WordPress: techniczne SEO w motywie”*.
- **Trudność WordPressa (pewność 0,37)** to znowu temat „na granicy”: Jev waha się między poziomem 2 (43%) i 3 (38%), bo „kompletny poradnik” może być i dla średniozaawansowanych, i dla ekspertów.
- **Claude Code sam przeliczył skalę.** API zwraca poziomy od 0 do 3, a Claude przesunął je na skalę 1–4 z promptu i oznaczył niepewne wyniki. To dobry przykład podziału pracy.

Podział ról jest prosty: **Claude rozumie zadanie i układa pytania, Jev tanio i szybko podejmuje decyzje, a Claude zbiera wynik i go tłumaczy.**

## Ile to kosztowało?

Każde wywołanie zwraca `usage.cost`, a pełną historię widać w panelu OpenRouter w **Logs → Generations**. Warto dodać filtr *API Key is jev-blog-test*, żeby widzieć tylko wywołania z testowego klucza:

Cały test z tego artykułu to **8 zapytań do Jeva**:

- **curl (dwa uruchomienia)** – Zapytania: 2 · Tokeny wejścia: 597 · Koszt: 2 × $0,0000251
- **jev.py** – Zapytania: 1 · Tokeny wejścia: 597 · Koszt: $0,0000251
- **Claude Code (5 tytułów)** – Zapytania: 5 · Tokeny wejścia: 718–723 · Koszt: 5 × ok. $0,0000303
- **Razem** – Zapytania: 8 · Koszt: ok. $0,00023

Mniej niż jedna czterdziesta centa za cały artykuł. Za dolara to ok. 35 tysięcy takich decyzji.

Dla porównania: licznik sesji Claude Code (Opus) w trakcie jednego zadania z tabelą wzrósł z $0,22 do $0,28. **Najdroższe nie są decyzje Jeva, tylko praca modelu, który je organizuje.** Dlatego do masowych ocen – setek czy tysięcy elementów – lepiej uruchamiać `jev.py` bezpośrednio w skrypcie, a Claude Code zostawić do budowania pytań i interpretacji wyników. Właśnie tak zrobimy w części 2.

## Ograniczenia

- **Tylko pytania zamknięte.** Jev nie napisze ani nie streści tekstu.
- **Brak uzasadnień.** Jeśli potrzebujesz „dlaczego”, dopytaj zwykły model.
- **Limit 32 tys. tokenów** kontekstu, do 255 opcji w `choice` i do 10 poziomów w `score`.
- **Decisions API ma status „alpha”.** Format może się jeszcze zmienić – śledź [dokumentację OpenRouter](https://openrouter.ai/docs/guides/community/jev).
- **Dane trafiają do dostawcy.** Nie wysyłaj danych klientów ani treści objętych NDA.

## Podsumowanie

W kwadrans masz działającego Jeva: klucz z limitem w pęku kluczy, test w terminalu i skill, dzięki któremu Claude Code sam deleguje mu powtarzalne decyzje. Koszt testu jest pomijalny, a odpowiedzi zawsze mieszczą się w schemacie, który sam ustalasz.

**W następnej części:** Jev ocenia mój backlog ponad 100 pomysłów na artykuły w Obsidianie – wykrywa kanibalizację z opublikowanymi wpisami i układa kolejkę „co pisać najpierw”.

## Źródła

- [TypeSafe AI – Introducing System One Models & Jev](https://typesafe.ai/blog/introducing-system-one-models-and-jev)
- [OpenRouter – Jev 1.13](https://openrouter.ai/typesafe/jev-1.13)
- [OpenRouter – dokumentacja Jev](https://openrouter.ai/docs/guides/community/jev)
- [OpenRouter – Decisions API reference](https://openrouter.ai/docs/api/api-reference/alphadecisions/submit-a-decisions-questions-and-answers-request)
- [Flavio Copes – How to get access to Jev](https://flaviocopes.com/jev-api-key/)

## Często zadawane pytania (FAQ)

### Czy do korzystania z Jeva potrzebuję konta w TypeSafe?

Nie. Przez OpenRouter wystarczy konto OpenRouter z doładowanymi kredytami i klucz API. Model ma identyfikator typesafe/jev-1.13 i jest dostępny bez listy oczekujących.

### Ile kosztuje jedno zapytanie do Jeva?

Jev kosztuje $0,042 za milion tokenów wejścia, a tokeny wyjścia są darmowe. W moim teście jedno zapytanie z trzema pytaniami (ok. 600–720 tokenów) kosztowało od $0,000025 do $0,00003, a cały test z 8 zapytaniami – ok. $0,00023.

### Czym Jev różni się od ChatGPT czy Claude?

Jev nie generuje tekstu. Odpowiada wyłącznie na pytania zamknięte: wybór z listy (choice), tak/nie (noul) lub ocena w skali (score), zawsze z prawdopodobieństwem. Odpowiedź nigdy nie wychodzi poza zdefiniowany schemat, ale Jev nie podaje też uzasadnień.

### Czy mogę używać Jeva w Claude Code bez serwera MCP?

Tak. Wystarczy skill w folderze ~/.claude/skills/jev: plik SKILL.md z instrukcją i krótki skrypt jev.py. Claude Code musi być uruchomiony z terminala, w którym ustawiona jest zmienna OPENROUTER_API_KEY.

---

*Wpis pochodzi z serwisu [krysmalski.pl](https://krysmalski.pl/blog/jev-openrouter-konfiguracja-claude-code)*
