2> Fetch the complete documentation index at: https://code.claude.com/docs/llms.txt2> Fetch the complete documentation index at: https://code.claude.com/docs/llms.txt
3> Use this file to discover all available pages before exploring further.3> Use this file to discover all available pages before exploring further.
4 4
5# Mit einem Mod auf Ereignisse reagieren5# Mit einem Mod auf Events reagieren
6 6
7> 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.7> Verarbeiten Sie Claude Code-Events in einem Mod: Beobachten, umschreiben oder beantworten Sie Tool-Aufrufe, Prompts und Turns, filtern Sie, welche Events ein Hook verarbeitet, und planen Sie für andere Mods.
8 8
9Ein 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).9Ein Hook ist ein Event-Handler: eine Funktion, die Claude Code ausführt, wenn ein benanntes Event eintritt. Claude Code löst an jeder Stelle ein Event aus, an der es im Begriff ist, eine Aktion auszuführen, etwa wenn es ein Tool ausführt, einen Prompt absendet, eine Anfrage an das Modell sendet oder eine Sitzung startet oder beendet. Ihr Hook wird ausgeführt, bevor Claude Code handelt, sodass er das Event beobachten, umschreiben oder anstelle von Claude Code beantworten kann. Sie registrieren einen Hook mit [`on(eventName, handler)`](/docs/de/plugins/mods/reference#the-hook-function).
10 10
11Erstellen 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).11Erstellen Sie Ihren [ersten Mod](/docs/de/plugins/mods/create), bevor Sie hier beginnen. Alle Events und ihre genauen Felder finden Sie in der [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).
12 12
13<h2 id="how-a-hook-handles-an-event">13<h2 id="how-a-hook-handles-an-event">
14 Wie ein Hook ein Ereignis behandelt14 Wie ein Hook ein Ereignis verarbeitet
15</h2>15</h2>
16 16
17Ein 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.17Ein Hook sitzt zwischen einem Ereignis und dem, was Claude Code daraufhin tun würde. Er kann das Ereignis daher beobachten, umschreiben oder selbst beantworten. Er erhält 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, also den Hook eines anderen Mods oder, am Ende der Kette, das eigene Verhalten von Claude Code, und wird zum Ergebnis aufgelöst. Was Ihr Hook mit `next` macht, bestimmt, welche der drei Möglichkeiten er umsetzt.
18 18
19<h3 id="observe-an-event">19<h3 id="observe-an-event">
20 Ein Ereignis beobachten20 Ein Ereignis beobachten
21</h3>21</h3>
22 22
23Um 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:23Um ein Ereignis zu beobachten, ohne es zu ändern, erledigen Sie Ihre Arbeit und geben `next(e)` zurück. Dieser Hook protokolliert jedes Tool, das Claude gleich verwenden wird:
24 24
25```javascript theme={null}25```javascript theme={null}
26on('tool.call', async ($, e, next) => {26on('tool.call', async ($, e, next) => {
27 // Wird ausgeführt, bevor das Tool ausgeführt wird27 // Runs before the tool does
28 $.ui.log('Claude is about to use ' + e.tool)28 $.ui.log('Claude is about to use ' + e.tool)
29 // Geben Sie das Ereignis unverändert weiter29 // Pass the event on unchanged
30 return next(e)30 return next(e)
31})31})
32```32```
33 33
34Bevor 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.34Bevor jedes Tool ausgeführt wird, erscheint im Transkript eine abgeblendete Zeile wie `● my-mod: Claude is about to use Bash`, wobei `my-mod` der Name Ihres Plugins ist. Das Tool wird so ausgeführt, wie es auch ohne den Mod ausgeführt würde.
35 35
36Um 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:36Um nach dem Ereignis zu handeln, verwenden Sie `await next(e)`, erledigen Ihre Arbeit und geben das Ergebnis zurück. Dieser Hook protokolliert jedes Tool, nachdem es ausgeführt wurde:
37 37
38```javascript theme={null}38```javascript theme={null}
39on('tool.call', async ($, e, next) => {39on('tool.call', async ($, e, next) => {
40 // Lassen Sie das Tool ausführen und warten Sie auf sein Ergebnis40 // Let the tool run, and wait for its result
41 const result = await next(e)41 const result = await next(e)
42 // Wird ausgeführt, nachdem das Tool ausgeführt wurde42 // Runs after the tool does
43 $.ui.log(e.tool + ' finished')43 $.ui.log(e.tool + ' finished')
44 // Geben Sie das Ergebnis unverändert zurück44 // Give the result back unchanged
45 return result45 return result
46})46})
47```47```
48 48
49Die 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.49Die Zeile erscheint jetzt, nachdem jedes Tool abgeschlossen ist. Claude liest in beiden Fällen dasselbe Ergebnis, da der Hook zurückgibt, wozu `next(e)` aufgelöst wurde.
50 50
51<h3 id="rewrite-an-event">51<h3 id="rewrite-an-event">
52 Ein Ereignis umschreiben52 Ein Ereignis umschreiben
53</h3>53</h3>
54 54
55Um 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:55Um zu ändern, worauf Claude Code reagiert, etwa den Text eines Prompts, rufen Sie `next` mit einer geänderten Kopie des Ereignisses auf. Das Ereignis selbst ist unveränderlich: Es ist tief eingefroren, und eine Zuweisung an ein Feld löst einen Fehler aus. Dieser Hook entfernt bei jedem Prompt vor dem Senden führende und nachfolgende Leerzeichen:
56 56
57```javascript theme={null}57```javascript theme={null}
58on('prompt.submit', async ($, e, next) => {58on('prompt.submit', async ($, e, next) => {
59 // Geben Sie eine Kopie des Ereignisses mit geändertem Text weiter59 // Pass on a copy of the event with its text changed
60 return next({ ...e, text: e.text.trim() })60 return next({ ...e, text: e.text.trim() })
61})61})
62```62```
63 63
64Spä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.64Nachfolgende Handler und Claude Code erhalten den gekürzten Prompt und sehen das Original nie. Sie können auch das Ergebnis ändern: Verwenden Sie `await next(e)` und geben Sie dann eine Kopie des Ergebnisses zurück, in der ein Feld ersetzt ist.
65 65
66<h3 id="answer-an-event">66<h3 id="answer-an-event">
67 Ein Ereignis beantworten67 Ein Ereignis beantworten
68</h3>68</h3>
69 69
70Um 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:70Um ein Ereignis selbst zu verarbeiten, geben Sie ein Ergebnis zurück, ohne `next` aufzurufen. Dadurch wird die Kette abgekürzt, sodass nachfolgende Mods und das eigene Verhalten von Claude Code nicht ausgeführt werden. Dieser Hook lehnt jeden Bash-Befehl ab:
71 71
72```javascript theme={null}72```javascript theme={null}
73on('tool.call', { tool: 'Bash' }, async () => {73on('tool.call', { tool: 'Bash' }, async () => {
74 // Kein Aufruf von next, daher wird der Befehl nie ausgeführt74 // No call to next, so the command never runs
75 return { deny: 'Bash is turned off in this project. Use the file tools.' }75 return { deny: 'Bash is turned off in this project. Use the file tools.' }
76})76})
77```77```
78 78
79Wenn 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.79Wenn Claude einen Bash-Befehl versucht, wird der Befehl nicht ausgeführt, und Claude liest den `deny`-Text als Ergebnis des Tools. Jedes Ereignis hat eine eigene Ergebnisstruktur, die in der [Ereignisreferenz](/docs/de/plugins/mods/reference#events) aufgeführt ist.
80 80
81<h3 id="filter-which-events-a-hook-handles">81<h3 id="filter-which-events-a-hook-handles">
82 Filtern Sie, welche Ereignisse ein Hook behandelt82 Filtern, welche Ereignisse ein Hook verarbeitet
83</h3>83</h3>
84 84
85Um 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.85Um einen Hook nur für bestimmte Ereignisse auszuführen, übergeben Sie einen Filter als zweites Argument an `on`. Claude Code nennt den Filter einen Matcher. Es handelt sich um 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.
86 86
87Jede Zeile in diesem Beispiel registriert die gleiche Funktion, `hook`, für einen engeren Satz von Tool-Aufrufen:87Jede Zeile in diesem Beispiel registriert dieselbe Funktion, `hook`, für eine engere Auswahl von Tool-Aufrufen:
88 88
89```javascript theme={null}89```javascript theme={null}
90// Ein String passt zu einem Wert: nur Bash-Aufrufe90// A string matches one value: Bash calls only
91on('tool.call', { tool: 'Bash' }, hook)91on('tool.call', { tool: 'Bash' }, hook)
92// Ein Array passt zu jedem Wert darin: Edit-Aufrufe und Write-Aufrufe92// An array matches any value in it: Edit calls and Write calls
93on('tool.call', { tool: ['Edit', 'Write'] }, hook)93on('tool.call', { tool: ['Edit', 'Write'] }, hook)
94// Ein regulärer Ausdruck passt nach Muster: jedes Tool eines MCP-Servers94// A regular expression matches by pattern: every tool of one MCP server
95on('tool.call', { tool: /^mcp__github__/ }, hook)95on('tool.call', { tool: /^mcp__github__/ }, hook)
96```96```
97 97
98`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.98`hook` wird einmal für einen Bash-, Edit- oder Write-Aufruf ausgeführt und einmal für einen Aufruf eines Tools, dessen Name mit `mcp__github__` beginnt. Ein Aufruf eines anderen Tools, etwa Read, stimmt mit keinem der drei überein, sodass `hook` dafür nicht ausgeführt wird.
99 99
100Der 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.100Der Ereignisname kann ein Platzhalter sein. `'classic.*'` passt auf jedes [Einstellungs-Hook-Ereignis](#hook-the-settings-hook-events). `'*'` passt auf jedes Ereignis außer den [Telemetrie-Ereignissen](/docs/de/plugins/mods/reference#telemetry), die ihren eigenen Namen und einen `{ to: 'collector' }`-Filter verwenden.
101 101
102Registrieren 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.102Registrieren Sie jedes Ereignis nur einmal pro Matcher. Wenn Sie `on` zweimal für `session.start` ohne Matcher aufrufen, kann das Modul nicht geladen werden und meldet `on("session.start") is registered twice without a matcher`. Fassen Sie alles, was Ihr Mod beim Sitzungsstart tut, in einem Hook zusammen.
103 103
104<h2 id="hook-what-claude-is-doing">104<h2 id="hook-what-claude-is-doing">
105 Hook, was Claude tut105 Auf das reagieren, was Claude tut
106</h2>106</h2>
107 107
108Hooken 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).108Behandeln Sie diese Events, um einen Tool-Aufruf, einen Prompt oder einen Turn zu sehen oder zu ändern, während er stattfindet. Alle Events und was ein Hook jeweils zurückgeben kann, finden Sie in der [Event-Referenz](/docs/de/plugins/mods/reference#events).
109 109
110<h3 id="guard-or-change-a-tool-call">110<h3 id="guard-or-change-a-tool-call">
111 Schützen oder ändern Sie einen Tool-Aufruf111 Einen Tool-Aufruf absichern oder ändern
112</h3>112</h3>
113 113
114Ein `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.114Ein `tool.call`-Hook sieht jedes Tool, das Claude gleich verwenden wird, und kann den Aufruf daher ablehnen, seine Argumente ändern oder ihn durchlassen. `tool.call` wird ausgelöst, wenn Claude Code gleich ein Tool ausführt, einschließlich Aufrufen eines Subagenten und Aufrufen von MCP-Tools. `e.tool` ist der Name des Tools, und die Argumente des Tools sind Felder von `e`, etwa `e.command` für Bash. Wenn Sie `next(e)` aufrufen, führt Claude Code die Berechtigungsprüfung und anschließend das Tool aus.
115 115
116Dieser Hook lehnt einen Bash-Befehl ab, der Force-Push durchführt, und teilt Claude mit, warum:116Dieser Hook lehnt einen Bash-Befehl ab, der einen Force-Push ausführt, und teilt Claude den Grund mit:
117 117
118```javascript theme={null}118```javascript theme={null}
119// Der Matcher begrenzt den Hook auf Bash-Aufrufe, daher ist e.command der Shell-Befehl119// The matcher limits the hook to Bash calls, so e.command is the shell command
120on('tool.call', { tool: 'Bash' }, async ($, e, next) => {120on('tool.call', { tool: 'Bash' }, async ($, e, next) => {
121 if (/git push .*--force/.test(e.command)) {121 if (/git push .*--force/.test(e.command)) {
122 // Rückgabe ohne Aufruf von next beantwortet das Ereignis, daher wird der Befehl nie ausgeführt122 // Returning without calling next answers the event, so the command never runs
123 return { deny: 'Force pushes are not allowed in this repository. Push to a new branch instead.' }123 return { deny: 'Force pushes are not allowed in this repository. Push to a new branch instead.' }
124 }124 }
125 // Jeder andere Befehl geht zur Berechtigungsprüfung und dann zu Bash125 // Every other command goes on to the permission check and then to Bash
126 return next(e)126 return next(e)
127})127})
128```128```
129 129
130Wenn 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.130Wenn Claude `git push --force` versucht, wird der Befehl nicht ausgeführt und es erscheint keine Berechtigungsabfrage, weil der Hook `next` nie aufruft. Claude liest den `deny`-Text als Ergebnis des Tools, formulieren Sie ihn also als Anweisung, nach der Claude handeln kann. Jeder andere Bash-Befehl wird so ausgeführt, wie er es ohne den Mod würde.
131 131
132Um 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:132Um nach der Ausführung eines Tools zu handeln, verwenden Sie `await next(e)`, erledigen Ihre Arbeit und geben zurück, was `next` Ihnen geliefert hat. Dieser Hook protokolliert jede `.mdx`-Datei, die Claude ändert, mit [`$.ui.log`](/docs/de/plugins/mods/api#show-something-without-starting-a-turn), das dem Transkript eine abgeblendete Zeile hinzufügt, die Claude nicht liest:
133 133
134```javascript theme={null}134```javascript theme={null}
135on('tool.call', { tool: ['Edit', 'Write'] }, async ($, e, next) => {135on('tool.call', { tool: ['Edit', 'Write'] }, async ($, e, next) => {
136 // Warten Sie auf die Berechtigungsprüfung und das Tool und behalten Sie, was sie produziert haben136 // Wait for the permission check and the tool, and keep what they produced
137 const result = await next(e)137 const result = await next(e)
138 // Ein abgelehnter Aufruf kommt als { deny } zurück, und ein fehlgeschlagener hat isError gesetzt138 // A refused call comes back as { deny }, and a failed one has isError set
139 const changed = !result.deny && !result.isError139 const changed = !result.deny && !result.isError
140 if (changed && e.file_path.endsWith('.mdx')) $.ui.log('Claude changed ' + e.file_path)140 if (changed && e.file_path.endsWith('.mdx')) $.ui.log('Claude changed ' + e.file_path)
141 // Geben Sie das Ergebnis so zurück, wie es kam, damit Claude liest, was das Tool zurückgegeben hat141 // Return the result as it came, so Claude reads what the tool returned
142 return result142 return result
143})143})
144```144```
145 145
146Nachdem 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.146Nachdem Claude eine `.mdx`-Datei bearbeitet oder geschrieben hat, nennt eine abgeblendete Zeile im Transkript die Datei. Für andere Dateitypen oder für einen abgelehnten oder fehlgeschlagenen Aufruf wird nichts protokolliert. Claudes Sicht auf den Aufruf ändert sich nicht, weil der Hook das erhaltene Ergebnis zurückgibt.
147 147
148Um 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.148Um einen Aufruf zu ändern, übergeben Sie geänderte Argumente an `next`. Um einen Aufruf erneut zu versuchen, rufen Sie `next(e)` noch einmal auf: Ein Hook, der beim ersten Ergebnis `isError` 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, etwa `{ result: 'Skipped by my-mod' }`, ohne `next` aufzurufen. In diesem Fall erscheint keine Berechtigungsabfrage und das Tool wird nicht ausgeführt, sodass das von Ihnen zurückgegebene Ergebnis alles ist, was Claude über den Vorgang erfährt.
149 149
150Hooks 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.150Hooks in den [verwalteten Einstellungen](/docs/de/server-managed-settings) Ihrer Organisation werden vor dem `tool.call`-Hook jedes Mods ausgeführt, und eine Blockierung durch einen davon ist endgültig.
151 151
152<h4 id="hold-a-tool-call-until-the-user-decides">152<h4 id="hold-a-tool-call-until-the-user-decides">
153 Halten Sie einen Tool-Aufruf an, bis der Benutzer entscheidet153 Einen Tool-Aufruf zurückhalten, bis der Benutzer entscheidet
154</h4>154</h4>
155 155
156Ein 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.156Ein Hook kann einen Tool-Aufruf anhalten und den Benutzer fragen, was geschehen soll, bevor er fortgesetzt wird. Ein `tool.call`-Hook kann `await` verwenden, bevor er `next` aufruft oder zurückkehrt, und der Tool-Aufruf bleibt bis dahin ausstehend. Um dem Benutzer die Frage 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 mit der 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.
157 157
158Das `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:158Das Muster `RISKY` in diesem Beispiel erfasst `rm -r`, `rm -rf`, `git reset --hard` und `git push` mit `--force` und übersieht andere Schreibweisen wie `git push -f`. Dieses Modul fragt nach, bevor es einen Bash-Befehl ausführt, der dem Muster entspricht:
159 159
160```javascript theme={null}160```javascript theme={null}
161const RISKY = /\brm\s+-rf?\b|\bgit\s+reset\s+--hard\b|\bgit\s+push\b.*--force/161const RISKY = /\brm\s+-rf?\b|\bgit\s+reset\s+--hard\b|\bgit\s+push\b.*--force/
162 162
163export function register(on) {163export function register(on) {
164 on('tool.call', { tool: 'Bash' }, async ($, e, next) => {164 on('tool.call', { tool: 'Bash' }, async ($, e, next) => {
165 // Lassen Sie jeden anderen Befehl ohne Frage durch165 // Let every other command through without a question
166 if (!RISKY.test(e.command)) return next(e)166 if (!RISKY.test(e.command)) return next(e)
167 // Beginnen Sie mit der sicheren Antwort, damit eine Frage, die niemand beantwortet, den Befehl ablehnt167 // Start from the safe answer, so a question nobody answers refuses the command
168 let answer = 'Refuse'168 let answer = 'Refuse'
169 try {169 try {
170 // Der Tool-Aufruf wartet hier, bis der Benutzer eine der beiden Bezeichnungen auswählt170 // The tool call waits here until the user picks one of the two labels
171 answer = await $.ui.ask('Run this command? ' + e.command, ['Run it', 'Refuse'])171 answer = await $.ui.ask('Run this command? ' + e.command, ['Run it', 'Refuse'])
172 } catch {172 } catch {
173 // Der Benutzer hat die Frage verworfen oder dies ist ein claude -p-Lauf mit niemandem zum Fragen173 // The user dismissed the question, or this is a claude -p run with nobody to ask
174 }174 }
175 if (answer !== 'Run it') {175 if (answer !== 'Run it') {
176 // Antwort ohne Aufruf von next, daher wird der Befehl nicht ausgeführt176 // Answer without calling next, so the command doesn't run
177 return { deny: 'The user declined this command. Ask before trying a different approach.' }177 return { deny: 'The user declined this command. Ask before trying a different approach.' }
178 }178 }
179 return next(e)179 return next(e)
183 183
184Wenn Claude einen Befehl wie `rm -rf build` versucht, erscheint die Frage mit dem Befehl darin, und der Befehl wartet auf die Antwort:184Wenn Claude einen Befehl wie `rm -rf build` versucht, erscheint die Frage mit dem Befehl darin, und der Befehl wartet auf die Antwort:
185 185
186* **Der Benutzer wählt Run it**: Der Hook ruft `next(e)` auf, und die übliche Berechtigungsprüfung wird danach immer noch ausgeführt186* **Der Benutzer wählt Run it**: Der Hook ruft `next(e)` auf, und die übliche Berechtigungsprüfung wird danach trotzdem ausgeführt
187* **Der Benutzer wählt Refuse**: Der Befehl wird nicht ausgeführt, und Claude liest den `deny`-Text187* **Der Benutzer wählt Refuse**: Der Befehl wird nicht ausgeführt, und Claude liest den `deny`-Text
188* **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.188* **Der Benutzer gibt eine Antwort ein**: `$.ui.ask` wird mit dem eingegebenen Text aufgelöst. Der Hook vergleicht ihn mit `Run it`, sodass jeder andere Text den Befehl ablehnt.
189* **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`189* **Niemand antwortet**: `$.ui.ask` wird abgelehnt, wenn der Benutzer die Frage schließt oder **Chat about this** wählt, sowie in einer `claude -p`-Ausführung, sodass der `catch`-Block die Antwort auf `Refuse` belässt
190 190
191Halten 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.191Lassen Sie das Warten innerhalb eines Aufrufs der Mods-API wie `$.ui.ask` stattfinden, weil diese Zeit nicht auf das [Zeitlimit](/docs/de/plugins/mods/reference#limits) des Hooks angerechnet wird. Zeit, die Sie mit dem Warten auf ein eigenes Promise verbringen, wird hingegen angerechnet. Claude Code überspringt einen Hook, der das Zeitlimit überschreitet, sodass der zurückgehaltene Befehl ausgeführt würde.
192
193<h4 id="approve-or-refuse-a-tool-call-before-the-user-is-asked">
194 Einen Tool-Aufruf genehmigen oder ablehnen, bevor der Benutzer gefragt wird
195</h4>
196
197Um zu entscheiden, ob ein Tool-Aufruf ausgeführt werden darf, behandeln Sie [`tool.check`](/docs/de/plugins/mods/reference#tools), das Event, in dem Claude Code diese Entscheidung trifft. Es wird ausgelöst, nachdem die Berechtigungsregeln und die Einstellungs-Hooks entschieden haben, und `next(e)` wird mit deren Entscheidung aufgelöst: `allow`, `ask` oder `deny`. Ihr Hook gibt diese Entscheidung oder eine andere zurück. `e.input` enthält die Argumente des Tools, etwa `command` für Bash.
198
199Für einen festen Befehl oder Pfad verwenden Sie eine [Berechtigungsregel](/docs/de/permissions#permission-rule-syntax) wie `Bash(npm test)`, die keinen Code erfordert. Behandeln Sie `tool.check`, wenn die Entscheidung davon abhängt, was in diesem Moment zutrifft, etwa vom aktuellen Git-Branch oder von einem Wert, den ein anderer Hook festgehalten hat.
200
201Dieser Hook lehnt `git push` ab, solange der aktuelle Branch `main` ist:
202
203```javascript theme={null}
204on('tool.check', { tool: 'Bash' }, async ($, e, next) => {
205 // What the permission rules and settings hooks decided: 'allow', 'ask', or 'deny'
206 const decided = await next(e)
207 if (!e.input.command.includes('git push')) return decided
208 const branch = await $.process.run(['git', 'branch', '--show-current'])
209 if (branch.stdout.trim() !== 'main') return decided
210 return { decision: 'deny', reason: 'Push from a branch other than main' }
211})
212```
213
214Auf `main` gibt der Hook `deny` zurück, selbst wenn eine Regel `git push` erlaubt. Auf einem anderen Branch und bei anderen Befehlen erhält der Aufruf die Entscheidung, die er ohne den Mod erhalten würde.
215
216Der Hook prüft den Text des Befehls, betrachten Sie ihn also als Erinnerung für Claude. Um Pushes auf `main` für alle zu blockieren, schützen Sie den Branch bei Ihrem Git-Host.
217
218Ein Hook kann `allow`, `ask` oder `deny` zurückgeben und daher auch einen Aufruf genehmigen, den ein `PreToolUse`-Hook außerhalb der verwalteten Einstellungen blockiert hat. Unter [Berechtigungen mit Hooks erweitern](/docs/de/permissions#extend-permissions-with-hooks) ist aufgeführt, welche Entscheidungen gegenüber einem Mod Bestand haben.
192 219
193<h3 id="rewrite-or-add-to-a-prompt">220<h3 id="rewrite-or-add-to-a-prompt">
194 Schreiben Sie eine Eingabeaufforderung um oder fügen Sie sie hinzu221 Einen Prompt umschreiben oder ergänzen
195</h3>222</h3>
196 223
197Ein `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.224Ein `prompt.submit`-Hook sieht jeden Prompt, bevor der Turn beginnt, und kann den Text daher umschreiben oder ergänzen. `e.text` ist das, was eingegeben wurde.
198 225
199| Um dies zu tun | Geben Sie dies zurück |226| Um dies zu tun | Geben Sie dies zurück |
200| :- | :- |227| :- | :- |
201| Schreiben Sie die Eingabeaufforderung um. Die Nachricht im Transkript zeigt den neuen Text. | `next({ ...e, text: newText })` |228| Den Prompt umschreiben. Die Nachricht im Transkript zeigt den neuen Text. | `next({ ...e, text: newText })` |
202| Fügen Sie Text hinzu, den nur Claude liest, nach der Eingabeaufforderung | `next({ ...e, context: [...(e.context ?? []), extraText] })` |229| Text nach dem Prompt hinzufügen, den nur Claude liest | `next({ ...e, context: [...(e.context ?? []), extraText] })` |
203| Verhindern Sie, dass die Eingabeaufforderung gesendet wird | `{ drop: 'the reason' }` |230| Das Senden des Prompts verhindern | `{ drop: 'the reason' }` |
204 231
205Dieser Hook fügt den aktuellen Branch-Namen für Claude hinzu, wenn eine Eingabeaufforderung einen Pull Request erwähnt:232Dieser Hook fügt für Claude den Namen des aktuellen Branches hinzu, sobald ein Prompt einen Pull Request erwähnt:
206 233
207```javascript theme={null}234```javascript theme={null}
208on('prompt.submit', async ($, e, next) => {235on('prompt.submit', async ($, e, next) => {
209 // Geben Sie eine Eingabeaufforderung weiter, die keinen Pull Request erwähnt, wie sie ist236 // Pass on a prompt that doesn't mention a pull request as it is
210 if (!/\bPR\b|pull request/i.test(e.text)) return next(e)237 if (!/\bPR\b|pull request/i.test(e.text)) return next(e)
211 const git = await $.process.run(['git', 'branch', '--show-current'])238 const git = await $.process.run(['git', 'branch', '--show-current'])
212 // Außerhalb eines Git-Repositorys schlägt der Befehl fehl, daher gibt es keinen Branch zum Hinzufügen239 // Outside a git repository the command fails, so there's no branch to add
213 if (git.exitCode !== 0) return next(e)240 if (git.exitCode !== 0) return next(e)
214 // Behalten Sie jeden Kontext, den ein früherer Hook hinzugefügt hat, und fügen Sie eine weitere Zeile für Claude hinzu241 // Keep any context an earlier hook added, and add one more line for Claude
215 return next({ ...e, context: [...(e.context ?? []), 'Current branch: ' + git.stdout.trim()] })242 return next({ ...e, context: [...(e.context ?? []), 'Current branch: ' + git.stdout.trim()] })
216})243})
217```244```
218 245
219Wenn 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.246Wenn Sie einen Prompt wie `open a PR for this change` senden, sieht Ihre Nachricht im Transkript unverändert aus, und Claude liest danach zusätzlich eine Zeile wie `Current branch: feature/auth`. Ein Prompt, der keinen Pull Request erwähnt, wird unverändert weitergeleitet, und `git` wird nicht ausgeführt.
220 247
221[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).248[Weitere Events](/docs/de/plugins/mods/reference#prompts-and-what-claude-reads) decken den Rest dessen ab, was Claude liest: `prompt.section` für jeden Abschnitt des System-Prompts, `prompt.context` für den mit der ersten Nachricht gesendeten Kontext und `skill.prompt` für den Text eines Skills. Text aus diesen Hooks, der sich zwischen Anfragen ändert, [macht den Prompt-Cache ungültig](/docs/de/prompt-caching).
222 249
223<h3 id="follow-a-turn">250<h3 id="follow-a-turn">
224 Folgen Sie einem Turn251 Einen Turn verfolgen
225</h3>252</h3>
226 253
227Ein Turn ist alles, was Claude als Antwort auf eine Eingabeaufforderung tut. Hooken Sie `turn.start`, `turn.step` und `turn.complete`, um einen zu folgen:254Ein Turn umfasst alles, was Claude als Antwort auf einen Prompt tut. Behandeln Sie `turn.start`, `turn.step` und `turn.complete`, um einen Turn zu verfolgen:
228 255
229| Ereignis | Wann es ausgelöst wird | Was ein Hook tun kann |256| Event | Wann es ausgelöst wird | Was ein Hook tun kann |
230| :- | :- | :- |257| :- | :- | :- |
231| `turn.start` | Ein Turn beginnt | Beobachten. `e.turnId` identifiziert den Turn in den anderen beiden Ereignissen. |258| `turn.start` | Ein Turn beginnt | Beobachten. `e.turnId` identifiziert den Turn in den beiden anderen Events. |
232| `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 |259| `turn.step` | Claude Code ist dabei, eine Anfrage an das Modell zu senden. Ein Turn mit Tool-Aufrufen hat mehrere davon. `e.agentId` ist bei der Anfrage eines Subagenten gesetzt. | Die Token-Nutzung jeder Anfrage auslesen, sie mit `next({ ...e, model })` an ein anderes Modell senden oder antworten, ohne das Modell aufzurufen |
233| `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 |260| `turn.complete` | Der Turn wurde beendet, einschließlich eines vom Benutzer unterbrochenen Turns, bei dem `e.isAborted` den Wert `true` hat. `e.answer` ist Claudes endgültiger Text, `e.durationMs` die Dauer und `e.usage` die Token-Summen des Turns. Der Turn eines Subagenten löst es mit gesetztem `e.agentId` aus. | Beobachten oder ein Objekt mit einem `text`-Feld zurückgeben, etwa `{ text: 'Done in 12 seconds' }`, um eine Zeile unter der Antwort anzuzeigen |
234 261
235Schreiben 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:262Schreiben Sie einen `turn.step`-Hook als asynchronen Generator, weil das Event gestreamt wird. `yield* next(e)` leitet die Antwort beim Streamen weiter und ergibt das fertige Ergebnis. Dieser Hook protokolliert, wie viel von jeder Anfrage die Claude API aus dem [Prompt-Cache](/docs/de/prompt-caching) bedient hat:
236 263
237```javascript theme={null}264```javascript theme={null}
238// function* macht den Hook zu einem Generator, der die Antwort Stück für Stück weitergeben kann265// function* makes the hook a generator, which can pass the response on piece by piece
239on('turn.step', async function* ($, e, next) {266on('turn.step', async function* ($, e, next) {
240 // Senden Sie die Anfrage, leiten Sie jedes Stück weiter, während es ankommt, und behalten Sie das fertige Ergebnis267 // Send the request, forward each piece as it arrives, and keep the finished result
241 const result = yield* next(e)268 const result = yield* next(e)
242 // Überspringen Sie ein Ergebnis, das keine Token-Zählungen meldet269 // Skip a result that reports no token counts
243 if (result.usage) {270 if (result.usage) {
244 $.ui.log('cache read ' + result.usage.cache_read_input_tokens + ' · wrote ' + result.usage.cache_creation_input_tokens)271 $.ui.log('cache read ' + result.usage.cache_read_input_tokens + ' · wrote ' + result.usage.cache_creation_input_tokens)
245 }272 }
246 // Geben Sie das Ergebnis unverändert zurück, damit der Turn wie gewohnt fortfährt273 // Return the result unchanged, so the turn continues as usual
247 return result274 return result
248})275})
249```276```
250 277
251Claude'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.278Claudes Antwort wird wie ohne den Mod auf den Bildschirm gestreamt. Nach Abschluss jeder Anfrage gibt eine abgeblendete Zeile im Transkript die Anzahl der aus dem Cache gelesenen und der in ihn geschriebenen Token an. Ein Turn mit Tool-Aufrufen hat mehrere Anfragen und fügt daher mehrere Zeilen hinzu.
252 279
253`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.280`result.usage` enthält die Token-Zahlen, die die Claude API für eine Anfrage meldet, sowie 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, prüfen Sie also `e.agentId`, wenn Sie nur die Hauptkonversation erfassen möchten.
254 281
255<h3 id="hook-the-settings-hook-events">282<h3 id="hook-the-settings-hook-events">
256 Hooken Sie die Settings-Hook-Ereignisse283 Die Events der Einstellungs-Hooks behandeln
257</h3>284</h3>
258 285
259Settings-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`.286Einstellungs-Hooks sind die Befehls-, HTTP-, Prompt- und Agent-Hooks, die Sie in Einstellungsdateien konfigurieren. Jedes [Event eines Einstellungs-Hooks](/docs/de/hooks#hook-events), etwa `Stop`, `SessionEnd` oder `PostToolUse`, ist auch ein Event, das aus `classic.` gefolgt vom Namen des Einstellungs-Hook-Events besteht, etwa `classic.Stop`. `e` ist das JSON, das ein Einstellungs-Hook über stdin erhält, einschließlich `transcript_path`.
260 287
261Dieser Hook verwendet `Stop`, das ausgelöst wird, wenn Claude die Antwort beendet, um zu protokollieren, wo das Transkript der Sitzung gespeichert ist:288Dieser Hook verwendet `Stop`, das ausgelöst wird, wenn Claude mit dem Antworten fertig ist, um zu protokollieren, wo das Transkript der Sitzung gespeichert ist:
262 289
263```javascript theme={null}290```javascript theme={null}
264on('classic.Stop', async ($, e, next) => {291on('classic.Stop', async ($, e, next) => {
265 // e hat die gleichen Felder, die ein Stop-Hook in einer Einstellungsdatei von stdin liest292 // e has the same fields a Stop hook in a settings file reads from stdin
266 $.ui.log('Transcript saved at ' + e.transcript_path)293 $.ui.log('Transcript saved at ' + e.transcript_path)
267 // Geben Sie das Ereignis weiter, damit Stop-Hooks in Ihren Einstellungsdateien immer noch ausgeführt werden294 // Pass the event on, so Stop hooks in your settings files still run
268 return next(e)295 return next(e)
269})296})
270```297```
271 298
272Jedes 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.299Jedes Mal, wenn Claude mit dem Antworten fertig ist, gibt eine abgeblendete Zeile im Transkript den Pfad der Transkriptdatei an. Der Hook gibt `next(e)` zurück, beobachtet das Event also nur und ändert nichts daran, wie der Turn endet.
273 300
274<h2 id="run-alongside-other-mods">301<h2 id="run-alongside-other-mods">
275 Führen Sie neben anderen Mods aus302 Zusammen mit anderen Mods ausführen
276</h2>303</h2>
277 304
278Mehrere 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.305Mehrere Mods können dasselbe Ereignis verarbeiten, und jeder von ihnen kann fehlschlagen. Wenn Ihr Mod Tool-Aufrufe blockiert, prüfen Sie seine Position in der Kette und was passiert, wenn sein Hook fehlschlägt.
279 306
280<h3 id="the-order-mods-run-in">307<h3 id="the-order-mods-run-in">
281 Die Reihenfolge, in der Mods ausgeführt werden308 Die Reihenfolge, in der Mods ausgeführt werden
282</h3>309</h3>
283 310
284Hooks 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.311Hooks für dasselbe Ereignis bilden eine Middleware-Kette. Das `next` jedes Mods ruft den Hook des nachfolgenden Mods auf, und das letzte `next` erreicht das eigene Verhalten von Claude Code. Der erste Mod ist der äußerste: 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 nicht verhindern, dass ein früherer ein Ereignis sieht.
285 312
286Claude Code ordnet die Kette danach, woher jeder Mod kommt:313Claude Code ordnet die Kette danach, woher jeder Mod stammt:
287 314
2881. 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` ist3151. Der integrierte Wächter `sec-default@builtin`, ein in Claude Code integrierter Mod, den `/plugin` als `cc-plugin-sec-default` auflistet, sofern [er geladen wird](/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 anschließend jeder andere Mod, der als Mod Ihrer Organisation gilt und nicht in `appendPlugins` steht
2892. Mods, die Sie installieren3162. Mods, die Sie installieren
2903. Mods, die Ihre Organisation in `appendPlugins` auflistet3173. Mods, die Ihre Organisation in `appendPlugins` auflistet
2914. Andere in Claude Code eingebaute Mods3184. Andere in Claude Code integrierte Mods
292 319
293Unter 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.320Unter den Mods, die Sie installieren, wird ein Mod vor den Mods ausgeführt, die er in seinem Manifest unter `dependencies` auflistet. Innerhalb eines Moduls werden Hooks in der Reihenfolge ausgeführt, in der `register` `on` aufgerufen hat.
294 321
295<h4 id="where-settings-hooks-run-in-the-order">322<h4 id="where-settings-hooks-run-in-the-order">
296 Wo Settings-Hooks in der Reihenfolge ausgeführt werden323 Wo Einstellungs-Hooks in der Reihenfolge ausgeführt werden
297</h4>324</h4>
298 325
299Die `PreToolUse`-Hooks, die in Einstellungsdateien konfiguriert sind, werden auch während eines Tool-Aufrufs an festen Punkten in der Kette von Mods ausgeführt:326Die in Einstellungsdateien konfigurierten `PreToolUse`-Hooks werden ebenfalls während eines Tool-Aufrufs ausgeführt, und zwar an festen Stellen in der Kette der Mods:
300 327
301* **`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.328* **`PreToolUse`-Hooks aus verwalteten Einstellungen**: werden vor dem `tool.call`-Hook des ersten Mods ausgeführt, und eine Blockierung durch einen von ihnen ist endgültig, sodass kein Mod den Aufruf sieht.
302* **`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.329* **`PreToolUse`-Hooks aus allen anderen Einstellungsdateien und aus der `hooks/hooks.json` von Plugins**: werden ausgeführt, nachdem der letzte Mod `next` aufgerufen hat, als Teil des eigenen Verhaltens von Claude Code. Ein Mod, der `tool.call` beantwortet, ohne `next` aufzurufen, verhindert ihre Ausführung, und ein Mod, der `next` aufruft, sieht ihre Entscheidung in dem Ergebnis, das er zurückgibt.
303 330
304[`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.331[`tool.check`](#approve-or-refuse-a-tool-call-before-the-user-is-asked) wird ausgelöst, nachdem diese Hooks und die Berechtigungsregeln entschieden haben, sodass ein Hook darauf einen Aufruf genehmigen kann, den ein Hook aus der zweiten Gruppe blockiert hat.
305 332
306<h3 id="handle-a-hook-that-fails">333<h3 id="handle-a-hook-that-fails">
307 Behandeln Sie einen Hook, der fehlschlägt334 Einen fehlschlagenden Hook behandeln
308</h3>335</h3>
309 336
310Ein 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:337Ein fehlschlagender Hook unterbricht die Sitzung nicht, und Sie können entscheiden, was stattdessen passiert. Wenn ein Hook ohne `.catch`-Handler eine Ausnahme auslöst, eine Zeitüberschreitung hat oder ein Ergebnis mit falscher Struktur zurückgibt, hängt das weitere Vorgehen davon ab, ob er `next` aufgerufen hatte:
311 338
312* **Es ist fehlgeschlagen, bevor `next` aufgerufen wurde**: Claude Code überspringt es, und der nächste Handler wird an seiner Stelle ausgeführt339* **Er ist fehlgeschlagen, bevor er `next` aufgerufen hat**: Claude Code überspringt ihn, und der nächste Handler wird an seiner Stelle ausgeführt
313* **Es ist fehlgeschlagen, nachdem `next` aufgelöst wurde**: Dieses Ergebnis bleibt bestehen, und nichts wird ein zweites Mal ausgeführt340* **Er ist fehlgeschlagen, nachdem `next` aufgelöst wurde**: Dieses Ergebnis bleibt bestehen, und nichts wird ein zweites Mal ausgeführt
314 341
315Eine 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.342Eine Zeile nennt den Mod, das Ereignis und den Grund, zum Beispiel `my-mod: tool.call hook skipped: threw Error: boom`. Wo Sie sie lesen, hängt von der Sitzung ab, wie [Herausfinden, warum ein Mod nichts tut](/docs/de/plugins/mods/troubleshoot#find-out-why-a-mod-does-nothing) auflistet. Ein `ui.render`-Hook, dessen Zeichnung die Validierung nicht besteht, wird anders gemeldet, wie [Einen Baum aus Elementen erstellen](/docs/de/plugins/mods/interface#build-a-tree-from-elements) beschreibt.
316 343
317Um 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:344Damit ein Hook, der Aufrufe blockiert, im Fehlerfall sicher blockiert (Fail-closed), fügen Sie einen `.catch`-Fehlerhandler hinzu, der an seiner Stelle antwortet. Hier ist `guard` Ihre Hook-Funktion:
318 345
319```javascript theme={null}346```javascript theme={null}
320// on gibt eine Registrierung zurück, und .catch fügt einen Handler an diesen einen Hook an347// on returns a registration, and .catch attaches a handler to that one hook
321on('tool.call', { tool: 'Bash' }, guard).catch(async ($, e, next) => {348on('tool.call', { tool: 'Bash' }, guard).catch(async ($, e, next) => {
322 // next.error.kind ist 'throw' oder 'timeout', was sagt, wie guard fehlgeschlagen ist349 // next.error.kind is 'throw' or 'timeout', which says how guard failed
323 return { deny: 'The command guard failed, so this command was not run: ' + next.error.kind }350 return { deny: 'The command guard failed, so this command was not run: ' + next.error.kind }
324})351})
325```352```
326 353
327Wä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.354Solange `guard` funktioniert, wird der Handler nie ausgeführt. Wenn `guard` bei einem Bash-Aufruf eine Ausnahme auslöst oder eine Zeitüberschreitung hat, ruft Claude Code den Handler mit demselben Ereignis auf. Der Handler gibt `{ deny }` zurück, sodass der Befehl nicht ausgeführt wird, 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 ein eigenes, kürzeres [Zeitlimit](/docs/de/plugins/mods/reference#limits).
328 355
329<h2 id="next-steps">356<h2 id="next-steps">
330 Nächste Schritte357 Nächste Schritte
331</h2>358</h2>
332 359
333* [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 aus360* [Die Mods-API verwenden](/docs/de/plugins/mods/api): Befehle und Tools hinzufügen, ein Modell aufrufen und Aufgaben zeitgesteuert ausführen
334* [Zeichnen Sie in der Schnittstelle](/docs/de/plugins/mods/interface): Zeigen Sie, was Ihre Hooks in einem Bereich oder über der Eingabeaufforderung sammeln361* [In der Oberfläche zeichnen](/docs/de/plugins/mods/interface): anzeigen, was Ihre Hooks in einem Bereich oder oberhalb des Prompts sammeln
335* [Testen Sie einen Mod](/docs/de/plugins/mods/test): Lösen Sie eines dieser Ereignisse aus einem Test aus362* [Einen Mod testen](/docs/de/plugins/mods/test): jedes dieser Ereignisse aus einem Test heraus auslösen
336* [Mods-Referenz](/docs/de/plugins/mods/reference): Jedes Ereignis, jede Mods-API-Methode und die Limits363* [Mods-Referenz](/docs/de/plugins/mods/reference): alle Ereignisse, alle Methoden der Mods-API und die Grenzwerte