> ## Documentation Index
> Fetch the complete documentation index at: https://code.claude.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Mit einem Mod auf Ereignisse reagieren

> Behandeln Sie Claude Code-Ereignisse von einem Mod aus: beobachten, schreiben Sie um oder beantworten Sie Tool-Aufrufe, Eingabeaufforderungen und Turns, filtern Sie, welche Ereignisse ein Hook behandelt, und planen Sie für andere Mods.

Ein Hook ist ein Ereignishandler: eine Funktion, die Claude Code ausführt, wenn ein benanntes Ereignis eintritt. Claude Code löst ein Ereignis an jedem Punkt aus, an dem es handeln wird, z. B. wenn es ein Tool ausführt, eine Eingabeaufforderung einreicht, eine Anfrage an das Modell sendet oder eine Sitzung startet oder beendet. Ihr Hook wird ausgeführt, bevor Claude Code handelt, sodass er das Ereignis beobachten, umschreiben oder an Stelle von Claude Code beantworten kann. Sie registrieren einen Hook mit [`on(eventName, handler)`](/docs/de/plugins/mods/reference#the-hook-function).

Erstellen Sie Ihren [ersten Mod](/docs/de/plugins/mods/create), bevor Sie hier beginnen. Für jedes Ereignis und seine genauen Felder siehe die [Referenz](/docs/de/plugins/mods/reference#events) oder lesen Sie [die Typen für Ihren Build](/docs/de/plugins/mods/create#get-the-types-for-your-build).

<h2 id="how-a-hook-handles-an-event">
  Wie ein Hook ein Ereignis behandelt
</h2>

Ein Hook sitzt zwischen einem Ereignis und dem, was Claude Code daran tun würde, sodass er das Ereignis beobachten, umschreiben oder selbst beantworten kann. Er empfängt drei Argumente: die [Mods-API](/docs/de/plugins/mods/api) als `$`, das Ereignis als `e` und den nächsten Handler als `next`. Die Handler für ein Ereignis bilden eine Middleware-Kette. `next(e)` ruft den nächsten Handler auf, der ein Hook eines anderen Mods oder am Ende der Kette Claude Codes eigenes Verhalten ist, und wird zum Ergebnis aufgelöst. Was Ihr Hook mit `next` tut, entscheidet, welches der drei er tut.

<h3 id="observe-an-event">
  Ein Ereignis beobachten
</h3>

Um ein Ereignis zu beobachten, ohne es zu ändern, führen Sie Ihre Arbeit aus und geben Sie `next(e)` zurück. Dieser Hook protokolliert jedes Tool, das Claude verwenden wird:

```javascript theme={null}
on('tool.call', async ($, e, next) => {
  // Wird ausgeführt, bevor das Tool ausgeführt wird
  $.ui.log('Claude is about to use ' + e.tool)
  // Geben Sie das Ereignis unverändert weiter
  return next(e)
})
```

Bevor jedes Tool ausgeführt wird, erscheint eine schwache Zeile wie `● my-mod: Claude is about to use Bash` im Transkript, wobei `my-mod` der Name Ihres Plugins ist. Das Tool wird so ausgeführt, wie es ohne den Mod wäre.

Um nach dem Ereignis zu handeln, `await next(e)`, führen Sie Ihre Arbeit aus und geben Sie das Ergebnis zurück. Dieser Hook protokolliert jedes Tool, nachdem es ausgeführt wurde:

```javascript theme={null}
on('tool.call', async ($, e, next) => {
  // Lassen Sie das Tool ausführen und warten Sie auf sein Ergebnis
  const result = await next(e)
  // Wird ausgeführt, nachdem das Tool ausgeführt wurde
  $.ui.log(e.tool + ' finished')
  // Geben Sie das Ergebnis unverändert zurück
  return result
})
```

Die Zeile erscheint jetzt, nachdem jedes Tool beendet ist. Claude liest das gleiche Ergebnis in beiden Fällen, da der Hook das zurückgibt, zu dem `next(e)` aufgelöst wurde.

<h3 id="rewrite-an-event">
  Ein Ereignis umschreiben
</h3>

Um zu ändern, worauf Claude Code handelt, z. B. den Text einer Eingabeaufforderung, rufen Sie `next` mit einer geänderten Kopie des Ereignisses auf. Das Ereignis selbst ist unveränderlich: es ist in jeder Tiefe eingefroren, und das Zuweisen zu einem Feld wirft einen Fehler. Dieser Hook schneidet jede Eingabeaufforderung ab, bevor sie gesendet wird:

```javascript theme={null}
on('prompt.submit', async ($, e, next) => {
  // Geben Sie eine Kopie des Ereignisses mit geändertem Text weiter
  return next({ ...e, text: e.text.trim() })
})
```

Spätere Handler und Claude Code erhalten die gekürzte Eingabeaufforderung und sehen niemals das Original. Sie können auch das Ergebnis ändern: `await next(e)`, dann geben Sie eine Kopie des Ergebnisses mit einem ersetzten Feld zurück.

<h3 id="answer-an-event">
  Ein Ereignis beantworten
</h3>

Um ein Ereignis selbst zu behandeln, geben Sie ein Ergebnis zurück, ohne `next` aufzurufen. Das unterbricht die Kette, sodass spätere Mods und Claude Codes eigenes Verhalten nicht ausgeführt werden. Dieser Hook lehnt jeden Bash-Befehl ab:

```javascript theme={null}
on('tool.call', { tool: 'Bash' }, async () => {
  // Kein Aufruf von next, daher wird der Befehl nie ausgeführt
  return { deny: 'Bash is turned off in this project. Use the file tools.' }
})
```

Wenn Claude einen Bash-Befehl versucht, wird der Befehl nicht ausgeführt, und Claude liest den `deny`-Text als Ergebnis des Tools. Jedes Ereignis hat seine eigene Ergebnisform, die die [Ereignisreferenz](/docs/de/plugins/mods/reference#events) auflistet.

<h3 id="filter-which-events-a-hook-handles">
  Filtern Sie, welche Ereignisse ein Hook behandelt
</h3>

Um einen Hook nur für einige Ereignisse auszuführen, übergeben Sie einen Filter als zweites Argument an `on`. Claude Code nennt den Filter einen Matcher. Es ist ein Objekt, dessen Felder mit denen des Ereignisses verglichen werden, und der Hook wird nur ausgeführt, wenn jedes Feld übereinstimmt. Ein Feld kann ein Wert, ein Array zulässiger Werte oder ein regulärer Ausdruck sein.

Jede Zeile in diesem Beispiel registriert die gleiche Funktion, `hook`, für einen engeren Satz von Tool-Aufrufen:

```javascript theme={null}
// Ein String passt zu einem Wert: nur Bash-Aufrufe
on('tool.call', { tool: 'Bash' }, hook)
// Ein Array passt zu jedem Wert darin: Edit-Aufrufe und Write-Aufrufe
on('tool.call', { tool: ['Edit', 'Write'] }, hook)
// Ein regulärer Ausdruck passt nach Muster: jedes Tool eines MCP-Servers
on('tool.call', { tool: /^mcp__github__/ }, hook)
```

`hook` wird einmal für einen Bash-, Edit- oder Write-Aufruf ausgeführt und einmal für einen Aufruf zu einem Tool, dessen Name mit `mcp__github__` beginnt. Ein Aufruf zu jedem anderen Tool, z. B. Read, passt zu keinem der drei, daher wird `hook` nicht dafür ausgeführt.

Der Ereignisname kann ein Platzhalter sein. `'classic.*'` passt zu jedem [Settings-Hook-Ereignis](#hook-the-settings-hook-events). `'*'` passt zu jedem Ereignis außer den [Telemetrie-Ereignissen](/docs/de/plugins/mods/reference#telemetry), die Sie nach Name oder als `'telemetry.*'` hooken.

Registrieren Sie jedes Ereignis einmal pro Matcher. Wenn Sie `on` zweimal für `session.start` ohne Matcher aufrufen, schlägt das Modul mit `on("session.start") is registered twice without a matcher` fehl. Fügen Sie alles, was Ihr Mod beim Sitzungsstart tut, in einen Hook ein.

<h2 id="hook-what-claude-is-doing">
  Hook, was Claude tut
</h2>

Hooken Sie diese Ereignisse, um einen Tool-Aufruf, eine Eingabeaufforderung oder einen Turn zu sehen oder zu ändern, während er stattfindet. Für jedes Ereignis und was ein Hook zurückgeben kann, siehe die [Ereignisreferenz](/docs/de/plugins/mods/reference#events).

<h3 id="guard-or-change-a-tool-call">
  Schützen oder ändern Sie einen Tool-Aufruf
</h3>

Ein `tool.call`-Hook sieht jedes Tool, das Claude verwenden wird, sodass er den Aufruf ablehnen, seine Argumente ändern oder ihn durchlassen kann. `tool.call` wird ausgelöst, wenn Claude Code ein Tool ausführen wird, einschließlich Aufrufe, die ein Subagent tätigt, und Aufrufe zu MCP-Tools. `e.tool` ist der Name des Tools und die Argumente des Tools sind Felder von `e`, z. B. `e.command` für Bash. Wenn Sie `next(e)` aufrufen, führt Claude Code die Berechtigungsprüfung und dann das Tool aus.

Dieser Hook lehnt einen Bash-Befehl ab, der Force-Push durchführt, und teilt Claude mit, warum:

```javascript theme={null}
// Der Matcher begrenzt den Hook auf Bash-Aufrufe, daher ist e.command der Shell-Befehl
on('tool.call', { tool: 'Bash' }, async ($, e, next) => {
  if (/git push .*--force/.test(e.command)) {
    // Rückgabe ohne Aufruf von next beantwortet das Ereignis, daher wird der Befehl nie ausgeführt
    return { deny: 'Force pushes are not allowed in this repository. Push to a new branch instead.' }
  }
  // Jeder andere Befehl geht zur Berechtigungsprüfung und dann zu Bash
  return next(e)
})
```

Wenn Claude `git push --force` versucht, wird der Befehl nicht ausgeführt und es erscheint keine Berechtigungsaufforderung, da der Hook `next` nie aufruft. Claude liest den `deny`-Text als Ergebnis des Tools, daher schreiben Sie ihn als Anweisung, auf die Claude reagieren kann. Jeder andere Bash-Befehl wird so ausgeführt, wie er ohne den Mod wäre.

Um nach Ausführung eines Tools zu handeln, `await next(e)`, führen Sie Ihre Arbeit aus und geben Sie das zurück, was `next` Ihnen gab. Dieser Hook protokolliert jede `.mdx`-Datei, die Claude ändert, mit [`$.ui.log`](/docs/de/plugins/mods/api#show-something-without-starting-a-turn), das eine schwache Zeile zum Transkript hinzufügt, die Claude nicht liest:

```javascript theme={null}
on('tool.call', { tool: ['Edit', 'Write'] }, async ($, e, next) => {
  // Warten Sie auf die Berechtigungsprüfung und das Tool und behalten Sie, was sie produziert haben
  const result = await next(e)
  // Ein abgelehnter Aufruf kommt als { deny } zurück, und ein fehlgeschlagener hat isError gesetzt
  const changed = !result.deny && !result.isError
  if (changed && e.file_path.endsWith('.mdx')) $.ui.log('Claude changed ' + e.file_path)
  // Geben Sie das Ergebnis so zurück, wie es kam, damit Claude liest, was das Tool zurückgegeben hat
  return result
})
```

Nachdem Claude eine `.mdx`-Datei bearbeitet oder geschrieben hat, benennt eine schwache Zeile im Transkript die Datei. Nichts wird für eine andere Art von Datei protokolliert oder für einen Aufruf, der abgelehnt oder fehlgeschlagen ist. Claude's Ansicht des Aufrufs ändert sich nicht, da der Hook das Ergebnis zurückgibt, das er erhalten hat.

Um einen Aufruf zu ändern, übergeben Sie geänderte Argumente an `next`. Um einen Aufruf zu wiederholen, rufen Sie `next(e)` erneut auf: Ein Hook, der `isError` beim ersten Ergebnis sieht, kann das Tool ein zweites Mal ausführen und dieses Ergebnis zurückgeben. Um einen Aufruf selbst zu beantworten, geben Sie ein Objekt mit einem `result`-Feld zurück, z. B. `{ result: 'Skipped by my-mod' }`, ohne `next` aufzurufen. Wenn Sie das tun, erscheint keine Berechtigungsaufforderung und das Tool wird nicht ausgeführt, daher ist das Ergebnis, das Sie zurückgeben, alles, was Claude über das Geschehene erfährt.

Hooks in den [verwalteten Einstellungen](/docs/de/server-managed-settings) Ihrer Organisation werden vor jedem `tool.call`-Hook eines Mods ausgeführt, und ein Block von einem von ihnen ist endgültig.

<h4 id="hold-a-tool-call-until-the-user-decides">
  Halten Sie einen Tool-Aufruf an, bis der Benutzer entscheidet
</h4>

Ein Hook kann einen Tool-Aufruf anhalten und den Benutzer fragen, was zu tun ist, bevor er fortfährt. Ein `tool.call`-Hook kann `await` durchführen, bevor er `next` aufruft oder zurückgibt, und der Tool-Aufruf bleibt ausstehend, bis dann. Um die Frage dem Benutzer zu stellen, rufen Sie `$.ui.ask` auf. Es zeigt Ihre Frage über einer nummerierten Liste Ihrer Optionen in dem Dialog an, den Claude verwendet, um Sie etwas zu fragen, und wird zur Bezeichnung aufgelöst, die der Benutzer auswählt. Nach Ihren Optionen fügt der Dialog eine Zeile zum Eingeben einer anderen Antwort und eine Zeile **Chat about this** hinzu.

Das `RISKY`-Muster in diesem Beispiel passt zu `rm -r`, `rm -rf`, `git reset --hard` und `git push` mit `--force` und verfehlt andere Schreibweisen wie `git push -f`. Dieses Modul fragt, bevor es einen Bash-Befehl ausführt, der dem Muster entspricht:

```javascript theme={null}
const RISKY = /\brm\s+-rf?\b|\bgit\s+reset\s+--hard\b|\bgit\s+push\b.*--force/

export function register(on) {
  on('tool.call', { tool: 'Bash' }, async ($, e, next) => {
    // Lassen Sie jeden anderen Befehl ohne Frage durch
    if (!RISKY.test(e.command)) return next(e)
    // Beginnen Sie mit der sicheren Antwort, damit eine Frage, die niemand beantwortet, den Befehl ablehnt
    let answer = 'Refuse'
    try {
      // Der Tool-Aufruf wartet hier, bis der Benutzer eine der beiden Bezeichnungen auswählt
      answer = await $.ui.ask('Run this command? ' + e.command, ['Run it', 'Refuse'])
    } catch {
      // Der Benutzer hat die Frage verworfen oder dies ist ein claude -p-Lauf mit niemandem zum Fragen
    }
    if (answer !== 'Run it') {
      // Antwort ohne Aufruf von next, daher wird der Befehl nicht ausgeführt
      return { deny: 'The user declined this command. Ask before trying a different approach.' }
    }
    return next(e)
  })
}
```

Wenn Claude einen Befehl wie `rm -rf build` versucht, erscheint die Frage mit dem Befehl darin, und der Befehl wartet auf die Antwort:

* **Der Benutzer wählt Run it**: Der Hook ruft `next(e)` auf, und die übliche Berechtigungsprüfung wird danach immer noch ausgeführt
* **Der Benutzer wählt Refuse**: Der Befehl wird nicht ausgeführt, und Claude liest den `deny`-Text
* **Der Benutzer gibt eine Antwort ein**: `$.ui.ask` wird zur eingegebenen Antwort aufgelöst. Der Hook vergleicht sie mit `Run it`, daher lehnt jeder andere Text den Befehl ab.
* **Niemand antwortet**: `$.ui.ask` wird abgelehnt, wenn der Benutzer die Frage verwirft oder **Chat about this** auswählt, und in einem `claude -p`-Lauf, daher lässt der `catch`-Block die Antwort bei `Refuse`

Halten Sie das Warten in einem Mods-API-Aufruf wie `$.ui.ask`, da diese Zeit nicht gegen das [10-Sekunden-Zeitlimit](/docs/de/plugins/mods/reference#limits) des Hooks zählt. Zeit, die mit dem Warten auf ein eigenes Promise verbracht wird, zählt. Claude Code überspringt einen Hook, der das Zeitlimit überschreitet, daher würde der gehaltene Befehl ausgeführt.

<h3 id="rewrite-or-add-to-a-prompt">
  Schreiben Sie eine Eingabeaufforderung um oder fügen Sie sie hinzu
</h3>

Ein `prompt.submit`-Hook sieht jede Eingabeaufforderung, bevor der Turn beginnt, sodass er den Text umschreiben oder hinzufügen kann. `e.text` ist das, was eingegeben wurde.

| Um dies zu tun | Geben Sie dies zurück |
| :- | :- |
| Schreiben Sie die Eingabeaufforderung um. Die Nachricht im Transkript zeigt den neuen Text. | `next({ ...e, text: newText })` |
| Fügen Sie Text hinzu, den nur Claude liest, nach der Eingabeaufforderung | `next({ ...e, context: [...(e.context ?? []), extraText] })` |
| Verhindern Sie, dass die Eingabeaufforderung gesendet wird | `{ drop: 'the reason' }` |

Dieser Hook fügt den aktuellen Branch-Namen für Claude hinzu, wenn eine Eingabeaufforderung einen Pull Request erwähnt:

```javascript theme={null}
on('prompt.submit', async ($, e, next) => {
  // Geben Sie eine Eingabeaufforderung weiter, die keinen Pull Request erwähnt, wie sie ist
  if (!/\bPR\b|pull request/i.test(e.text)) return next(e)
  const git = await $.process.run(['git', 'branch', '--show-current'])
  // Außerhalb eines Git-Repositorys schlägt der Befehl fehl, daher gibt es keinen Branch zum Hinzufügen
  if (git.exitCode !== 0) return next(e)
  // Behalten Sie jeden Kontext, den ein früherer Hook hinzugefügt hat, und fügen Sie eine weitere Zeile für Claude hinzu
  return next({ ...e, context: [...(e.context ?? []), 'Current branch: ' + git.stdout.trim()] })
})
```

Wenn Sie eine Eingabeaufforderung wie `open a PR for this change` senden, sieht Ihre Nachricht im Transkript gleich aus, und Claude liest auch eine Zeile wie `Current branch: feature/auth` danach. Eine Eingabeaufforderung, die keinen Pull Request erwähnt, wird unverändert weitergeleitet, und `git` wird nicht ausgeführt.

[Andere Ereignisse](/docs/de/plugins/mods/reference#prompts-and-what-claude-reads) behandeln den Rest dessen, was Claude liest: `prompt.section` für jeden Abschnitt der Systemaufforderung, `prompt.context` für den Kontext, der mit der ersten Nachricht gesendet wird, und `skill.prompt` für den Text einer Fähigkeit. Text aus diesen Hooks, der sich zwischen Anfragen ändert, [invalidiert den Prompt-Cache](/docs/de/prompt-caching).

<h3 id="follow-a-turn">
  Folgen Sie einem Turn
</h3>

Ein Turn ist alles, was Claude als Antwort auf eine Eingabeaufforderung tut. Hooken Sie `turn.start`, `turn.step` und `turn.complete`, um einen zu folgen:

| Ereignis | Wann es ausgelöst wird | Was ein Hook tun kann |
| :- | :- | :- |
| `turn.start` | Ein Turn beginnt | Beobachten. `e.turnId` identifiziert den Turn in den anderen beiden Ereignissen. |
| `turn.step` | Claude Code wird eine Anfrage an das Modell senden. Ein Turn mit Tool-Aufrufen hat mehrere. `e.agentId` wird für eine Anfrage eines Subagenten gesetzt. | Lesen Sie die Token-Nutzung jeder Anfrage, senden Sie sie mit `next({ ...e, model })` an ein anderes Modell, oder beantworten Sie ohne Aufruf des Modells |
| `turn.complete` | Der Turn endete, einschließlich eines Turns, den der Benutzer unterbrochen hat, wobei `e.isAborted` `true` ist. `e.answer` ist Claude's endgültiger Text, `e.durationMs` wie lange es dauerte, und `e.usage` die Token-Gesamtwerte des Turns. Ein Turn eines Subagenten wird es mit `e.agentId` gesetzt auslösen. | Beobachten, oder geben Sie ein Objekt mit einem `text`-Feld zurück, z. B. `{ text: 'Done in 12 seconds' }`, um eine Zeile unter der Antwort anzuzeigen |

Schreiben Sie einen `turn.step`-Hook als asynchronen Generator, da das Ereignis streamt. `yield* next(e)` leitet die Antwort weiter, während sie streamt, und wird zum fertigen Ergebnis ausgewertet. Dieser Hook protokolliert, wie viel von jeder Anfrage die Claude-API aus dem [Prompt-Cache](/docs/de/prompt-caching) bedient hat:

```javascript theme={null}
// function* macht den Hook zu einem Generator, der die Antwort Stück für Stück weitergeben kann
on('turn.step', async function* ($, e, next) {
  // Senden Sie die Anfrage, leiten Sie jedes Stück weiter, während es ankommt, und behalten Sie das fertige Ergebnis
  const result = yield* next(e)
  // Überspringen Sie ein Ergebnis, das keine Token-Zählungen meldet
  if (result.usage) {
    $.ui.log('cache read ' + result.usage.cache_read_input_tokens + ' · wrote ' + result.usage.cache_creation_input_tokens)
  }
  // Geben Sie das Ergebnis unverändert zurück, damit der Turn wie gewohnt fortfährt
  return result
})
```

Claude's Antwort streamt auf den Bildschirm, wie es ohne den Mod wäre. Nachdem jede Anfrage beendet ist, gibt eine schwache Zeile im Transkript die Anzahl der aus dem Cache gelesenen Token und die Anzahl der darin geschriebenen Token an. Ein Turn mit Tool-Aufrufen hat mehrere Anfragen, daher fügt er mehrere Zeilen hinzu.

`result.usage` enthält die vier Token-Zählungen, die die Claude-API für eine Anfrage meldet, plus das `model`, das geantwortet hat: `input_tokens`, `output_tokens`, `cache_read_input_tokens` und `cache_creation_input_tokens`. Der Hook wird auch für Anfragen von Subagenten ausgeführt, daher überprüfen Sie `e.agentId`, wenn Sie nur die Hauptkonversation möchten.

<h3 id="hook-the-settings-hook-events">
  Hooken Sie die Settings-Hook-Ereignisse
</h3>

Settings-Hooks sind die Befehls-, HTTP-, Eingabeaufforderungs- und Agent-Hooks, die Sie in Einstellungsdateien konfigurieren. Jedes [Settings-Hook-Ereignis](/docs/de/hooks#hook-events), z. B. `Stop`, `SessionEnd` oder `PostToolUse`, ist auch ein Ereignis mit dem Namen `classic.` gefolgt vom Namen des Settings-Hook-Ereignisses, z. B. `classic.Stop`. `e` ist das JSON, das ein Settings-Hook auf stdin empfängt, einschließlich `transcript_path`.

Dieser Hook verwendet `Stop`, das ausgelöst wird, wenn Claude die Antwort beendet, um zu protokollieren, wo das Transkript der Sitzung gespeichert ist:

```javascript theme={null}
on('classic.Stop', async ($, e, next) => {
  // e hat die gleichen Felder, die ein Stop-Hook in einer Einstellungsdatei von stdin liest
  $.ui.log('Transcript saved at ' + e.transcript_path)
  // Geben Sie das Ereignis weiter, damit Stop-Hooks in Ihren Einstellungsdateien immer noch ausgeführt werden
  return next(e)
})
```

Jedes Mal, wenn Claude die Antwort beendet, gibt eine schwache Zeile im Transkript den Pfad der Transkriptdatei an. Der Hook gibt `next(e)` zurück, daher beobachtet er das Ereignis und ändert nichts daran, wie der Turn endet.

<h2 id="run-alongside-other-mods">
  Führen Sie neben anderen Mods aus
</h2>

Mehrere Mods können das gleiche Ereignis hooken, und jeder von ihnen kann fehlschlagen. Wenn Ihr Mod Tool-Aufrufe blockiert, überprüfen Sie seine Position in der Kette und was passiert, wenn sein Hook fehlschlägt.

<h3 id="the-order-mods-run-in">
  Die Reihenfolge, in der Mods ausgeführt werden
</h3>

Hooks auf dem gleichen Ereignis bilden eine Middleware-Kette. Jeder `next` eines Mods ruft den Hook des folgenden Mods auf, und der letzte `next` erreicht Claude Codes eigenes Verhalten. Der erste Mod ist am weitesten außen: Er sieht das Ereignis vor den anderen und das Ergebnis nach ihnen, und er entscheidet, ob die anderen überhaupt ausgeführt werden. Ein späterer Mod kann einen früheren nicht daran hindern, ein Ereignis zu sehen.

Claude Code ordnet die Kette danach, woher jeder Mod kommt:

1. Der eingebaute Guard `sec-default@builtin`, ein in Claude Code eingebauter Mod, den `/plugin` als `cc-plugin-sec-default` auflistet, wo [er lädt](/docs/de/plugins/mods/admin#know-what-happens-by-default), Mods, die Ihre Organisation in [`prependPlugins`](/docs/de/plugins/mods/admin#install-your-organizations-mods) auflistet, und dann jeden anderen Mod, der als Mod Ihrer Organisation zählt und nicht in `appendPlugins` ist
2. Mods, die Sie installieren
3. Mods, die Ihre Organisation in `appendPlugins` auflistet
4. Andere in Claude Code eingebaute Mods

Unter den Mods, die Sie installieren, wird ein Mod vor den Mods ausgeführt, die er unter `dependencies` in seinem Manifest auflistet. Innerhalb eines Moduls werden Hooks in der Reihenfolge ausgeführt, in der `register` `on` aufgerufen hat.

<h4 id="where-settings-hooks-run-in-the-order">
  Wo Settings-Hooks in der Reihenfolge ausgeführt werden
</h4>

Die `PreToolUse`-Hooks, die in Einstellungsdateien konfiguriert sind, werden auch während eines Tool-Aufrufs an festen Punkten in der Kette von Mods ausgeführt:

* **`PreToolUse`-Hooks aus verwalteten Einstellungen**: werden vor dem Hook `tool.call` des ersten Mods ausgeführt, und ein Block von einem von ihnen ist endgültig, daher sieht kein Mod den Aufruf.
* **`PreToolUse`-Hooks aus jeder anderen Einstellungsdatei und aus `hooks/hooks.json` von Plugins**: werden nach dem letzten Aufruf von `next` eines Mods ausgeführt, als Teil von Claude Codes eigenem Verhalten. Ein Mod, der `tool.call` beantwortet, ohne `next` aufzurufen, hindert sie daran, ausgeführt zu werden, und ein Mod, der `next` aufruft, sieht ihre Entscheidung im Ergebnis, das er zurückgibt.

[`tool.check`](/docs/de/plugins/mods/reference#tools) ist das Ereignis, bei dem Claude Code entscheidet, ob ein Tool-Aufruf ausgeführt werden darf. Es wird nach diesen Hooks und den Berechtigungsregeln ausgelöst, und `next(e)` wird zu ihrer Entscheidung aufgelöst. Ein Hook auf `tool.check` kann eine andere Entscheidung zurückgeben, z. B. `{ decision: 'allow' }`, daher kann er einen Aufruf genehmigen, den ein Hook in der zweiten Gruppe blockiert hat. [Erweitern Sie Berechtigungen mit Hooks](/docs/de/permissions#extend-permissions-with-hooks) listet auf, welche Entscheidungen einen Mod überlagern.

<h3 id="handle-a-hook-that-fails">
  Behandeln Sie einen Hook, der fehlschlägt
</h3>

Ein Hook, der fehlschlägt, bricht die Sitzung nicht, und Sie können entscheiden, was stattdessen passiert. Wenn ein Hook ohne `.catch`-Handler wirft, das Zeitlimit überschreitet oder ein Ergebnis der falschen Form zurückgibt, hängt das, was als nächstes passiert, davon ab, ob er `next` aufgerufen hatte:

* **Es ist fehlgeschlagen, bevor `next` aufgerufen wurde**: Claude Code überspringt es, und der nächste Handler wird an seiner Stelle ausgeführt
* **Es ist fehlgeschlagen, nachdem `next` aufgelöst wurde**: Dieses Ergebnis bleibt bestehen, und nichts wird ein zweites Mal ausgeführt

Eine Zeile benennt den Mod, das Ereignis und den Grund, z. B. `my-mod: tool.call hook skipped: threw Error: boom`. Wo Sie es lesen, hängt von der Sitzung ab, wie [Finden Sie heraus, warum ein Mod nichts tut](/docs/de/plugins/mods/troubleshoot#find-out-why-a-mod-does-nothing) auflistet. Ein `ui.render`-Hook, dessen Zeichnung nicht validiert, wird anders gemeldet, wie [Erstellen Sie einen Baum aus Elementen](/docs/de/plugins/mods/interface#build-a-tree-from-elements) beschreibt.

Um einen Hook, der Aufrufe blockiert, fehlgeschlagen zu schließen, fügen Sie einen `.catch`-Fehlerhandler hinzu, der stattdessen antwortet. Hier ist `guard` Ihre Hook-Funktion:

```javascript theme={null}
// on gibt eine Registrierung zurück, und .catch fügt einen Handler an diesen einen Hook an
on('tool.call', { tool: 'Bash' }, guard).catch(async ($, e, next) => {
  // next.error.kind ist 'throw' oder 'timeout', was sagt, wie guard fehlgeschlagen ist
  return { deny: 'The command guard failed, so this command was not run: ' + next.error.kind }
})
```

Während `guard` funktioniert, wird der Handler nie ausgeführt. Wenn `guard` bei einem Bash-Aufruf wirft oder das Zeitlimit überschreitet, ruft Claude Code den Handler mit dem gleichen Ereignis auf. Der Handler gibt `{ deny }` zurück, daher wird der Befehl nicht ausgeführt, und Claude liest den Text mit `throw` oder `timeout` am Ende. Ohne den Handler würde Claude Code `guard` überspringen und den Befehl ausführen. Der Handler hat [eine Sekunde](/docs/de/plugins/mods/reference#limits) Zeit zum Antworten.

<h2 id="next-steps">
  Nächste Schritte
</h2>

* [Verwenden Sie die Mods-API](/docs/de/plugins/mods/api): Fügen Sie Befehle und Tools hinzu, rufen Sie ein Modell auf und führen Sie Arbeit auf einem Timer aus
* [Zeichnen Sie in der Schnittstelle](/docs/de/plugins/mods/interface): Zeigen Sie, was Ihre Hooks in einem Bereich oder über der Eingabeaufforderung sammeln
* [Testen Sie einen Mod](/docs/de/plugins/mods/test): Lösen Sie eines dieser Ereignisse aus einem Test aus
* [Mods-Referenz](/docs/de/plugins/mods/reference): Jedes Ereignis, jede Mods-API-Methode und die Limits
