Zum Hauptinhalt springen

Plugin-Evals: Teste dein Plugin mit claude plugin eval

Experte
What you'll learn
  • Verstehen, was ein Plugin-Eval misst, das `claude plugin validate` und ein manueller Test nicht messen können: *feuert* der Skill, und schlägt er ein Modell ohne Plugin
  • Die drei Zahlen in jedem Ergebnis lesen — WITH, W/OUT und Δ — und wissen, warum manche Grader bewusst aus dem Score ausgeschlossen werden
  • Unter den sechs Grader-Typen (vier kostenlos, zwei Judge-basiert) wählen und Rubriken schreiben, die ein stabiles Signal liefern
  • Die MCP-Server eines Plugins mocken, damit eine Suite reproduzierbar ist und nie den echten Dienst berührt
  • Ein CI-Gate mit gepinnten Modellen, einer Kostenobergrenze und dem Exit-Code-Vertrag verdrahten

Bisher hatte ein Plugin-Autor zwei Werkzeuge: claude plugin validate, das prüft, ob Manifeste und Frontmatter parsen, und die eigenen Augen. Keines davon beantwortet die Frage, die entscheidet, ob ein Plugin die Installation wert ist: Wenn ein Nutzer eine natürliche Anfrage eintippt, wählt Claude den Skill, und ist das Ergebnis besser als das, was Claude ohnehin getan hätte? claude plugin eval beantwortet genau das. Es führt jeden Case in einer Wegwerf-Session aus, in der nur dein Plugin geladen ist, führt ihn noch einmal ganz ohne Plugin aus, bewertet beides und meldet die Differenz.

Diese Seite richtet sich an Leute, die bereits ein funktionierendes Plugin oder einen Skill haben. Wenn du nur das Konzept kennen musst, lies die ersten beiden Abschnitte und das Quiz.

Das mentale Modell: zwei Arme und ein Delta​

Jeder Case ist ein Prompt plus ein oder mehrere Grader. Ein Grader ist eine Bestanden/Nicht-bestanden-Prüfung dessen, was Claude produziert hat. Für jeden Case führt Claude Code aus:

  • den With-Arm: eine frische Headless-Session, in der nur dein Plugin geladen ist, der Prompt gesendet wird, Claude arbeiten darf, bis es fertig ist oder das Turn-/Zeitlimit erreicht, und dann die Grader angewendet werden;
  • den Without-Arm: derselbe Prompt, dieselbe Anzahl Läufe, kein Plugin.

Jeder Arm führt den Case standardmäßig dreimal aus, denn ein einzelner Lauf eines nicht-deterministischen Agenten sagt dir fast nichts. Der Score eines Laufs ist der Anteil der bestandenen Grader (gewichtet, falls du Gewichte setzt). Der Score des Cases ist der Mittelwert über die Läufe. Du bekommst:

SpalteBedeutung
WITHMittlerer Score mit geladenem Plugin
W/OUTMittlerer Score ohne Plugin
ΔWITH − W/OUT — was das Plugin tatsächlich beigetragen hat

Der nicht offensichtliche Teil: Ein hoher WITH-Score allein beweist nichts. Wenn ein Case in beiden Armen 1.0 erreicht, hat Claude ihn ohne dich gelöst, und dein Plugin ist für diesen Prompt Ballast. Das Δ ist die Zahl, die die Existenz eines Plugins rechtfertigt. Anthropics eigene Docs nennen den häufigsten ersten Befund: ein Δ nahe null bei einem fehlschlagenden Skill-fired-Grader, was bedeutet, dass Claude deinen Skill bei natürlicher Formulierung nie gewählt hat. Das ist ein description-Problem in SKILL.md, kein Code-Problem, und keine Menge manueller Tests, bei denen du den Skill beim Namen aufrufst, hätte es entdeckt.

Warum manche Grader aus dem Score ausgeschlossen werden​

Eine Prüfung wie „das Skill-Tool wurde aufgerufen" kann im Without-Arm nie bestehen. Würde sie zählen, zöge sie W/OUT Richtung null und bliese Δ gratis auf. Deshalb schließt Claude Code in einem Zwei-Arm-Lauf aus dem Score aus, in beiden Armen, jeden tool_used-Grader, dessen tool Skill ist, plus alles, was du mit arm: with-only markierst. Sie erscheinen weiterhin im Report als Bestanden/Nicht-bestanden-Indikatoren (der Report kennzeichnet sie als „plugin-fired indicator"), und das JSON markiert sie mit scored: false. Daraus folgen zwei Randregeln:

  • Wenn jeder Grader eines Cases ausgeschlossen würde, werden sie stattdessen normal bewertet, sonst bliebe nichts zu bewerten übrig.
  • arm: both zwingt einen Grader, in beiden Armen zu zählen. Das willst du für eine „darf den Skill nicht aufrufen"-Prüfung auf einem Köder-Prompt, geschrieben als tool_used mit min: 0 und max: 0.

Eine Konsequenz, die man sich merken sollte: Dieselbe Suite kann unter --ablation none (ein Arm, nichts ausgeschlossen) einen anderen absoluten Score melden als im standardmäßigen Zwei-Arm-Modus. Vergleiche Gleiches mit Gleichem, wenn du Trends aufzeichnest.

Anatomie eines Cases​

Eine Suite liegt in evals/ innerhalb des Plugins (oder einem anderen Verzeichnis, das du benennst). Jeder Case ist ein Ordner mit einer prompt.md, einer case.yaml oder beidem, plus einem Ordner graders/ mit einer Markdown-Datei pro Grader.

my-plugin/
├── .claude-plugin/plugin.json
├── skills/...
└── evals/
├── drafts-commit-message/
│ ├── prompt.md # frontmatter: run limits; body: the user's request
│ └── graders/
│ ├── criteria.md # type: llm — rubric in the body
│ └── skill-fired.md # type: tool_used, tool: Skill
├── ignores-unrelated-request/
│ └── ...
├── mocks/ # optional suite-wide MCP mocks
└── results/ # written by each run — add to .gitignore

Der Prompt-Body wird genau wie geschrieben an Claude gesendet. Zwei Dinge erwischen Erstautoren:

  • Jeder Lauf startet in einem leeren Arbeitsverzeichnis mit einem Wegwerf-Home, ohne Nutzereinstellungen, ohne CLAUDE.md, ohne persönliche MCP-Server, ohne andere Plugins und nur mit einer Allowlist von Umgebungsvariablen (Grundlegendes wie PATH, Provider-Auth, die meisten ANTHROPIC_*/CLAUDE_CODE_* und alles, was EVAL_* heißt). Wenn die Aufgabe Dateien braucht, lege sie in den Prompt, scaffolde sie oder liefere sie im Plugin mit.
  • @path-Erwähnungen im Prompt werden nicht zu Anhängen expandiert. Gewähre Read in allowed_tools, wenn Claude eine Datei öffnen muss.

Die wichtigsten Frontmatter-Felder von prompt.md:

FeldDefaultHinweis
runs31 bis 50 pro Arm; --runs überschreibt
max_turns10Bis zu 200. Das Erreichen wird als Laufefehler protokolliert und senkt meist den Score, also sei großzügig
timeout_seconds300Bis zu 3600 pro Lauf
allowed_tools[]Read-only-Tools werden allein durch Auflisten gewährt; alles andere braucht eine CLI-Freigabe
modelSession-Default--model überschreibt; in CI pinnen
env{}Keys müssen auf EVAL_[A-Z0-9_]* passen, sonst schlägt der Lauf fehl
pluginsnächstes umschließendes PluginSetze ["../.."], wenn die Auto-Erkennung dein Plugin verfehlt

case.yaml trägt dieselben Felder (Ausführungsfelder unter execution:) plus die drei, die auf andere Dateien verweisen: context.scaffold_script (ein Bash-Skript, das den Workspace vorbereitet, nur mit --scaffold ausgeführt), context.history_file (ein .jsonl-Transkript zum Fortsetzen, sodass dein Prompt der nächste Turn wird) und context.add_dirs (Fixture-Verzeichnisse, die Claude lesen darf).

Die sechs Grader-Typen​

Vier werden aus Transkript und Dateien berechnet und kosten nichts. Zwei rufen ein Judge-Modell auf und erhöhen die Rechnung.

TypKostenlos?Besteht, wenn
regexjaEin JavaScript-Regex im Ziel gefunden wird (standardmäßig last_message, oder trace, files, eine bestimmte Datei oder mock_calls). match: not_contains für Abwesenheit, match: "count:N" für eine exakte Anzahl. Groß-/Kleinschreibung-Unabhängigkeit gehört in flags: i; inline (?i) wird nicht unterstützt
tool_usedjaDie Anzahl der Aufrufe von tool, deren JSON-kodierter Input auf input_match passt, zwischen min (Default 1) und max (unbegrenzt) liegt. min: 0, max: 0 behauptet, dass ein Tool nie aufgerufen wurde
tool_orderjaBeide Tools aufgerufen wurden und der erste before-Treffer dem ersten after-Treffer vorausgeht
file_existsjaEine Datei, die Claude erstellt hat, auf den path-Glob passt (oder keine, mit exists: false). Dateien, die ein Scaffold erstellt oder Claude nur bearbeitet hat, zählen nicht
llmneinEin Judge-Modell in mindestens zwei von drei Stimmen mit PASS für deine Rubrik stimmt
baselineneinEin Judge feststellt, dass der Lauf die Kriterien mindestens so gut erfüllt wie ein Referenz-Transkript, das du als baseline_file gespeichert hast

Es gibt keine Custom-Code-Grader. Wenn du prüfen musst, ob ein Build oder Test bestanden hat, lass den Prompt Claude anweisen, ihn auszuführen und das Ergebnis in eine Datei zu schreiben, bewerte diese Datei mit regex und stelle mit einem tool_used-Grader, dessen input_match den Befehl nennt, sicher, dass er lief.

Der Skill-fired-Grader, den fast jeder Case will, sieht so aus (ersetze den Skill-Namen; das Muster passt auch auf die Namespace-Form plugin:skill):

graders/skill-fired.md — ist mein Skill wirklich gelaufen?

---
type: tool_used
tool: Skill
input_match: '"skill"\s*:\s*"(?:[\w-]+:)?your-skill-name"'
---

Und die Judge-Rubrik daneben, geschrieben als konkrete PASS/FAIL-Bedingungen statt Adjektive:

graders/criteria.md — eine Rubrik, die ein stabiles Urteil liefert

---
type: llm
weight: 2
---

PASS if the reply is a single conventional-commit subject line under 72 characters,
starts with "refactor:", and mentions both the rename (getUser -> fetchUser) and the
number of call sites updated.
FAIL if the reply contains more than one candidate message, asks a clarifying
question, or omits the rename.

Gewohnheiten, die Scores stabil halten​

Das sind die Praktiken, die die offiziellen Docs empfehlen, und sie decken sich mit dem, was jeder, der LLM-as-Judge-Pipelines betrieben hat, auf die harte Tour lernt:

  • Bewerte lange Ausgaben mit regex über die Datei, nicht mit einem llm-Judge. Die Varianz des Judges wächst mit der Länge dessen, was er liest. Behalte llm-Grader für kurze Abschlussnachrichten.
  • Ein Grader auf dem Ergebnis, einer auf dem Weg. Ein regex-/llm-/file_exists-Grader sagt dir, dass die Antwort richtig war; ein tool_used-/tool_order-Grader sagt dir, dass dein Plugin sie erzeugt hat. Du brauchst beides, um Δ zu interpretieren.
  • Verdächtige den Judge vor dem Plugin, wenn Δ negativ ist, der Skill aber gefeuert hat. Der Standard-Judge ist ein kleines, schnelles Modell; er kann eine korrekte Antwort durchfallen lassen, weil sie anders formatiert ist als die Rubrik. Führe erneut mit --judge-model sonnet aus und ziehe die Rubrik so fest, dass die Formatierung nicht entscheidet.
  • Iteriere an einem Case mit einem Arm, dann bestätige mit drei Läufen: --case <name> --runs 1 --ablation none. Mit einem Arm zeigt die Tabelle SCORE und PASS% statt WITH/W/OUT/Δ.

Mocke die MCP-Server​

Wenn die Skills deines Plugins MCP-Tools aufrufen, startet ein Lauf nie die echten Server, es sei denn, du verlangst es. Stattdessen registriert Claude Code unter dem Namen jedes Servers einen Stellvertreter und beantwortet Tool-Aufrufe aus Markdown-Dateien: evals/mocks/<server>/<tool>.md für die ganze Suite, oder der eigene mocks/-Ordner eines Cases, um pro Case zu überschreiben. Der Dateibody ist das Tool-Ergebnis, mit {{input.<field>}}-Substitutionen und {{file:fixtures/...}}-Einfügungen. Ein Tool ohne Mock-Datei ist für Claude schlicht nicht verfügbar.

evals/mocks/tracker/create_issue.md — ein Mock, der auch den Input prüft

---
expect:
title: string
priority: [low, medium, high]
---

Created issue #4821: {{input.title}}

Der expect:-Block macht aus einem Mock eine Assertion: Ein Aufruf, der ihn verletzt, bricht den Lauf mit Score 0 ab und protokolliert Server, Tool und Grund. Richte einen Grader auf target: mock_calls, um zu bewerten, was das Plugin vom Server verlangt hat. Für Server, deren Antworten vom Gesprächsverlauf abhängen, lässt type: agent ein kleines Modell den Server spielen; saubere Läufe speichern dessen Antworten unter results/<timestamp>/mock-recordings/, und sobald du eine Aufzeichnung nach mocks/.replay/<server>/ kopierst, spielen spätere Läufe sie ohne Modellaufruf ab. Committe .replay/, damit CI deterministisch ist. _tools.json (eine gespeicherte tools/list-Antwort) gibt gemockten Tools ihre echten Beschreibungen und Schemas statt eines permissiven Platzhalters.

Um stattdessen echte Server zu erreichen: --allow-real-servers startet die ohne Mocks; --mocks off ignoriert Mocks komplett. In beiden Fällen laufen diese Prozesse als du, außerhalb der Sandbox, und ihre Tools brauchen weiterhin eine explizite Freigabe wie --allow-tools "mcp__plugin_my-plugin_github__*".

Ausführen​

Guided walkthrough1 of 5
  1. Führe im Plugin-Root `claude plugin eval init` aus. Es öffnet eine interaktive Session, in der Claude das Plugin liest, fragt, wie ein gutes Ergebnis aussieht, Prompts vorschlägt, die es auslösen sollten und die es nicht auslösen sollten, Grader entwirft, sie einmal pilotiert und pro Prompt ein Case-Verzeichnis schreibt. `claude plugin eval init --bare <name>` schreibt stattdessen eine leere Vorlage (die einzige Form, die ohne Terminal funktioniert, z. B. in CI).

Der Befehl für die ganze Suite mit den Flags, nach denen du tatsächlich greifen wirst:

Die Suite mit einem stärkeren Judge und einer Kostenobergrenze ausführen

claude plugin eval . \
--judge-model sonnet \
--max-cost-usd 10 \
--allow-tools Read Write "Bash(npm test *)" \
-j 4

Anmerkungen zu den Flags: -j/--concurrency geht von 1 bis 8 und verkürzt nur die Wanduhrzeit, weil alle Läufe das Rate-Limit deines Accounts teilen. --max-cost-usd ist eine Obergrenze für die Listenpreis-Schätzung, geprüft bevor jeder Lauf startet; bereits laufende Läufe werden beendet, sodass die Ausgaben um diese Läufe überschießen können, und alles, was nicht gestartet wurde, lässt den Befehl mit Exit 2 und partial: true enden. Setze das Ziel (.) vor --tag, --allow-tools und --json: jedes davon nimmt eine Liste oder einen optionalen Wert und würde ein nachfolgendes Ziel verschlucken (der Fehler „--json output path must end in .json" ist genau dieser Fehler).

Was es kostet​

Jeder Lauf und jede Judge-Stimme ist ein echter Modellaufruf auf deinem Account, angerechnet auf die Nutzung deines Plans oder deine API-Rechnung. Die grobe Arithmetik: cases × runs Agenten-Läufe für den With-Arm, dasselbe noch einmal für den Without-Arm, plus drei kurze Judge-Aufrufe pro llm- oder baseline-Grader pro Lauf. Der einzelne Case des offiziellen Walkthroughs mit zwei Gradern (ein llm, ein tool_used) lief sechs Agenten-Läufe in 74 Sekunden bei einer Listenpreis-Schätzung von etwa 0,41 $. Drei Hebel halten eine Suite bezahlbar:

  • --ablation none halbiert die Agenten-Läufe, wenn du an Gradern iterierst und Δ nicht brauchst.
  • Nur kostenlose Grader (regex, tool_used, tool_order, file_exists) für die Suite bei jedem Commit; Judge-Grader für die nächtliche.
  • Ein Nutzungs- oder Rate-Limit-Fehler mitten in der Suite lässt jeden späteren Lauf mit diesem Fehler enden und meist mit Score 0, und die Suite wird nicht als partial markiert, sodass ein gedrosselter Lauf genau wie eine Regression aussehen kann. Prüfe die NOTES-Spalte oder cases[].arms.with[].error, bevor du einem plötzlichen Einbruch glaubst.

Mach es zum CI-Gate​

CI-Job — gepinnte Modelle, lokaler Report, Exit-Code steuert den Build

claude plugin eval . \
--trust-plugin \
--json results.json \
--threshold 0.8 \
--model claude-sonnet-5 \
--judge-model claude-haiku-4-5 \
--no-publish \
--max-cost-usd 20

Warum jedes Flag da ist:

  • --trust-plugin bestätigt die Trust-Entscheidung des ersten Laufs. Ohne es wird ein nicht-interaktiver Job mit Exit 1 verweigert (oder hängt am Prompt, wenn der Runner ein TTY zuweist). Übergib es nur für Plugins, deren Code und Suite du auf deiner eigenen Maschine ausführen würdest.
  • --model und --judge-model sind gepinnt, damit ein Modell-Rollout nie mit einer Plugin-Regression verwechselt wird. Das ist wichtiger, als es klingt: Der getestete Agent nutzt standardmäßig ANTHROPIC_MODEL oder den aktuellen Default von Claude Code, der sich mit Releases ändert.
  • --threshold 0.8, weil der Default 1.0 ist, was den Befehl mit Exit 1 enden lässt, sobald irgendein Case weniger als perfekt ist. Eine 1.0-Latte auf einem Drei-Lauf-Mittelwert eines nicht-deterministischen Agenten ist ein flackerndes Gate.
  • --json results.json schreibt das versionierte Ergebnisdokument (schemaVersion: 1, camelCase, neue Felder ohne Umbenennungen hinzugefügt) und unterdrückt die Fortschrittsausgabe.

Der Exit-Code-Vertrag:

ExitBedeutung
0Jeder Case auf oder über dem Schwellenwert und jede Case-Datei geladen
1Ein Case unter dem Schwellenwert, eine Case-Datei konnte nicht geladen werden, keine Cases gefunden, ein Lauf konnte nicht starten, nicht vertrauenswürdiges Verzeichnis ohne --trust-plugin oder eine ungültige Option
2Teillauf: Kostenobergrenze erreicht oder Credential beim oder vor dem ersten Lauf abgelehnt. results.json wird trotzdem mit partial: true geschrieben
130 / 143Unterbrochen / beendet (z. B. CI-Timeout). Teilergebnisse werden geschrieben

Probleme beim Schreiben oder Veröffentlichen des Reports ändern den Exit-Code nie. Beim Aufzeichnen von Trends lass Dokumente mit partial: true und Läufe mit skippedPaidGraders weg, da ihre Scores nicht vergleichbar sind.

Felder, die ein Gating-Skript aus dem JSON liest: aggregates.overallScore, aggregates.casesPassed / casesTotal, aggregates.meanDelta und pro Case cases[].aggregates.score und .delta (weggelassen, wenn die Arme nicht vergleichbar sind). Ein Lauf mit einem nicht-null cases[].arms.with[].error (z. B. timed out after 300s) wird trotzdem nach dem bewertet, was er produziert hat, ein Fehler impliziert also nicht Score 0; ein aborted-Lauf (das expect: eines Mocks hat gefeuert) erhält Score 0, wobei error null bleibt.

Was ein Lauf erreichen kann und was nicht​

Lies das, bevor du ein Plugin evaluierst, das du nicht geschrieben hast. claude plugin eval auf ein Verzeichnis zu richten ist dieselbe Trust-Entscheidung wie claude --plugin-dir: Die Skills und Hooks des Plugins werden auf deiner Maschine als du geladen und ausgeführt. Die Isolation begrenzt, was der getestete Agent tun kann; sie ist keine Grenze gegenüber dem eigenen Code des Plugins, und eine bestandene Suite sagt nichts darüber aus, ob das Plugin sicher ist.

  • Isolierter Agent. Jeder Lauf bekommt ein Wegwerf-Home, -Arbeitsverzeichnis und eine Wegwerf-Claude-Code-Konfiguration, läuft als claude -p-Kindprozess, kann das Eval-Verzeichnis nicht lesen (sieht also nie die Prompts oder Grader des Cases oder seiner Geschwister) und hat das Artifact-Tool abgeschaltet.
  • Verwaltete Einstellungen gelten weiterhin. Einschränkungen, die ein Administrator auf die Maschine ausgerollt hat, gelten innerhalb eines Laufs, sodass Ergebnisse auf einem verwalteten Laptop von einem nicht verwalteten CI-Runner abweichen können.
  • Opt-in-Notausgänge. Das scaffold_script eines Cases läuft als du, außerhalb der Sandbox, und nur mit --scaffold. Echte MCP-Server nur mit --allow-real-servers oder --mocks off. Die allowed_tools eines Cases oder das eigene allowed-tools-Frontmatter eines Skills können diese Grenzen nie erweitern.
  • Netzwerk. Shell-Befehle, die du gewährst, folgen den Netzwerkregeln der Sandbox; eine WebFetch(domain:…)-Freigabe erreicht diese Domain direkt; die Hooks des Plugins und jeder echte MCP-Server, den du startest, können jeden Host erreichen.

Für ein Drittanbieter-Plugin, das Hooks mitliefert oder seine echten Server braucht, behandle die Scores als unverbindlich, es sei denn, du hast die Suite in einem Container oder auf einem CI-Runner ausgeführt. Siehe Drittanbieter-Code prüfen für die umfassendere Checkliste.

Kurzreferenz: die Fallstricke​

  • Das Standard-target für regex ist last_message. Wenn du trace anvisierst, ist es JSON pro Zeile, Anführungszeichen erscheinen also als \" und Zeilenumbrüche sind escaped.
  • files ist eine Liste von Pfaden, die Claude erstellt hat, nicht deren Inhalt. Um Inhalte zu bewerten, nutze { source: file, path: <path> } als target/focus. Ein llm-Judge sieht PNG/JPEG/GIF/WebP als Bilder und verweigert andere Binärdateien (.pptx, PDF).
  • Ein llm-Judge, der trace liest, sieht nur die ersten 12 und letzten 12 Nachrichten.
  • file_exists sieht nur Dateien, die während des Laufs erstellt wurden. Eine gescaffoldete oder nur bearbeitete Datei ist dafür unsichtbar; bewerte ihren Inhalt oder nutze tool_used auf Edit.
  • Unbekannte Keys im prompt.md-Frontmatter sind ein Fehler, und env-Keys müssen EVAL_* sein.
  • Ein installiertes Plugin per Name zu evaluieren (name@marketplace) schreibt Ergebnisse unter ./evals/results/ in deinem aktuellen Verzeichnis und überspringt den Trust-Prompt.
  • Das Plugin-Eval-Case-Format ist getrennt von der evals/evals.json-Datei, die das skill-creator-Plugin für Skill-Evals nutzt.
Drücke Enter oder die Leertaste, um die Karte umzudrehen. Nutze die Pfeiltasten links und rechts, um zwischen den Karten zu wechseln.Begriff angezeigt.
1 / 7

Teste dich selbst

0/6
  1. Ein Case erreicht 1.00 WITH und 1.00 W/OUT. Was sagt dir das?
  2. Dein CI-Job führt `claude plugin eval . --json results.json` ohne weitere Flags aus und endet mit Exit 1, obwohl jeder Case 0.9 erreicht hat. Warum?
  3. Welche Grader-Typen kosten beim Ausführen nichts extra?
  4. Δ ist negativ, aber der Skill-fired-Grader hat in jedem With-Arm-Lauf bestanden. Was soll man laut offizieller Empfehlung zuerst prüfen?
  5. Ein gemocktes MCP-Tool eines Laufs erhält einen Aufruf, dessen Input den `expect:`-Block des Mocks verletzt. Was passiert?
  6. Worauf hat der getestete Agent während eines Laufs Zugriff?

Quellen und weiterführende Literatur​

Weiter​

  • Plugins und Marketplaces — paketiere, was du gerade getestet hast, und veröffentliche es, sobald die Suite grün ist
  • Skills — das description-Feld ist das, was ein fehlschlagender Skill-fired-Grader dir zu reparieren aufträgt
  • Drittanbieter-Code prüfen — bevor du das Plugin (und die Hooks) von jemand anderem auf deiner Maschine durch ein Eval jagst