Recherche-CLI · ocl

Zitate prüfen und Belege sichern, direkt aus dem Terminal

ocl ist ein kleiner Client ohne Abhängigkeiten für die OpenCaseLaw-Recherche-API. Er dient einer Anwältin am Terminal ebenso wie einem KI-Agenten im Skript: lesbarer Text am Bildschirm, JSON in der Pipe. Alles, was er zeigt, kommt unverändert vom Dienst: Kennungen, Zitierstrings, Erwägungstext.

Installation

Python 3.10 oder neuer. Von PyPI als Werkzeug mit pipx oder uv installieren; beide erstellen die isolierte Umgebung, die aktuelle Python-Installationen verlangen. ocl doctor prüft Verbindung, Server und Client.

pipx install opencaselaw-cli        # or: uv tool install opencaselaw-cli
ocl --help

Ohne pipx oder uv eine virtuelle Umgebung verwenden: python3 -m venv .venv && .venv/bin/pip install opencaselaw-cli, dann .venv/bin/ocl ausführen. Aktualisieren mit pipx upgrade opencaselaw-cli (oder uv tool upgrade opencaselaw-cli).

1. Die Zitate eines Entwurfs prüfen

Die Referenzen aus dem Entwurf in eine Datei schreiben, eine pro Zeile, oder als JSON-Zeilen, wenn eine Referenz eine Erwägung nennt. Jede kommt als resolved, missing oder ambiguous zurück, mit dem gefundenen Entscheid; eine genannte Erwägung gilt nur als resolved, wenn sie im Index existiert.

cat > references.jsonl <<'JSONL'
{"reference":"BGE 136 III 513","pinpoint":"2.3"}
{"reference":"4A_747/2012"}
{"reference":"BGE 999 III 1"}
{"reference":"BGE 140 III 86","pinpoint":"2.3"}
JSONL
ocl citations resolve --input references.jsonl

Am Terminal erscheint:

resolved              BGE 136 III 513  bge_BGE_136_III_513  E. 2.3 retrieved
resolved              4A_747/2012      bger_4A_747_2012     BGer 4A_747/2012 vom 5. April 2013
missing               BGE 999 III 1                         not in the corpus
pinpoint_unavailable  BGE 140 III 86   bge_BGE_140_III_86   E. 2.3 not in the index

partial: 2 resolved, 1 missing, 1 pinpoint_unavailable.
Existence and pinpoints only; no assessment of legal support.

Der Exit-Code ist 4, weil nicht alles aufgelöst wurde. Was die Prüfung nicht tut: Sie sagt nie, dass ein Entscheid Ihre These stützt, noch gilt oder auf Ihren Sachverhalt passt. Diese Lektüre bleibt Ihre Aufgabe.

2. Die Belege hinter einer Notiz aufbewahren

Ein Befehl führt die Suche aus und speichert die ausgewählten Entscheide, die genannten Erwägungen und die genannten Gesetzesartikel in einen Ordner: Volltexte wie geliefert, ein lesbares INDEX.md und ein manifest.json mit jeder Anfrage, jedem Zeitstempel, jeder Quellenadresse und jedem Datei-Hash. Gespeicherte Dateien werden nie überschrieben; --resume beendet einen unterbrochenen Lauf.

ocl bundle create 'Rachekündigung Art. 336 OR' --max-results 10 --passage 2 \
  --law OR:336 --out rachekuendigung-2026-09

Der Ordner ist ohne Werkzeug lesbar:

rachekuendigung-2026-09/
  INDEX.md                                    what was saved, in plain language
  manifest.json                               every request, timestamp, hash, source link
  decisions/bge_BGE_136_III_513-5b3e22ef.txt  full text as served (+ .json metadata)
  passages/bge_BGE_136_III_513_2-ff487655.txt E. 2, verbatim
  laws/OR_336-812a5382.json                   Art. 336 OR, consolidation date, Fedlex link
  search/page-0000-1850ce82.json              the search page the selection came from

Ein Paket ist complete, wenn jedes verlangte Element gespeichert wurde, sonst partial mit jedem fehlgeschlagenen Element, etwa einem kantonalen Entscheid ohne nummerierte Erwägungen. Es bewahrt, was der Dienst an jenem Tag geliefert hat; der Korpus wird jede Nacht neu aufgebaut, dieselbe Abfrage kann nächsten Monat andere Entscheide auswählen.

Was die Ergebnisse bedeuten

  • resolved: Der Entscheid existiert im Korpus. Mit Erwägungsangabe existiert die genannte Erwägung, und ihr Text steht in der Zeile.
  • pinpoint_unavailable: Der Entscheid existiert; die nummerierte Erwägung ist nicht im Strukturindex. Bei einer Buchstaben-Untererwägung (E. 2a, E. 3c/aa) wird die übergeordnete Nummer geliefert (parent_retrieved); den Buchstaben darin suchen.
  • missing: Kein Entscheid mit diesem Zitat oder dieser Verfahrensnummer. Ein falsches Zitat oder eine Lücke in der Abdeckung, nie ein Beweis, dass ein Zitat erfunden wurde.
  • ambiguous: Mehr als ein Entscheid trägt diese Bezeichnung (Verfahrensnummern werden von verschiedenen Gerichten wiederverwendet). Eine decision_id wählen.
  • unrecognized: Der vom Dienst vorgeschlagene Entscheid trägt keine Bezeichnung, die in der Referenz steht; der Vorschlag steht unter service_candidate, nie in decision_id. resolution_incomplete, error: Identität nicht feststellbar oder Anfrage gescheitert. Nichts wird geraten.
  • total_is_lower_bound: true bedeutet «mindestens so viele». Eine Textsuche wird über einen begrenzten Kandidatenbestand gerankt; has_more: false beweist nie, dass jeder relevante Entscheid gesehen wurde.
  • Exit-Codes: 0 vollständig, 2 ungültige Eingabe, 3 Dienst oder Netz gescheitert, 4 teilweise oder ungelöst (auch: ein Entscheid oder eine Erwägung, die der Dienst nicht hat). Skripte verzweigen darauf, ohne Prosa zu parsen.
  • discrepancy: Der Entscheid wurde identifiziert, aber das Datum oder die neben dem BGE-Zitat geschriebene Verfahrensnummer widerspricht dem Datensatz; discrepancies nennt jede Abweichung.

Rezepte

Suchen, dann die Volltexte holen, in einer Pipeline:

ocl decisions search 'Rachekündigung Art. 336 OR' --max-results 5 --format jsonl |
  ocl decisions get --stdin --format jsonl > decisions.jsonl

Alles, was ein Gericht in einem Zeitraum entschieden hat. Ohne Suchtext zählen die Filter eine exakte Menge seitenweise auf:

ocl decisions search --court bge --date-from 2026-01-01 --date-to 2026-06-30 \
  --sort date_desc --max-results 500 --format jsonl > bge-2026-h1.jsonl

Eine Erwägung wörtlich zitieren, mit dem passenden Zitierstring:

ocl decisions passage bge_BGE_136_III_513 2.3
ocl cite 'BGE 136 III 513' --pinpoint 2.3 --language fr

Ein Gesetz, wie es an einem Datum galt:

ocl laws get OR --article 41 --as-of 2015-01-01

Wer einen Leitentscheid zitiert:

ocl citations list bge_BGE_140_III_86 --direction incoming --limit 50

Coding-Agenten wie Claude Code oder Codex führen dieselben Befehle in einer Shell aus und lesen das JSON; die Belege bleiben in Dateien, die Sie prüfen können, statt im Gedächtnis des Modells.

Für Agenten

Ein Agent braucht vier Dinge: eine Installation ohne Rückfragen, Ausgaben, die er parsen kann, Verdikte, auf die er verzweigen kann, und Regeln, die er sich nicht wegreden kann. ocl liefert alle vier: JSON, sobald die Ausgabe in eine Pipe geht; Exit-Codes, die das Ergebnis tragen (0 alles aufgelöst, 2 ungültige Eingabe, 3 Dienst oder Netz, 4 etwas hat sich nicht aufgelöst); --cache, damit Wiederholungen innerhalb einer Datenbank-Generation nichts kosten; und drei mitgelieferte Skills (Zitatprüfung, Recherche, Beleg-Ordner). ocl tool call erreicht jedes Recherche-Werkzeug des Dienstes.

ocl agent-guide                  # the contract on one page: JSON, exit codes, statuses, rules
ocl skills install --claude      # citation-check, research, evidence-bundle into ~/.claude/skills
ocl tool list                    # every research tool of the service
ocl tool call find_leading_cases query='Rachekündigung Art. 336 OR' limit=5
ocl quotes check --input quotes.jsonl --format jsonl
ocl citations resolve --input refs.jsonl --format jsonl --cache ~/.cache/ocl

Die Regeln sind nicht verhandelbar: Zitatstrings und Zitate kommen unverändert vom Dienst; ein close_match oder service_candidate ist Information für die Autorin, nie ein Ersatz; das Werkzeug stellt Existenz und Wortlaut fest, nicht die rechtliche Tragweite. opencaselaw_cli.api bietet dasselbe als Bibliothek.

Wo es hingehört

  • Gespräch: Claude, ChatGPT oder einen anderen MCP-Client mit mcp.opencaselaw.ch verbinden (Einrichtung pro Client).
  • Skripte, Notebooks und Agenten: ocl oder direkt die REST-API. Gleiche Datensätze, gleiche Grenzen.
  • Analysen über den ganzen Korpus: der Parquet-Datensatz.

Grenzen

Eine Textsuche wird als eine einzige gerankte Anfrage mit höchstens 800 Ergebnissen gesendet; reine Filtersuchen werden seitenweise geholt. Breite Abfragen können die Zeitgrenze überschreiten und werden als Fehler gemeldet, nicht als leeres Ergebnis. Kantonale Gesetze werden als --law ZH/StG:1 angesprochen. Abfragen gehen an den gehosteten Dienst und unterstehen der Datenschutzerklärung; --base-url verweist auf einen separat betriebenen Server.

Die vollständige Anleitung mit den Referenzteilen (Suche und Abruf, Pakete, Zitatauflösung, API-Vertrag) steht auf GitHub: docs/research-cli.md.