> ## 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.

# Hooks-Referenz

> Referenz für Claude Code Hook-Ereignisse, Konfigurationsschema, JSON-Ein-/Ausgabeformate, Exit-Codes, asynchrone Hooks, HTTP-Hooks, Prompt-Hooks und MCP-Tool-Hooks.

<Tip>
  Eine Schnellstartanleitung mit Beispielen finden Sie unter [Hooks automatisieren](/docs/de/hooks-guide).
</Tip>

Hooks sind benutzerdefinierte Shell-Befehle, HTTP-Endpunkte, MCP-Tool-Aufrufe, LLM-Prompts oder Subagenten, die automatisch an bestimmten Punkten im Lebenszyklus von Claude Code ausgeführt werden. Claude Code löst die gleichen Hook-Ereignisse überall aus, wo es läuft: Sitzungen im Terminal, IDE-Erweiterungen, die [Desktop-App](/docs/de/desktop-quickstart) und [Cloud-Sitzungen](/docs/de/claude-code-on-the-web). Verwenden Sie diese Referenz, um Ereignisschemas, Konfigurationsoptionen, JSON-Ein-/Ausgabeformate und erweiterte Funktionen wie asynchrone Hooks, HTTP-Hooks und MCP-Tool-Hooks nachzuschlagen.

Ein Plugin kann auch Hooks als JavaScript-Funktionen registrieren, die Claude Code in seinem eigenen Prozess aufruft, die sowohl in der Benutzeroberfläche angezeigt als auch auf Ereignisse reagieren können. Ein Plugin, das dies tut, ist ein [mod](/docs/de/plugins/mods/overview), und diese Funktions-Hooks werden in [Auf Ereignisse reagieren](/docs/de/plugins/mods/events) behandelt, nicht hier. Die Hooks auf dieser Seite funktionieren weiterhin neben Mods.

<h2 id="hook-lifecycle">
  Hook-Lebenszyklus
</h2>

Claude Code führt Hooks an bestimmten Punkten während einer Sitzung aus. Wenn ein Ereignis ausgelöst wird und ein Matcher passt, übergibt Claude Code JSON-Kontext über das Ereignis an Ihren Hook-Handler. Für Command-Hooks kommt die Eingabe über stdin an. Für HTTP-Hooks kommt sie als POST-Request-Body an. Ihr Handler kann dann die Eingabe überprüfen, Maßnahmen ergreifen und optional eine Entscheidung zurückgeben.

Ereignisse fallen in drei Rhythmen:

* pro Sitzung: `SessionStart` und `SessionEnd`
* pro Runde: `UserPromptSubmit`, `Stop` und `StopFailure`
* bei jedem Tool-Aufruf innerhalb der agentengesteuerten Schleife: `PreToolUse` und `PostToolUse`, außer [`EndConversation`](/docs/de/tools-reference#endconversation-tool-behavior)-Aufrufen, die beide überspringen

<div style={{maxWidth: "500px", margin: "0 auto"}}>
  <Frame>
    <img src="https://mintcdn.com/claude-code/x7pO8l4XcvAXCoVc/images/hooks-lifecycle.svg?fit=max&auto=format&n=x7pO8l4XcvAXCoVc&q=85&s=81b9256c1bbe8832553485f5d9e9c746" className="dark:hidden" alt="Hook-Lebenszyklus-Diagramm, das optionales Setup zeigt, das in SessionStart führt, dann eine Pro-Runde-Schleife mit UserPromptSubmit, UserPromptExpansion für Slash-Befehle, die verschachtelte agentengesteuerte Schleife (PreToolUse, PermissionRequest, PostToolUse, PostToolUseFailure, PostToolBatch, SubagentStart/Stop, TaskCreated, TaskCompleted) und Stop oder StopFailure, gefolgt von TeammateIdle, PreCompact, PostCompact und SessionEnd, mit Elicitation und ElicitationResult verschachtelt in MCP-Tool-Ausführung, PermissionDenied als Seitenzweig von PermissionRequest für Auto-Mode-Ablehnungen, WorktreeCreate, WorktreeRemove, Notification, ConfigChange, InstructionsLoaded, CwdChanged, FileChanged und DirectoryAdded als eigenständige asynchrone Ereignisse, PreModelSwitch als eigenständiges sequenzielles Ereignis, das vor einem angeforderten Modellwechsel ausgeführt wird, PostModelSwitch als eigenständiges asynchrones Ereignis, das nach dem Modellwechsel der Sitzung ausgeführt wird, und MessageDisplay als reines Anzeigereignis, das während des Streamings von Assistenten-Nachrichtentexten ausgeführt wird" width="520" height="1336" data-path="images/hooks-lifecycle.svg" />

    <img src="https://mintcdn.com/claude-code/x7pO8l4XcvAXCoVc/images/hooks-lifecycle-dark.svg?fit=max&auto=format&n=x7pO8l4XcvAXCoVc&q=85&s=c9b3d88487335f58cce0b52e2f9e7531" className="hidden dark:block" alt="Hook-Lebenszyklus-Diagramm, das optionales Setup zeigt, das in SessionStart führt, dann eine Pro-Runde-Schleife mit UserPromptSubmit, UserPromptExpansion für Slash-Befehle, die verschachtelte agentengesteuerte Schleife (PreToolUse, PermissionRequest, PostToolUse, PostToolUseFailure, PostToolBatch, SubagentStart/Stop, TaskCreated, TaskCompleted) und Stop oder StopFailure, gefolgt von TeammateIdle, PreCompact, PostCompact und SessionEnd, mit Elicitation und ElicitationResult verschachtelt in MCP-Tool-Ausführung, PermissionDenied als Seitenzweig von PermissionRequest für Auto-Mode-Ablehnungen, WorktreeCreate, WorktreeRemove, Notification, ConfigChange, InstructionsLoaded, CwdChanged, FileChanged und DirectoryAdded als eigenständige asynchrone Ereignisse, PreModelSwitch als eigenständiges sequenzielles Ereignis, das vor einem angeforderten Modellwechsel ausgeführt wird, PostModelSwitch als eigenständiges asynchrones Ereignis, das nach dem Modellwechsel der Sitzung ausgeführt wird, und MessageDisplay als reines Anzeigereignis, das während des Streamings von Assistenten-Nachrichtentexten ausgeführt wird" width="520" height="1336" data-path="images/hooks-lifecycle-dark.svg" />
  </Frame>
</div>

Die folgende Tabelle fasst zusammen, wann jedes Ereignis ausgelöst wird. Der Abschnitt [Hook-Ereignisse](#hook-events) dokumentiert das vollständige Eingabeschema und die Optionen zur Entscheidungskontrolle für jedes Ereignis.

| Ereignis | Wann es ausgelöst wird |
| :- | :- |
| `SessionStart` | Wenn eine Sitzung beginnt oder fortgesetzt wird |
| `Setup` | Wenn Sie Claude Code mit `--init-only` starten oder mit `--init` oder `--maintenance` im `-p`-Modus. Für einmalige Vorbereitung in CI oder Skripten |
| `UserPromptSubmit` | Wenn ein Prompt abgesendet wird, bevor Claude ihn verarbeitet. Wird auch bei [Turns ausgelöst, die Claude Code selbst startet](/docs/de/hooks#userpromptsubmit) |
| `UserPromptExpansion` | Wenn ein von Ihnen eingegebener Befehl in eine Eingabeaufforderung erweitert wird, bevor sie Claude erreicht. Kann die Erweiterung blockieren |
| `PreToolUse` | Bevor ein Werkzeugaufruf ausgeführt wird. Kann ihn blockieren |
| `PermissionRequest` | Wenn ein Werkzeugaufruf eine Genehmigungsentscheidung benötigt |
| `PermissionDenied` | Wenn der automatische Modus einen Werkzeugaufruf ablehnt, einschließlich Ablehnungen ohne Klassifizierer-Urteil. Verwenden Sie JSON `hookSpecificOutput.retry: true`, um dem Modell mitzuteilen, dass es den abgelehnten Werkzeugaufruf möglicherweise erneut versuchen kann. Claude Code ignoriert `retry`, wenn der Klassifizierer kein Urteil gefällt hat |
| `PostToolUse` | Nach erfolgreichem Werkzeugaufruf |
| `PostToolUseFailure` | Nach fehlgeschlagenem Werkzeugaufruf |
| `PostToolBatch` | Nach Auflösung eines vollständigen Satzes paralleler Werkzeugaufrufe, bevor der nächste Modellaufruf erfolgt |
| `Notification` | Wenn Claude Code eine Benachrichtigung sendet |
| `MessageDisplay` | Während der Text der Assistentnachricht angezeigt wird |
| `SubagentStart` | Wenn ein Subagent erzeugt wird |
| `SubagentStop` | Wenn ein Subagent beendet wird |
| `TaskCreated` | Wenn eine Aufgabe über `TaskCreate` erstellt wird |
| `TaskCompleted` | Wenn eine Aufgabe als abgeschlossen markiert wird |
| `Stop` | Wenn Claude die Antwort beendet |
| `StopFailure` | Wenn die Runde aufgrund eines API-Fehlers endet |
| `TeammateIdle` | Wenn ein [Agent-Team](/docs/de/agent-teams)-Teamkollege im Begriff ist, untätig zu werden |
| `InstructionsLoaded` | Wenn eine CLAUDE.md- oder `.claude/rules/*.md`-Datei in den Kontext geladen wird. Wird beim Sitzungsstart und beim verzögerten Laden von Dateien während einer Sitzung ausgelöst |
| `ConfigChange` | Wenn sich eine Konfigurationsdatei während einer Sitzung ändert |
| `CwdChanged` | Wenn sich das Arbeitsverzeichnis ändert, z. B. wenn Claude einen `cd`-Befehl ausführt. Nützlich für reaktive Umgebungsverwaltung mit Tools wie direnv |
| `DirectoryAdded` | Wenn ein Arbeitsverzeichnis während einer Sitzung über `/add-dir` oder die SDK-Steueranforderung `register_repo_root` hinzugefügt wird |
| `FileChanged` | Wenn sich eine überwachte Datei auf der Festplatte ändert. Das Feld `matcher` gibt an, welche Dateinamen überwacht werden sollen |
| `WorktreeCreate` | Wenn ein Worktree über `--worktree`, `isolation: "worktree"` oder für eine Hintergrundsitzung erstellt wird. Ersetzt das Standard-Git-Verhalten |
| `WorktreeRemove` | Wenn ein Worktree beim Sitzungsende, beim Beenden eines Subagenten oder beim Löschen einer Hintergrundsitzung entfernt wird |
| `PreCompact` | Vor Kontextkomprimierung |
| `PostCompact` | Nach Abschluss der Kontextkomprimierung |
| `PreModelSwitch` | Bevor Claude Code einen Modellwechsel anwendet, den Sie oder ein Client angefordert haben. Kann den Wechsel blockieren |
| `PostModelSwitch` | Nach Änderung des Modells der Sitzung, einschließlich Änderungen, die Claude Code selbst vornimmt, z. B. Wiederherstellung des Modells beim Fortsetzen einer Sitzung |
| `Elicitation` | Wenn ein MCP-Server während eines Werkzeugaufrufs Benutzereingaben anfordert |
| `ElicitationResult` | Nachdem ein Benutzer auf eine MCP-Abfrage antwortet, bevor die Antwort an den Server zurückgesendet wird |
| `SessionEnd` | Wenn eine Sitzung beendet wird |

<h3 id="how-a-hook-resolves">
  Wie ein Hook aufgelöst wird
</h3>

Um zu sehen, wie das Ereignis, der Matcher und der Handler zusammenpassen, betrachten Sie diesen `PreToolUse`-Hook, der destruktive Shell-Befehle blockiert.

<Tabs>
  <Tab title="macOS/Linux">
    Der `matcher` grenzt auf Bash-Tool-Aufrufe ein und die `if`-Bedingung grenzt weiter auf Bash-Unterbefehle ein, die mit `rm *` übereinstimmen, daher wird `block-rm.sh` nur ausgeführt, wenn beide Filter passen:

    ```json theme={null}
    {
      "hooks": {
        "PreToolUse": [
          {
            "matcher": "Bash",
            "hooks": [
              {
                "type": "command",
                "if": "Bash(rm *)",
                "command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/block-rm.sh",
                "args": []
              }
            ]
          }
        ]
      }
    }
    ```

    Das Skript liest die JSON-Eingabe von stdin, extrahiert den Befehl und gibt eine `permissionDecision` von `"deny"` zurück, wenn es `rm -rf` enthält. Speichern Sie es unter `.claude/hooks/block-rm.sh` in Ihrem Projekt und machen Sie es mit `chmod +x .claude/hooks/block-rm.sh` ausführbar, damit Claude Code es ausführen kann:

    ```bash theme={null}
    #!/bin/bash
    # .claude/hooks/block-rm.sh
    COMMAND=$(jq -r '.tool_input.command')

    if echo "$COMMAND" | grep -q 'rm -rf'; then
      jq -n '{
        hookSpecificOutput: {
          hookEventName: "PreToolUse",
          permissionDecision: "deny",
          permissionDecisionReason: "Destructive command blocked by hook"
        }
      }'
    else
      exit 0  # no decision; normal permission flow applies
    fi
    ```

    Dieses Skript verwendet wie die anderen Bash-Beispiele auf dieser Seite, die JSON-Eingabe analysieren, `jq`, daher installieren Sie `jq` und stellen Sie sicher, dass es sich in Ihrem `PATH` befindet, bevor Sie sie versuchen.
  </Tab>

  <Tab title="Windows (PowerShell)">
    Der Matcher `Bash|PowerShell` deckt das [PowerShell-Tool](#powershell) sowie Bash ab. Eine einzelne `if`-Regel passt nur zu den Aufrufen eines Tools, daher erhält jedes Tool seinen eigenen Handler: der erste grenzt auf Bash-Unterbefehle ein, die mit `rm *` übereinstimmen, der zweite auf PowerShell-Befehle, die mit `Remove-Item *` übereinstimmen. Beide führen das gleiche Skript über `powershell.exe` aus:

    ```json theme={null}
    {
      "hooks": {
        "PreToolUse": [
          {
            "matcher": "Bash|PowerShell",
            "hooks": [
              {
                "type": "command",
                "if": "Bash(rm *)",
                "command": "powershell.exe",
                "args": [
                  "-NoProfile",
                  "-ExecutionPolicy",
                  "Bypass",
                  "-File",
                  "${CLAUDE_PROJECT_DIR}/.claude/hooks/block-rm.ps1"
                ]
              },
              {
                "type": "command",
                "if": "PowerShell(Remove-Item *)",
                "command": "powershell.exe",
                "args": [
                  "-NoProfile",
                  "-ExecutionPolicy",
                  "Bypass",
                  "-File",
                  "${CLAUDE_PROJECT_DIR}/.claude/hooks/block-rm.ps1"
                ]
              }
            ]
          }
        ]
      }
    }
    ```

    Das Flag `-NoProfile` überspringt das Laden Ihres PowerShell-Profils, damit der Hook schnell startet, und `-ExecutionPolicy Bypass` ermöglicht PowerShell, die lokale Skriptdatei auszuführen.

    Das Skript liest die JSON-Eingabe von stdin, extrahiert den Befehl und gibt eine `permissionDecision` von `"deny"` zurück, wenn es `rm -rf` oder `Remove-Item` gefolgt von `-Recurse` enthält. Speichern Sie es unter `.claude/hooks/block-rm.ps1` in Ihrem Projekt:

    ```powershell theme={null}
    # .claude/hooks/block-rm.ps1
    $callInput = [Console]::In.ReadToEnd() | ConvertFrom-Json
    $command = $callInput.tool_input.command

    if ($command -match 'rm -rf|Remove-Item.*-Recurse') {
      @{
        hookSpecificOutput = @{
          hookEventName = "PreToolUse"
          permissionDecision = "deny"
          permissionDecisionReason = "Destructive command blocked by hook"
        }
      } | ConvertTo-Json
    } else {
      exit 0  # no decision; normal permission flow applies
    }
    ```
  </Tab>
</Tabs>

Angenommen, Claude Code entscheidet sich, `Bash "rm -rf /tmp/build"` gegen die macOS/Linux-Konfiguration auszuführen. Hier ist, was passiert:

<Frame>
  <img src="https://mintcdn.com/claude-code/ikqp3_70mqIahteV/images/hook-resolution.svg?fit=max&auto=format&n=ikqp3_70mqIahteV&q=85&s=be0bf3053550c26de5f54cd64674c197" className="dark:hidden" alt="Diagramm der Hook-Auflösung: PreToolUse wird ausgelöst, der Matcher prüft auf eine Bash-Übereinstimmung, dann prüft die if-Bedingung auf eine Bash(rm *)-Übereinstimmung. Wenn beide passen, wird der Hook-Befehl ausgeführt und gibt permissionDecision deny zurück, daher wird der Tool-Aufruf blockiert und Claude Code wird fortgesetzt. Wenn eine der Prüfungen nicht passt, wird der Hook übersprungen und der Tool-Aufruf darf fortgesetzt werden." width="930" height="270" data-path="images/hook-resolution.svg" />

  <img src="https://mintcdn.com/claude-code/_xqph1dUOslCOwsj/images/hook-resolution-dark.svg?fit=max&auto=format&n=_xqph1dUOslCOwsj&q=85&s=e80af91f8507cee6bd51ac3c2dd92f63" className="hidden dark:block" alt="Diagramm der Hook-Auflösung: PreToolUse wird ausgelöst, der Matcher prüft auf eine Bash-Übereinstimmung, dann prüft die if-Bedingung auf eine Bash(rm *)-Übereinstimmung. Wenn beide passen, wird der Hook-Befehl ausgeführt und gibt permissionDecision deny zurück, daher wird der Tool-Aufruf blockiert und Claude Code wird fortgesetzt. Wenn eine der Prüfungen nicht passt, wird der Hook übersprungen und der Tool-Aufruf darf fortgesetzt werden." width="930" height="270" data-path="images/hook-resolution-dark.svg" />
</Frame>

<Steps>
  <Step title="Ereignis wird ausgelöst">
    Das `PreToolUse`-Ereignis wird ausgelöst. Claude Code sendet die Tool-Eingabe als JSON über stdin an den Hook:

    ```json theme={null}
    { "tool_name": "Bash", "tool_input": { "command": "rm -rf /tmp/build" }, ... }
    ```
  </Step>

  <Step title="Matcher prüft">
    Der Matcher `"Bash"` passt zum Tool-Namen, daher wird diese Hook-Gruppe aktiviert. Wenn Sie den Matcher weglassen oder `"*"` verwenden, wird die Gruppe bei jedem Auftreten des Ereignisses aktiviert.
  </Step>

  <Step title="If-Bedingung prüft">
    Die `if`-Bedingung `"Bash(rm *)"` passt, weil `rm -rf /tmp/build` ein Unterbefehl ist, der mit `rm *` übereinstimmt, daher wird dieser Handler ausgeführt. Wenn der Befehl `npm test` gewesen wäre, würde die `if`-Prüfung fehlschlagen und `block-rm.sh` würde nie ausgeführt, wodurch der Prozess-Spawn-Overhead vermieden wird. Das Feld `if` ist optional; ohne es wird jeder Handler in der passenden Gruppe ausgeführt.
  </Step>

  <Step title="Hook-Handler wird ausgeführt">
    Das Skript überprüft den vollständigen Befehl und findet `rm -rf`, daher gibt es eine Entscheidung auf stdout aus:

    ```json theme={null}
    {
      "hookSpecificOutput": {
        "hookEventName": "PreToolUse",
        "permissionDecision": "deny",
        "permissionDecisionReason": "Destructive command blocked by hook"
      }
    }
    ```

    Wenn der Befehl eine sicherere `rm`-Variante gewesen wäre, wie `rm file.txt`, würde das Skript stattdessen `exit 0` treffen. Exit-Code 0 ohne Ausgabe bedeutet, dass der Hook keine Entscheidung zu melden hat, daher wird der Tool-Aufruf durch den normalen [Berechtigungsfluss](/docs/de/permissions) fortgesetzt. Der Hook kann den Aufruf ablehnen, aber Stille bedeutet nicht, dass er ihn genehmigt.
  </Step>

  <Step title="Claude Code handelt nach dem Ergebnis">
    Claude Code liest die JSON-Entscheidung, blockiert den Tool-Aufruf und zeigt Claude den Grund an.
  </Step>
</Steps>

Der Abschnitt [Konfiguration](#configuration) unten dokumentiert das vollständige Schema, und jeder Abschnitt [Hook-Ereignis](#hook-events) dokumentiert, welche Eingabe Ihr Befehl erhält und welche Ausgabe er zurückgeben kann.

<h2 id="configuration">
  Konfiguration
</h2>

Hooks werden in JSON-Einstellungsdateien definiert. Die Konfiguration hat drei Verschachtelungsebenen:

1. Wählen Sie ein [Hook-Ereignis](#hook-events) aus, auf das reagiert werden soll, wie `PreToolUse` oder `Stop`
2. Fügen Sie eine [Matcher-Gruppe](#matcher-patterns) hinzu, um zu filtern, wann es ausgelöst wird, z. B. „nur für das Bash-Tool“
3. Definieren Sie einen oder mehrere [Hook-Handler](#hook-handler-fields), die ausgeführt werden, wenn eine Übereinstimmung gefunden wird

Siehe [Wie ein Hook aufgelöst wird](#how-a-hook-resolves) oben für eine vollständige Anleitung mit einem kommentierten Beispiel.

<Note>
  Diese Seite verwendet spezifische Begriffe für jede Ebene: **Hook-Ereignis** für den Lebenszykluspunkt, **Matcher-Gruppe** für den Filter und **Hook-Handler** für den Shell-Befehl, HTTP-Endpunkt, MCP-Tool, Prompt oder Agent, der ausgeführt wird. „Hook“ bezieht sich allein auf die allgemeine Funktion.
</Note>

<h3 id="hook-locations">
  Hook-Speicherorte
</h3>

Der Ort, an dem Sie einen Hook definieren, bestimmt seinen Umfang:

| Speicherort | Umfang | Freigegeben |
| :- | :- | :- |
| `~/.claude/settings.json` | Alle Ihre Projekte | Nein, lokal auf Ihrem Computer |
| `.claude/settings.json` | Einzelnes Projekt | Ja, kann im Repository committed werden |
| `.claude/settings.local.json` | Einzelnes Projekt | Nein, gitignored, wenn Claude Code eine Einstellung darin speichert |
| Verwaltete Richtlinieneinstellungen | Organisationsweit | Ja, von Administrator kontrolliert |
| [Plugin](/docs/de/plugins/overview) `hooks/hooks.json` | Wenn Plugin aktiviert ist | Ja, mit dem Plugin gebündelt |
| [Skill](/docs/de/skills) Frontmatter | Der Rest der Sitzung, sobald der Skill aufgerufen wird. Siehe [Hooks in Skills und Agents](#hooks-in-skills-and-agents) | Ja, in der Skill-Datei definiert |
| [Subagent](/docs/de/sub-agents) Frontmatter | Während dieser Subagent ausgeführt wird | Ja, in der Subagent-Datei definiert |

[Cloud-Sitzungen](/docs/de/claude-code-on-the-web) lesen Ihre lokale `~/.claude/settings.json` nicht. In einer [selbstgehosteten Umgebung](/docs/de/self-hosted-environments-configuration#permissions-and-tool-approval) führt Claude Code auch die Hooks aus, die der Operator vom Host `~/.claude/` des Runners seeded hat, und führt die Hooks in der verwalteten Einstellungsdatei des Runner-Images aus, wenn diese Datei unter den [verwalteten Quellen liegt, die Claude Code anwendet](/docs/de/managed-settings#how-claude-code-combines-managed-sources), was standardmäßig bedeutet, dass nur dann, wenn weder servergesteuerte Einstellungen noch eine von MDM bereitgestellte Claude Code-Richtlinie die verwaltete Ebene bereitstellt. Siehe [was von Ihrem Setup übertragen wird](/docs/de/cloud-environments#what-carries-over-from-your-setup) für welche Einstellungsdateien und Plugins und somit welche Hooks eine Cloud-Sitzung erreichen.

Weitere Informationen zur Auflösung von Einstellungsdateien finden Sie unter [Einstellungen](/docs/de/settings).

Hooks aus Einstellungsdateien, verwalteten Richtlinieneinstellungen und Plugins werden auch in [Subagents](/docs/de/sub-agents) ausgeführt. Wenn ein Subagent ein Tool aufruft, werden Tool-Ereignisse wie `PreToolUse` und `PostToolUse` die gleichen konfigurierten Hooks wie im Hauptgespräch ausgelöst, und die Eingabe enthält die [gemeinsamen Eingabefelder](#common-input-fields) `agent_id` und `agent_type`, die den Subagent identifizieren.

Unternehmensadministratoren können [`allowManagedHooksOnly`](/docs/de/settings-reference#allowmanagedhooksonly) in [verwalteten Einstellungen](/docs/de/managed-settings) verwenden, um einzuschränken, welche Hooks ausgeführt werden:

* Ihre Benutzer-, Projekt-, lokalen und Plugin-Hooks werden blockiert. Hooks aus Plugins, die in verwalteten Einstellungen `enabledPlugins` erzwungen aktiviert sind, sind ausgenommen
* Claude Code schränkt auch Ihre [`statusLine`](/docs/de/statusline), [`fileSuggestion`](/docs/de/settings-reference#filesuggestion) und [`subagentStatusLine`](/docs/de/statusline#subagent-status-lines) Einstellungen auf verwaltete Einstellungen ein
* Claude Code deaktiviert auch Plugins mit einer [`command`-Quelle](/docs/de/plugins/marketplace-reference#command-plugin-source), einschließlich Plugins, die in verwalteten Einstellungen `enabledPlugins` erzwungen aktiviert sind, es sei denn, [`disableCommandPluginSources`](/docs/de/settings-reference#disablecommandpluginsources) ist explizit auf `false` gesetzt. `command`-Quellen erfordern Claude Code v2.1.229 oder später
* Claude Code blockiert auch Marketplace-[`headersHelper`-Befehle](/docs/de/plugins/host-marketplace#authenticate-archive-downloads), es sei denn, [`disableCommandPluginSources`](/docs/de/settings-reference#disablecommandpluginsources) ist explizit auf `false` gesetzt, außer für einen Marketplace, den verwaltete Einstellungen selbst deklarieren

Siehe [was unter `allowManagedHooksOnly` ausgeführt wird](/docs/de/settings-reference#what-runs-under-allowmanagedhooksonly).

Hook-Einträge werden über Einstellungsebenen hinweg zusammengeführt, anstatt sich gegenseitig zu ersetzen: Benutzer-, Projekt- und lokale Einstellungen fügen ihre eigenen Hooks hinzu, ohne verwaltete zu entfernen, und die Einstellung [`disableAllHooks`](#disable-or-remove-hooks) kann verwaltete Hooks von außerhalb verwalteter Einstellungen nicht deaktivieren.

Die [HTTP-Hook-Allowlists](/docs/de/settings-reference#hook-and-skill-settings) gelten für Hooks aus jeder Quelle, einschließlich verwalteter Richtlinieneinstellungen:

* `allowedHttpHookUrls`: Wenn auf einer beliebigen Einstellungsebene definiert, führt Claude Code einen HTTP-Hook-Handler nur aus, wenn seine URL mit der zusammengeführten Allowlist übereinstimmt
* `httpHookAllowedEnvVars`: Wenn definiert, interpoliert Claude Code nur die Umgebungsvariablen auf dieser Liste in Hook-Header

<h3 id="matcher-patterns">
  Matcher-Muster
</h3>

Das Feld `matcher` filtert, wann Hooks ausgelöst werden. Wie ein Matcher ausgewertet wird, hängt von den Zeichen ab, die er enthält:

| Matcher-Wert | Ausgewertet als | Beispiel |
| :- | :- | :- |
| `"*"`, `""` oder weggelassen | Alle abgleichen | wird bei jedem Auftreten des Ereignisses ausgelöst |
| Nur Buchstaben, Ziffern, `_`, `-`, Leerzeichen, `,` und `\|` | Exakte Zeichenkette oder Liste exakter Zeichenketten, getrennt durch `\|` oder `,` mit optionalem umgebendem Leerzeichen | `Bash` passt nur auf das Bash-Tool; `Edit\|Write` und `Edit, Write` passen jeweils auf eines der beiden Tools genau; `code-reviewer` passt nur auf diesen Agent-Typ |
| Enthält ein anderes Zeichen | JavaScript-Regulärer Ausdruck, nicht verankert | `^Notebook` passt auf jedes Tool, dessen Name mit `Notebook` beginnt; `mcp__memory__.*` passt auf jedes Tool vom `memory`-Server |

Ein Matcher auf dem Pfad des regulären Ausdrucks wird mit `RegExp.prototype.test` von JavaScript getestet, was bei einer Übereinstimmung an einer beliebigen Stelle im Wert erfolgreich ist. `Edit.*` passt sowohl auf `Edit` als auch auf `NotebookEdit`; umgeben Sie das Muster mit `^` und `$`, wie in `^Edit$`, wenn Sie eine Übereinstimmung mit der gesamten Zeichenkette benötigen.

`FileChanged` und `StopFailure` verwenden einen engeren exakten Übereinstimmungssatz von nur Buchstaben, Ziffern, `_` und `|`. Ein Bindestrich, Leerzeichen oder Komma in einem Matcher für diese beiden Ereignisse hält ihn auf dem Pfad des regulären Ausdrucks, und nur `|` trennt Alternativen. Jedes andere Ereignis mit Matcher-Unterstützung in der folgenden Tabelle akzeptiert `|` oder `,`.

Das Ereignis `FileChanged` folgt diesen Regeln nicht, wenn es seine Beobachtungsliste erstellt. Siehe [FileChanged](#filechanged).

Jeder Ereignistyp passt auf ein anderes Feld:

| Ereignis | Worauf der Matcher filtert | Beispiel-Matcher-Werte |
| :- | :- | :- |
| `PreToolUse`, `PostToolUse`, `PostToolUseFailure`, `PermissionRequest`, `PermissionDenied` | Tool-Name | `Bash`, `Edit\|Write`, `mcp__.*` |
| `SessionStart` | wie die Sitzung gestartet wurde | `startup`, `resume`, `clear`, `compact`, `fork` |
| `Setup` | welches CLI-Flag Setup ausgelöst hat | `init`, `maintenance` |
| `SessionEnd` | warum die Sitzung endete | `clear`, `resume`, `logout`, `prompt_input_exit`, `other` |
| `Notification` | Benachrichtigungstyp | `permission_prompt`, `idle_prompt`, `auth_success`, `elicitation_dialog`, `elicitation_url_dialog`, `elicitation_complete`, `elicitation_response`, `agent_needs_input`, `agent_completed`, `quota_auto_resume_fired`, `quota_auto_resume_stale`, `quota_auto_resume_disabled` |
| `SubagentStart` | Agent-Typ | `general-purpose`, `Explore`, `Plan`, benutzerdefinierte Agent-Namen oder Plugin-bezogene Namen wie `^my-plugin:reviewer$` |
| `PreCompact`, `PostCompact` | was Komprimierung ausgelöst hat | `manual`, `auto` |
| `PreModelSwitch`, `PostModelSwitch` | kanonischer Name des Modells, zu dem die Sitzung wechselt, wie unter [PreModelSwitch](#premodelswitch) beschrieben | `claude-opus-5`, `claude-opus-4-6\|claude-opus-5`, `.*opus.*` |
| `SubagentStop` | Agent-Typ | gleiche Werte wie `SubagentStart` |
| `ConfigChange` | Konfigurationsquelle | `user_settings`, `project_settings`, `local_settings`, `policy_settings`, `skills` |
| `CwdChanged` | keine Matcher-Unterstützung | wird immer bei jedem Auftreten ausgelöst |
| `DirectoryAdded` | wie das Verzeichnis hinzugefügt wurde | `slash_command`, `register_repo_root` |
| `FileChanged` | wörtliche Dateinamen zum Beobachten (siehe [FileChanged](#filechanged)) | `.envrc\|.env` |
| `StopFailure` | Fehlertyp | `rate_limit`, `overloaded`, `authentication_failed`, `oauth_org_not_allowed`, `account_on_hold`, `billing_error`, `invalid_request`, `model_not_found`, `server_error`, `max_output_tokens`, `cloud_credential_error`, `unknown` |
| `InstructionsLoaded` | Ladegrund | `session_start`, `nested_traversal`, `path_glob_match`, `include`, `compact` |
| `UserPromptExpansion` | Befehlsname | Ihre Skill- oder Befehlsnamen |
| `Elicitation` | MCP-Servername | Ihre konfigurierten MCP-Servernamen |
| `ElicitationResult` | MCP-Servername | gleiche Werte wie `Elicitation` |
| `UserPromptSubmit`, `PostToolBatch`, `Stop`, `TeammateIdle`, `TaskCreated`, `TaskCompleted`, `WorktreeCreate`, `WorktreeRemove`, `MessageDisplay` | keine Matcher-Unterstützung | wird immer bei jedem Auftreten ausgelöst |

Das Abgleichen von `StopFailure` auf `cloud_credential_error` erfordert Claude Code v2.1.267 oder später, die erste Version, die Fehler beim Laden von Anmeldedaten unter diesem Wert statt unter `server_error` oder `unknown` meldet.

Für die meisten Ereignisse wertet Claude Code den Matcher gegen ein Feld aus der [JSON-Eingabe](#hook-input-and-output) aus, die es Ihrem Hook auf stdin sendet. Für Tool-Ereignisse ist dieses Feld `tool_name`. Für `PreModelSwitch` und `PostModelSwitch` wertet Claude Code den Matcher gegen den kanonischen Namen aus, den es aus `to_model` ableitet, wie unter [PreModelSwitch](#premodelswitch) beschrieben. Jeder [Hook-Ereignis](#hook-events)-Abschnitt listet den vollständigen Satz von Matcher-Werten und das Eingabeschema für dieses Ereignis auf.

Dieses Beispiel führt ein Linting-Skript nur aus, wenn Claude eine Datei schreibt oder bearbeitet:

```json theme={null}
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "/path/to/lint-check.sh"
          }
        ]
      }
    ]
  }
}
```

Wenn Sie ein `matcher`-Feld zu einem Ereignis ohne Matcher-Unterstützung hinzufügen, wird es stillschweigend ignoriert.

Für Tool-Ereignisse können Sie enger filtern, indem Sie das Feld [`if`](#common-fields) auf einzelnen Hook-Handlern setzen. `if` verwendet [Berechtigungsregelsyntax](/docs/de/permissions), um gegen den Tool-Namen und die Argumente zusammen abzugleichen, sodass `"Bash(git *)"` ausgeführt wird, wenn ein Bash-Eingabe-Subbefehl `git *` passt und `"Edit(*.ts)"` nur für TypeScript-Dateien ausgeführt wird.

<h4 id="match-mcp-tools">
  MCP-Tools abgleichen
</h4>

[MCP](/docs/de/mcp)-Server-Tools erscheinen als reguläre Tools in Tool-Ereignissen (`PreToolUse`, `PostToolUse`, `PostToolUseFailure`, `PermissionRequest`, `PermissionDenied`), sodass Sie sie auf die gleiche Weise abgleichen können wie jeden anderen Tool-Namen.

MCP-Tools folgen dem Benennungsmuster `mcp__<server>__<tool>`, zum Beispiel:

* `mcp__memory__create_entities`: Entitäten-Tool des Memory-Servers erstellen
* `mcp__filesystem__read_file`: Datei-Lese-Tool des Filesystem-Servers
* `mcp__github__search_repositories`: Such-Tool des GitHub-Servers

Um jedes Tool von einem Server abzugleichen, hängen Sie `.*` an das Server-Präfix an. Das `.*` ist erforderlich: ein Matcher wie `mcp__memory` oder `mcp__brave-search` enthält nur exakte Übereinstimmungszeichen, sodass er als exakte Zeichenkette verglichen wird und kein Tool passt.

* `mcp__memory__.*` passt auf alle Tools vom `memory`-Server
* `mcp__brave-search__.*` passt auf alle Tools von einem Server, dessen Name einen Bindestrich enthält
* `mcp__.*__write.*` passt auf jedes Tool, dessen Name mit `write` beginnt, von jedem Server

Tools von einem [Plugin-gebündelten MCP-Server](/docs/de/mcp#plugin-provided-mcp-servers) verwenden ein bereichsbezogenes Server-Segment, das den Plugin-Namen enthält: `mcp__plugin_<plugin-name>_<server-name>__<tool>`. Ein Matcher, der gegen den bloßen Server-Schlüssel geschrieben wird, wird nie für diese Tools ausgelöst. Für ein Plugin namens `my-plugin`, das einen Server unter dem Schlüssel `db` bündelt, erscheint ein `query`-Tool als `mcp__plugin_my-plugin_db__query`, sodass der Matcher für jedes Tool von diesem Server `mcp__plugin_my-plugin_db__.*` ist. Verwenden Sie denselben bereichsbezogenen Tool-Namen im Feld [`if`](#common-fields) eines Handlers. Siehe [Plugin-bereitgestellte MCP-Server](/docs/de/mcp#plugin-provided-mcp-servers) für die Erstellung des bereichsbezogenen Namens.

Dieses Beispiel protokolliert alle Memory-Server-Operationen und validiert Schreibvorgänge von jedem MCP-Server:

```json theme={null}
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "mcp__memory__.*",
        "hooks": [
          {
            "type": "command",
            "command": "echo 'Memory operation initiated' >> ~/mcp-operations.log"
          }
        ]
      },
      {
        "matcher": "mcp__.*__write.*",
        "hooks": [
          {
            "type": "command",
            "command": "/home/user/scripts/validate-mcp-write.py"
          }
        ]
      }
    ]
  }
}
```

<h3 id="hook-handler-fields">
  Hook-Handler-Felder
</h3>

Jedes Objekt im inneren `hooks`-Array ist ein Hook-Handler: der Shell-Befehl, HTTP-Endpunkt, MCP-Tool, LLM-Prompt oder Agent, der ausgeführt wird, wenn der Matcher passt. Es gibt fünf Typen:

* **[Command-Hooks](#command-hook-fields)** (`type: "command"`): Führen einen Shell-Befehl aus. Ihr Skript empfängt die [JSON-Eingabe](#hook-input-and-output) des Ereignisses auf stdin und kommuniziert Ergebnisse über Exit-Codes und stdout zurück.
* **[HTTP-Hooks](#http-hook-fields)** (`type: "http"`): Senden Sie die JSON-Eingabe des Ereignisses als HTTP-POST-Anfrage an eine URL. Der Endpunkt kommuniziert Ergebnisse über den Antwortkörper mit dem gleichen [JSON-Ausgabeformat](#json-output) wie Command-Hooks zurück.
* **[MCP-Tool-Hooks](#mcp-tool-hook-fields)** (`type: "mcp_tool"`): Rufen Sie ein Tool auf einem konfigurierten [MCP-Server](/docs/de/mcp) auf. Die Textausgabe des Tools wird wie Command-Hook-stdout behandelt.
* **[Prompt-Hooks](#prompt-and-agent-hook-fields)** (`type: "prompt"`): Senden Sie einen Prompt an ein Claude-Modell zur Einzelturn-Bewertung. Das Modell gibt seine Entscheidung als JSON zurück. Siehe [Prompt-basierte Hooks](#prompt-based-hooks).
* **[Agent-Hooks](#prompt-and-agent-hook-fields)** (`type: "agent"`): Spawnen Sie einen Subagent, der Tools wie Read, Grep und Glob verwenden kann, um Bedingungen zu überprüfen, bevor er eine Entscheidung zurückgibt. Agent-Hooks sind experimentell und können sich ändern. Siehe [Agent-basierte Hooks](#agent-based-hooks).

Alle passenden Hooks werden parallel ausgeführt. Wenn Sie denselben Handler in mehr als einer Einstellungsdatei definieren, wird er einmal ausgeführt. Eine Kopie desselben Handlers eines Plugins oder Skills bleibt separat.

Handler werden im aktuellen Verzeichnis mit der Umgebung von Claude Code ausgeführt. Wenn das aktuelle Verzeichnis nicht mehr existiert, z. B. ein Worktree oder temporäres Verzeichnis, das eine andere Shell während der Sitzung gelöscht hat, führt Claude Code Command-Hooks aus dem ersten dieser Verzeichnisse aus, das noch existiert: das Verzeichnis, in dem die Sitzung gestartet wurde, das Projekt-Root, Ihr Home-Verzeichnis oder das System-Temp-Verzeichnis. Claude Code zeichnet eine Warnung auf, die das Fallback-Verzeichnis im [Debug-Log](#debug-hooks) benennt.

Die Umgebungsvariable `$CLAUDE_CODE_REMOTE` ist `"true"` in Remote-Web-Umgebungen und nicht gesetzt in der lokalen CLI. Claude Code v2.1.199 und später setzt [`$CLAUDE_CODE_BRIDGE_SESSION_ID`](/docs/de/env-vars) auf die [Remote Control](/docs/de/remote-control)-Sitzungs-ID, während die lokale Sitzung eine aktive Remote Control-Verbindung hat.

<h4 id="common-fields">
  Gemeinsame Felder
</h4>

Diese Felder gelten für alle Hook-Typen:

| Feld | Erforderlich | Beschreibung |
| :- | :- | :- |
| `type` | ja | `"command"`, `"http"`, `"mcp_tool"`, `"prompt"` oder `"agent"` |
| `if` | nein | [Berechtigungsregelsyntax](/docs/de/permissions#permission-rule-syntax) zum Filtern, wann dieser Hook ausgeführt wird, z. B. `"Bash(git *)"` oder `"Edit(*.ts)"`. Der Hook-Befehl wird nur ausgeführt, wenn der Tool-Aufruf dem Muster entspricht. Siehe die [Bash-Matching-Tabelle](#bash-if-matching), wie Bash-Muster gegen Subbefehle, `$()` und Backticks ausgewertet werden. Nur auf Tool-Ereignissen ausgewertet: `PreToolUse`, `PostToolUse`, `PostToolUseFailure`, `PermissionRequest` und `PermissionDenied`. Bei anderen Ereignissen wird ein Hook mit gesetztem `if` nie ausgeführt |
| `timeout` | nein | Sekunden vor dem Abbruch. Claude Code erzwingt es nicht auf einem Command-Hook, den Sie mit [`async: true`](#run-hooks-in-the-background) ausführen. Standardwerte: 600 für `command`, `http` und `mcp_tool`; 30 für `prompt`; 60 für `agent`. Claude Code senkt den Standard für `command`, `http` und `mcp_tool` auf 30 bei [`UserPromptSubmit`](#userpromptsubmit), [`PreModelSwitch`](#premodelswitch) und [`PostModelSwitch`](#postmodelswitch) und auf 10 bei [`MessageDisplay`](#messagedisplay). [`SessionEnd`](#sessionend)-Hooks teilen sich ein Budget von 1,5 Sekunden; wenn Ihre Einstellungen einen längeren Pro-Hook-`timeout` setzen, erhöht Claude Code das Budget, um zu entsprechen, bis zu 60 Sekunden |
| `statusMessage` | nein | Benutzerdefinierte Spinner-Nachricht, die angezeigt wird, während der Hook ausgeführt wird |
| `once` | nein | Wenn `true`, entfernt Claude Code den Hook nach seiner ersten erfolgreichen Ausführung. Eine Ausführung, die fehlschlägt, mit Exit-Code 2 blockiert oder das Timeout überschreitet, hinterlässt den Hook an Ort und Stelle, sodass er beim nächsten passenden Ereignis erneut ausgeführt wird. Wird nur für Hooks beachtet, die in [Skill-Frontmatter](#hooks-in-skills-and-agents) deklariert sind; wird in Einstellungsdateien und Agent-Frontmatter ignoriert |

Das Feld `if` enthält genau eine Berechtigungsregel. Es gibt keine `&&`-, `||`- oder Listsyntax zum Kombinieren von Regeln; um mehrere Bedingungen anzuwenden, definieren Sie einen separaten Hook-Handler für jede.

In einer `if`-Bedingung für ein Datei-Tool passt ein Verzeichnismuster mit einem Segment wie `"Edit(src/**)"` nur auf das `src`-Verzeichnis im Arbeitsverzeichnis und die Dateien darunter. Um ein Verzeichnis namens `src` in beliebiger Tiefe abzugleichen, schreiben Sie `"Edit(**/src/**)"`. Vor v2.1.214 passte `"Edit(src/**)"` auf ein Verzeichnis namens `src` in beliebiger Tiefe unter dem Arbeitsverzeichnis.

<h4 id="bash-if-matching">
  Wie `if`-Muster Bash-Befehle abgleichen
</h4>

Bei Bash-Mustern im [`if`-Feld](#common-fields) hängt es von der Form des Musters und dem Bash-Befehl, den Claude aufruft, ab, ob Ihr Hook-Befehl ausgeführt wird. Führende `VAR=value`-Zuweisungen werden vor dem Abgleich entfernt.

| `if`-Muster | Bash-Befehl | Hook wird ausgeführt? | Warum |
| :- | :- | :- | :- |
| `Bash(git *)` | `FOO=bar git push` | ja | führende Zuweisungen werden entfernt; `git push` passt |
| `Bash(git *)` | `npm test && git push` | ja | jeder Subbefehl wird überprüft; `git push` passt |
| `Bash(rm *)` | `echo $(rm -rf /)` | ja | Befehle in `$()` und Backticks werden überprüft; `rm -rf /` passt |
| `Bash(rm *)` | `echo $(date)` | nein | kein Subbefehl passt auf `rm *` |
| `Bash(git push *)` | `echo $(date)` | ja | Muster, die mehr als den Befehlsnamen angeben, führen den Hook trotzdem bei `$()`, Backticks oder `$VAR` aus |

Wenn Claude Code nicht bestimmen kann, welche Befehle die Bash-Eingabe ausführt, führt es Ihren Hook unabhängig vom Muster aus. Da der `if`-Filter Best-Effort ist, verwenden Sie das [Berechtigungssystem](/docs/de/permissions) statt eines Hooks, um ein hartes Zulassen oder Verweigern durchzusetzen.

<h4 id="command-hook-fields">
  Command-Hook-Felder
</h4>

Zusätzlich zu den [gemeinsamen Feldern](#common-fields) akzeptieren Command-Hooks diese Felder:

| Feld | Erforderlich | Beschreibung |
| :- | :- | :- |
| `command` | ja | Shell-Befehl zum Ausführen. Mit `args` die Ausführungsdatei zum direkten Spawnen. Siehe [Exec-Form und Shell-Form](#exec-form-and-shell-form) |
| `args` | nein | Argumentliste. Wenn vorhanden, wird `command` als Ausführungsdatei aufgelöst und direkt mit `args` als Argumentvektor gespawnt, ohne Shell. Siehe [Exec-Form und Shell-Form](#exec-form-and-shell-form) |
| `async` | nein | Wenn `true`, wird im Hintergrund ohne Blockierung ausgeführt. Siehe [Hooks im Hintergrund ausführen](#run-hooks-in-the-background) |
| `asyncRewake` | nein | Wenn `true`, wird im Hintergrund ausgeführt und weckt Claude bei Exit-Code 2 auf. Die stderr des Hooks oder stdout, wenn stderr leer ist, wird Claude als [Systemerinnerung](/docs/de/glossary#system-reminder) angezeigt, damit es auf einen langfristigen Hintergrund-Fehler reagieren kann |
| `shell` | nein | Shell, die für diesen Hook verwendet werden soll. Akzeptiert `"bash"` oder `"powershell"`. Standardmäßig `"bash"` oder `"powershell"` unter Windows, wenn Git Bash nicht installiert ist. Das Setzen von `"powershell"` führt den Befehl über PowerShell unter Windows aus. Erfordert nicht `CLAUDE_CODE_USE_POWERSHELL_TOOL`, da Hooks PowerShell direkt spawnen. Wird ignoriert, wenn `args` gesetzt ist |

<a id="exec-form-and-shell-form" />

<h5 id="exec-form-and-shell-form">
  Exec-Form und Shell-Form
</h5>

Ein Command-Hook wird als Exec-Form ausgeführt, wenn `args` gesetzt ist, und als Shell-Form, wenn `args` weggelassen ist. Setzen Sie `args`, wenn der Hook auf einen [Pfad-Platzhalter](#reference-scripts-by-path) verweist, da jedes Element als ein Argument ohne Anführungszeichen übergeben wird. Lassen Sie `args` weg, wenn Sie Shell-Funktionen wie Pipes oder `&&` benötigen, oder wenn keine der beiden Bedenken zutrifft.

**Exec-Form** wird ausgeführt, wenn `args` vorhanden ist. Claude Code löst `command` als Ausführungsdatei auf `PATH` auf und spawnt es direkt mit `args` als Argumentvektor. Es gibt keine Shell, sodass jedes `args`-Element genau ein Argument ist, wie geschrieben, und Pfad-Platzhalter wie `${CLAUDE_PLUGIN_ROOT}` werden in `command` und in jedes `args`-Element als einfache Zeichenketten ersetzt. Sonderzeichen wie Apostrophe, `$` und Backticks werden wörtlich durchgeleitet, da es keine Shell gibt, um sie zu interpretieren. Auf keiner Plattform findet Shell-Tokenisierung statt.

**Shell-Form** wird ausgeführt, wenn `args` fehlt. Die `command`-Zeichenkette wird an eine Shell übergeben: `sh -c` auf macOS und Linux, Git Bash unter Windows oder PowerShell, wenn Git Bash nicht installiert ist. Setzen Sie das Feld `shell`, um explizit zu wählen. Die Shell tokenisiert die Zeichenkette, erweitert Variablen und interpretiert Pipes, `&&`, Umleitungen und Globs.

<Note>
  Unter Windows erfordert die Exec-Form, dass `command` sich zu einer echten Ausführungsdatei wie `.exe` auflöst. Die `.cmd`- und `.bat`-Shims, die npm, npx, eslint und andere Tools in `node_modules/.bin` installieren, sind keine Ausführungsdateien und können ohne Shell nicht gespawnt werden. Um sie in Exec-Form auszuführen, rufen Sie das zugrunde liegende Skript direkt mit `node` auf, z. B. `"command": "node", "args": ["${CLAUDE_PLUGIN_ROOT}/node_modules/eslint/bin/eslint.js"]`. Das Muster `node` plus Skriptpfad funktioniert auf jeder Plattform, da `node.exe` eine echte Binärdatei ist. Um einen `.cmd`- oder `.bat`-Shim nach Name auszuführen, verwenden Sie Shell-Form.
</Note>

Dieses Beispiel führt ein Node-Skript aus, das mit einem Plugin gebündelt ist. Exec-Form übergibt den aufgelösten Skriptpfad als ein Argument ohne Anführungszeichen:

```json theme={null}
{
  "type": "command",
  "command": "node",
  "args": ["${CLAUDE_PLUGIN_ROOT}/scripts/format.js", "--fix"]
}
```

Die äquivalente Shell-Form benötigt Anführungszeichen, um Pfade mit Leerzeichen oder Sonderzeichen zu handhaben:

```json theme={null}
{
  "type": "command",
  "command": "node \"${CLAUDE_PLUGIN_ROOT}\"/scripts/format.js --fix"
}
```

Beide Formen unterstützen die gleichen [Pfad-Platzhalter](#reference-scripts-by-path) und exportieren sie beide als Umgebungsvariablen `CLAUDE_PROJECT_DIR`, `CLAUDE_PLUGIN_ROOT` und `CLAUDE_PLUGIN_DATA` auf dem gespawnten Prozess, sodass ein Skript `process.env.CLAUDE_PLUGIN_ROOT` unabhängig davon lesen kann, wie es gestartet wurde.

Plugin-Hooks ersetzen zusätzlich [`${user_config.*}`](/docs/de/plugins/manifest-reference#user-configuration)-Werte, nur in Exec-Form: Der Wert wird in `command` und in jedes `args`-Element als einfache Zeichenkette ersetzt, sodass die Shell ihn nicht erneut analysiert.

Ein Shell-Form-Plugin-Hook, dessen `command` auf `${user_config.*}` verweist, schlägt mit einem [Fehler](/docs/de/errors#plugin-command-references-user-config) fehl, anstatt ausgeführt zu werden. Um einen Optionswert aus einem Shell-Form-Hook zu verwenden, lesen Sie die Umgebungsvariable `$CLAUDE_PLUGIN_OPTION_<KEY>`, z. B. `$CLAUDE_PLUGIN_OPTION_WEBHOOK_URL` für eine `webhook_url`-Option, oder setzen Sie `args`, um den Hook auf Exec-Form umzuschalten. Vor v2.1.207 ersetzten Shell-Form-Plugin-Hook-Befehle auch `${user_config.*}`.

<Note>
  In Exec-Form ist `command` nur der Ausführungsdateiname oder -pfad. Wenn `command` ein bloßer Name ohne Pfad-Trennzeichen ist und Leerzeichen neben `args` enthält, protokolliert Claude Code eine Warnung, da das Spawn fehlschlägt: Es gibt keine Ausführungsdatei namens `node script.js`. Verschieben Sie die zusätzlichen Token in `args`. Absolute Pfade mit Leerzeichen, z. B. `C:\Program Files\nodejs\node.exe`, sind eine einzelne gültige Ausführungsdatei und lösen die Warnung nicht aus.
</Note>

<h4 id="http-hook-fields">
  HTTP-Hook-Felder
</h4>

Zusätzlich zu den [gemeinsamen Feldern](#common-fields) akzeptieren HTTP-Hooks diese Felder:

| Feld | Erforderlich | Beschreibung |
| :- | :- | :- |
| `url` | ja | URL zum Senden der POST-Anfrage an |
| `headers` | nein | Zusätzliche HTTP-Header als Schlüssel-Wert-Paare. Werte unterstützen Umgebungsvariablen-Interpolation mit `$VAR_NAME` oder `${VAR_NAME}`-Syntax. Nur Variablen in `allowedEnvVars` werden aufgelöst |
| `allowedEnvVars` | nein | Liste von Umgebungsvariablennamen, die in Header-Werte interpoliert werden dürfen. Verweise auf nicht aufgelistete Variablen werden durch leere Zeichenketten ersetzt. Erforderlich für jede Umgebungsvariablen-Interpolation |

Claude Code sendet die [JSON-Eingabe](#hook-input-and-output) des Hooks als POST-Anfragekörper mit `Content-Type: application/json`. Der Antwortkörper verwendet das gleiche [JSON-Ausgabeformat](#json-output) wie Command-Hooks.

Die Fehlerbehandlung unterscheidet sich von Command-Hooks; siehe [HTTP-Antwortbehandlung](#http-response-handling).

Dieses Beispiel sendet `PreToolUse`-Ereignisse an einen lokalen Validierungsdienst und authentifiziert sich mit einem Token aus der Umgebungsvariable `MY_TOKEN`:

```json theme={null}
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "http",
            "url": "http://localhost:8080/hooks/pre-tool-use",
            "timeout": 30,
            "headers": {
              "Authorization": "Bearer $MY_TOKEN"
            },
            "allowedEnvVars": ["MY_TOKEN"]
          }
        ]
      }
    ]
  }
}
```

<h4 id="mcp-tool-hook-fields">
  MCP-Tool-Hook-Felder
</h4>

Zusätzlich zu den [gemeinsamen Feldern](#common-fields) akzeptieren MCP-Tool-Hooks diese Felder:

| Feld | Erforderlich | Beschreibung |
| :- | :- | :- |
| `server` | ja | Name eines konfigurierten MCP-Servers. Für einen [Plugin-gebündelten Server](/docs/de/mcp#plugin-provided-mcp-servers) ist dies der bereichsbezogene Name `plugin:<plugin-name>:<server-name>`, z. B. `plugin:my-plugin:db`, nicht der bloße Server-Schlüssel |
| `tool` | ja | Name des Tools, das auf diesem Server aufgerufen werden soll |
| `input` | nein | Argumente, die an das Tool übergeben werden. Zeichenkettenwerte unterstützen `${path}`-Ersetzung aus der [JSON-Eingabe](#hook-input-and-output) des Hooks, z. B. `"${tool_input.file_path}"` |

Dieses Beispiel ruft das Tool `security_scan` auf dem MCP-Server `my_server` nach jedem `Write` oder `Edit` auf und übergibt den Pfad der bearbeiteten Datei:

```json theme={null}
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [
          {
            "type": "mcp_tool",
            "server": "my_server",
            "tool": "security_scan",
            "input": { "file_path": "${tool_input.file_path}" }
          }
        ]
      }
    ]
  }
}
```

<h5 id="how-the-tool’s-result-is-read">
  Wie das Ergebnis des Tools gelesen wird
</h5>

Claude Code liest den Textinhalt des Tools auf die gleiche Weise wie Command-Hook-stdout und folgt der [Parsing-Regel unter Exit-Code 0](#exit-code-0). Wenn das Tool `isError: true` zurückgibt, erzeugt der Hook einen nicht blockierenden Fehler und die Ausführung wird fortgesetzt.

<h5 id="when-the-server-is-still-connecting">
  Wenn der Server noch verbunden wird
</h5>

Bei Ereignissen, bei denen ein Hook blockieren oder das Ergebnis ändern kann, z. B. `PreToolUse` oder `Stop`, wartet Claude Code auf einen verbindenden Server, bevor es das Tool aufruft, für höchstens [`MCP_TIMEOUT`](/docs/de/env-vars) und innerhalb des [`timeout`](#common-fields) des Hooks. Bei Beobachtungsereignissen, z. B. `Notification` oder `SessionEnd`, wartet es nicht.

Ein Server mit dem [`cached`-Status](/docs/de/mcp#server-status-detail) verbindet sich, wenn der Hook sein Tool aufruft. Wenn der Server zu diesem Zeitpunkt nicht verbunden ist, erzeugt der Hook einen nicht blockierenden Fehler und die Ausführung wird fortgesetzt. Der Hook startet nie einen OAuth-Fluss, also [authentifizieren Sie den Server von `/mcp`](/docs/de/mcp#authenticate-with-remote-mcp-servers) zuerst.

<h5 id="events-that-fire-before-mcp-servers-are-available">
  Ereignisse, die ausgelöst werden, bevor MCP-Server verfügbar sind
</h5>

`SessionStart` beim Start, einschließlich mit `--continue` oder `--resume`, und jedes `Setup`-Ereignis werden ausgelöst, bevor die MCP-Server der Sitzung für Hooks verfügbar sind. Claude Code überspringt ihre `mcp_tool`-Hooks ohne Aufruf des Tools, und das [Debug-Log](#debug-hooks) zeichnet `mcp_tool hooks are not available for the 'SessionStart' hook event (no MCP client context)` auf, oder die gleiche Nachricht, die `Setup` benennt. Wenn `SessionStart` später in der Sitzung erneut ausgelöst wird, nach `/clear` oder einer Komprimierung, werden seine `mcp_tool`-Hooks ausgeführt. Für alles, das die Sitzung beim Start benötigt, verwenden Sie stattdessen einen `type: "command"`-Hook auf `SessionStart`.

<h4 id="prompt-and-agent-hook-fields">
  Prompt- und Agent-Hook-Felder
</h4>

Zusätzlich zu den [gemeinsamen Feldern](#common-fields) akzeptieren Prompt- und Agent-Hooks diese Felder:

| Feld | Erforderlich | Beschreibung |
| :- | :- | :- |
| `prompt` | ja | Prompt-Text zum Senden an das Modell. Verwenden Sie `$ARGUMENTS` als Platzhalter für die Hook-Eingabe-JSON. Mit einem Backslash escapen, um wörtlichen Text einzuschließen: `\$1.00` wird als `$1.00` gerendert |
| `model` | nein | Modell, das für die Bewertung verwendet werden soll. Standardmäßig das Modell, das Claude Code für [Hintergrundfunktionalität](/docs/de/costs#background-token-usage) verwendet |

<h3 id="reference-scripts-by-path">
  Skripte nach Pfad referenzieren
</h3>

Verwenden Sie diese Platzhalter, um Hook-Skripte relativ zum Projekt- oder Plugin-Root zu referenzieren, unabhängig vom Arbeitsverzeichnis, wenn der Hook ausgeführt wird:

* `${CLAUDE_PROJECT_DIR}`: das Projekt-Root, wo die Sitzung gestartet wurde. Claude Code setzt diese Variable auch in der Umgebung von [stdio MCP-Servern](/docs/de/mcp#option-3-add-a-local-stdio-server) und Plugin-LSP-Servern.
* `${CLAUDE_PLUGIN_ROOT}`: das Plugin-Installationsverzeichnis für Skripte, die mit einem [Plugin](/docs/de/plugins/overview) gebündelt sind. Siehe [Plugin-Umgebungsvariablen](/docs/de/plugins/manifest-reference#environment-variables) für das Verhalten des Pfads über Updates hinweg.
* `${CLAUDE_PLUGIN_DATA}`: das [persistente Datenverzeichnis](/docs/de/plugins/components#path-variables-and-persistent-data) des Plugins für Abhängigkeiten und Status, die Plugin-Updates überstehen sollten.

<Note>
  **Worktrees sind anders.** Wenn Claude während der Sitzung einen [Worktree](/docs/de/worktrees) betritt, behält Claude Code `${CLAUDE_PROJECT_DIR}` bei, wo es war, und übergibt den Worktree-Pfad Ihren Hooks auf andere Weise:

  * **`${CLAUDE_PROJECT_DIR}` bleibt stehen**: Es zeigt immer noch auf das Projekt-Root, wo die Sitzung gestartet wurde, sodass ein Befehl wie `${CLAUDE_PROJECT_DIR}/.claude/hooks/check-style.sh` das Skript immer noch im Haupt-Checkout ausführt.
  * **`cwd` folgt Claude**: Das Feld `cwd` in der Hook-[Eingabe-JSON](#common-input-fields) ist das Worktree-Root, nachdem Claude einen Worktree betritt, und das neue Verzeichnis, nachdem Claude `cd` ausführt. Lesen Sie es, wenn ein Hook wissen muss, welches Verzeichnis Claude bearbeitet.
</Note>

Bevorzugen Sie [Exec-Form](#exec-form-and-shell-form) für jeden Hook, der auf einen Pfad-Platzhalter verweist. In Shell-Form umgeben Sie jeden Platzhalter mit doppelten Anführungszeichen.

<Tabs>
  <Tab title="Projekt-Skripte">
    Dieses Beispiel verwendet `${CLAUDE_PROJECT_DIR}`, um einen Style-Checker aus dem Verzeichnis `.claude/hooks/` des Projekts nach jedem `Write`- oder `Edit`-Tool-Aufruf auszuführen:

    ```json theme={null}
    {
      "hooks": {
        "PostToolUse": [
          {
            "matcher": "Write|Edit",
            "hooks": [
              {
                "type": "command",
                "command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/check-style.sh",
                "args": []
              }
            ]
          }
        ]
      }
    }
    ```
  </Tab>

  <Tab title="Plugin-Skripte">
    Definieren Sie Plugin-Hooks in `hooks/hooks.json` mit einem optionalen Top-Level-Feld `description`. Wenn ein Plugin aktiviert ist, werden seine Hooks mit Ihren Benutzer- und Projekt-Hooks zusammengeführt.

    Dieses Beispiel führt ein Formatierungsskript aus, das mit dem Plugin gebündelt ist:

    ```json theme={null}
    {
      "description": "Automatic code formatting",
      "hooks": {
        "PostToolUse": [
          {
            "matcher": "Write|Edit",
            "hooks": [
              {
                "type": "command",
                "command": "${CLAUDE_PLUGIN_ROOT}/scripts/format.sh",
                "args": [],
                "timeout": 30
              }
            ]
          }
        ]
      }
    }
    ```

    Siehe die [Plugin-Komponenten-Referenz](/docs/de/plugins/components#hooks) für Details zum Erstellen von Plugin-Hooks.
  </Tab>
</Tabs>

<h3 id="hooks-in-skills-and-agents">
  Hooks in Skills und Agents
</h3>

Zusätzlich zu Einstellungsdateien und Plugins können Hooks direkt in [Skills](/docs/de/skills) und [Subagents](/docs/de/sub-agents) mit Frontmatter im gleichen Konfigurationsformat wie einstellungsbasierte Hooks definiert werden. Wie lange Claude Code sie registriert hält, hängt von der Komponente ab:

* **Subagent-Hooks**: Claude Code führt sie nur aus, während dieser Subagent ausgeführt wird, und entfernt sie, wenn er fertig ist. Claude Code konvertiert einen `Stop`-Hook hier zu `SubagentStop`, dem Ereignis, das ausgelöst wird, wenn ein Subagent abgeschlossen ist.
* **Skill-Hooks**: Claude Code registriert sie, wenn Sie oder Claude den Skill aufrufen, und führt sie für den Rest der Sitzung aus, auf Turns nach dem eigenen Turn des Skills auch. Um Claude Code stattdessen einen Hook nach seiner ersten erfolgreichen Ausführung zu entfernen, setzen Sie [`once: true`](#common-fields) darauf.

Dieser Skill definiert einen `PreToolUse`-Hook, der ein Sicherheitsvalidierungsskript vor jedem `Bash`-Befehl ausführt:

```yaml theme={null}
---
name: secure-operations
description: Perform operations with security checks
hooks:
  PreToolUse:
    - matcher: "Bash"
      hooks:
        - type: command
          command: "./scripts/security-check.sh"
---
```

Subagents verwenden das gleiche Format in ihrem YAML-Frontmatter.

Frontmatter-Hooks in einem Projekt-Skill folgen der gleichen [Workspace-Trust-Regel wie Hooks in Einstellungsdateien](#workspace-trust). Claude Code registriert sie, wenn Sie oder Claude den Skill aufrufen, auch in einem `-p`-Run in einem Ordner, dem Sie nicht vertraut haben.

Frontmatter-Hooks in einem Projekt-Subagent werden nur ausgeführt, nachdem Sie den [Workspace-Trust-Dialog](/docs/de/permissions#project-allow-rules-and-workspace-trust) für den Ordner akzeptieren, aus dem die Agent-Datei stammt. Eine `-p`-Sitzung zählt nicht als Akzeptanz. [Was vor dem Vertrauen in einen Ordner ausgeführt wird](/docs/de/permissions#what-runs-before-you-trust-a-folder) vergleicht dies mit der Einstellungsdatei-Regel, und die Subagents-Seite listet auf, [welche Bereiche ausgenommen sind](/docs/de/sub-agents#hooks-in-subagent-frontmatter). Vor v2.1.218 konnten diese Hooks aus Ordnern ausgeführt werden, denen Sie nicht vertraut haben.

<h3 id="the-/hooks-menu">
  Das `/hooks`-Menü
</h3>

Geben Sie `/hooks` in Claude Code ein, um eine nur lesende Ansicht Ihrer konfigurierten Hooks zu öffnen. Die Liste kennzeichnet jeden Hook mit seiner Herkunft, z. B. Benutzereinstellungen, Projekteinstellungen, lokale Einstellungen, ein Plugin oder die aktuelle Sitzung.

Wählen Sie einen Hook aus, um den vollständigen Text dessen zu sehen, was er ausführt, und wo er definiert ist, z. B. den Pfad seiner Einstellungsdatei oder den Namen seines Plugins.

Um alle Hook-Ereignisse zu durchsuchen, einschließlich solcher ohne konfigurierte Hooks, wählen Sie `All events` am Ende der Liste aus.

<h3 id="disable-or-remove-hooks">
  Hooks deaktivieren oder entfernen
</h3>

Um einen in einer Einstellungsdatei definierten Hook zu entfernen, löschen Sie seinen Eintrag aus dieser Datei.

Um alle Hooks vorübergehend zu deaktivieren, ohne sie zu entfernen, setzen Sie `"disableAllHooks": true` in Ihrer Einstellungsdatei. Claude Code liest den Wert, der nach [Einstellungspriorität](/docs/de/settings#settings-precedence) bleibt, sodass ein `"disableAllHooks": false` in der `.claude/settings.json` eines Projekts ein `true` in Ihren Benutzereinstellungen überschreibt. Um Hooks für einen Run auszuschalten, unabhängig davon, was die Einstellungen des Projekts sagen, übergeben Sie `--settings '{"disableAllHooks": true}'`, was Vorrang vor Projekt- und lokalen Einstellungen hat. Es gibt keine Möglichkeit, einen einzelnen Hook zu deaktivieren, während er in der Konfiguration bleibt.

Die Einstellung `disableAllHooks` respektiert die Hierarchie der verwalteten Einstellungen. Wenn ein Administrator Hooks durch verwaltete Richtlinieneinstellungen konfiguriert hat, kann `disableAllHooks`, das in Benutzer-, Projekt- oder lokalen Einstellungen gesetzt ist, diese verwalteten Hooks nicht deaktivieren. Nur `disableAllHooks`, das auf der Ebene der verwalteten Einstellungen gesetzt ist, kann verwaltete Hooks deaktivieren. Für die vollständige Reichweite jeder Ebene siehe [`disableAllHooks`](/docs/de/settings-reference#disableallhooks).

Direkte Änderungen an Hooks in Einstellungsdateien werden normalerweise automatisch vom Datei-Watcher aufgegriffen.

<h2 id="hook-input-and-output">
  Hook-Eingabe und -Ausgabe
</h2>

Command Hooks empfangen JSON-Daten über stdin und teilen Ergebnisse über Exit-Codes, stdout und stderr mit. HTTP Hooks empfangen das gleiche JSON wie der POST-Request-Body und teilen Ergebnisse über den HTTP-Response-Body mit. Dieser Abschnitt behandelt Felder und Verhalten, die für alle Events gemeinsam sind. Jeder Event-Abschnitt unter [Hook Events](#hook-events) enthält sein spezifisches Input-Schema und Optionen zur Entscheidungskontrolle.

Auf macOS und Linux werden Command Hooks in ihrer eigenen Session ohne steuerndes Terminal ausgeführt. Der Hook-Prozess und alle untergeordneten Prozesse können `/dev/tty` nicht öffnen oder Escape-Sequenzen direkt an die Claude Code-Schnittstelle senden. Windows hat kein `/dev/tty`.

Um eine Nachricht für den Benutzer auf jeder Plattform anzuzeigen, geben Sie [`systemMessage`](#json-output) in der JSON-Ausgabe zurück. Einige Events verwerfen sie oder liefern sie an anderer Stelle, und jeder [Event-Abschnitt](#hook-events) gibt an, wo. Um eine Desktop-Benachrichtigung auszulösen, einen Fenstertitel zu setzen oder die Glocke zu läuten, geben Sie stattdessen [`terminalSequence`](#emit-terminal-notifications) zurück.

<h3 id="common-input-fields">
  Allgemeine Eingabefelder
</h3>

Hook Events empfangen diese Felder als JSON, zusätzlich zu Event-spezifischen Feldern, die in jedem [Hook-Event](#hook-events)-Abschnitt dokumentiert sind. Für Command Hooks kommt dieses JSON über stdin an. Für HTTP Hooks kommt es als POST-Request-Body an.

| Feld | Beschreibung |
| :- | :- |
| `session_id` | Aktuelle Session-Kennung |
| `prompt_id` | UUID, die den aktuell verarbeiteten Benutzer-Prompt identifiziert. Stimmt mit dem [`prompt.id`-Attribut auf OpenTelemetry-Events](/docs/de/monitoring-usage#event-correlation-attributes) überein, sodass Sie Hook-Ausgabe mit Telemetrie für einen einzelnen Prompt korrelieren können. Nicht vorhanden bis zur ersten Benutzereingabe |
| `transcript_path` | Pfad zur Konversations-JSON. Die Transkriptdatei wird asynchron geschrieben und kann der In-Memory-Konversation hinterherhinken, daher kann sie möglicherweise noch nicht die neuesten Nachrichten des aktuellen Turns enthalten, wenn ein Hook ausgelöst wird. Hooks, die den endgültigen Assistant-Text des aktuellen Turns benötigen, sollten `last_assistant_message` auf [Stop](#stop) und [SubagentStop](#subagentstop) verwenden, anstatt das Transkript zu lesen |
| `cwd` | Aktuelles Arbeitsverzeichnis, wenn der Hook aufgerufen wird |
| `scratchpad_dir` | Pfad zum [Scratchpad-Verzeichnis der Session](/docs/de/claude-directory#session-scratchpad-directory), in dem Claude temporäre Arbeitsdateien speichert. Nicht vorhanden, wenn die Session kein Scratchpad hat oder das Temp-Verzeichnis nicht verfügbar ist. Erfordert Claude Code v2.1.257 oder später |
| `permission_mode` | Aktueller [Berechtigungsmodus](/docs/de/permissions#permission-modes): `"default"`, `"plan"`, `"acceptEdits"`, `"auto"`, `"dontAsk"` oder `"bypassPermissions"`. Der als **Manuell** bezeichnete Modus kommt als `"default"` an, nie als `"manual"`, sodass Skripte, die `"default"` abgleichen, weiterhin funktionieren. Nicht alle Events erhalten dieses Feld. Überprüfen Sie das JSON-Beispiel in jedem [Hook-Event](#hook-events)-Abschnitt |
| `effort` | Objekt mit einem `level`-Feld, das die [Effort-Stufe](/docs/de/model-config#adjust-effort-level) enthält, die wirksam ist, wenn der Hook ausgeführt wird: `"low"`, `"medium"`, `"high"`, `"xhigh"` oder `"max"`. Wenn Sie eine Stufe festlegen, die das aktive Modell nicht unterstützt, meldet `level` die Stufe, die Claude Code stattdessen ausgeführt hat; [Effort-Stufe anpassen](/docs/de/model-config#adjust-effort-level) sagt, wie es diese Stufe auswählt. Das Objekt stimmt mit dem [Status-Feld](/docs/de/statusline#available-data) `effort`-Feld überein. Vorhanden für Events, die innerhalb eines Tool-Use-Kontexts ausgelöst werden, wie `PreToolUse`, `PostToolUse`, `Stop` und `SubagentStop`, wenn das aktuelle Modell den Effort-Parameter unterstützt. Die Stufe ist auch für Hook-Befehle und das Bash-Tool als die `$CLAUDE_EFFORT`-Umgebungsvariable verfügbar. |
| `hook_event_name` | Name des ausgelösten Events |

Bei Ausführung mit `--agent` oder innerhalb eines Subagenten sind zwei zusätzliche Felder enthalten:

| Feld | Beschreibung |
| :- | :- |
| `agent_id` | Eindeutige Kennung für den Subagenten. Nur vorhanden, wenn der Hook innerhalb eines Subagenten-Aufrufs ausgelöst wird. Verwenden Sie dies, um Subagenten-Hook-Aufrufe von Main-Thread-Aufrufen zu unterscheiden. |
| `agent_type` | Agent-Name (z. B. `"Explore"` oder `"security-reviewer"`). Vorhanden, wenn die Session `--agent` verwendet oder der Hook innerhalb eines Subagenten ausgelöst wird. Für Subagenten hat der Typ des Subagenten Vorrang vor dem `--agent`-Wert der Session. Siehe [SubagentStart](#subagentstart) für die Werte, die benutzerdefinierte und Plugin-Subagenten melden, und wie man einen Matcher gegen einen Plugin-Scoped-Namen schreibt. |

Nur [`SessionStart`](#sessionstart)-Hooks können ein `model`-Feld empfangen, und Claude Code fügt es nicht immer ein. [`PreModelSwitch`](#premodelswitch)- und [`PostModelSwitch`](#postmodelswitch)-Hooks empfangen stattdessen `from_model` und `to_model`, verwenden Sie also einen PostModelSwitch-Hook, um das Modell zu verfolgen, während es sich während einer Session ändert.

Es gibt keine `$CLAUDE_MODEL`-Umgebungsvariable. Der Hook kann `$ANTHROPIC_MODEL` lesen, wenn Sie es in Ihrer Shell festlegen, aber dieser Wert ändert sich nicht, wenn Sie während einer Session mit `/model` Modelle wechseln.

Ein Hook-Prozess erbt die übergeordnete Umgebung, mit Ausnahme der `OTEL_*`-Exporter-Variablen, die Claude Code [aus jedem Subprocess entfernt, den es spawnt](/docs/de/monitoring-usage#administrator-configuration), und, wenn [`CLAUDE_CODE_SUBPROCESS_ENV_SCRUB`](/docs/de/env-vars#variables) auf `1` gesetzt ist, die Variablen, die es entfernt. In einer Sitzung, die [die HIPAA-Konfiguration erhält](/docs/de/hipaa-setup#check-how-developers-sign-in-and-connect), [entfernt Claude Code außerdem Anthropic-Anmeldedaten](/docs/de/hipaa-setup#anthropic-credentials-in-commands-hooks-and-mcp-servers) aus der Umgebung des Hooks.

Beispielsweise empfängt ein `PreToolUse`-Hook für einen Bash-Befehl dies auf stdin:

```json theme={null}
{
  "session_id": "abc123",
  "prompt_id": "550e8400-e29b-41d4-a716-446655440000",
  "transcript_path": "/home/user/.claude/projects/.../transcript.jsonl",
  "cwd": "/home/user/my-project",
  "scratchpad_dir": "/tmp/claude-1000/-home-user-my-project/abc123/scratchpad",
  "permission_mode": "default",
  "hook_event_name": "PreToolUse",
  "tool_name": "Bash",
  "tool_input": {
    "command": "npm test",
    "description": "Run test suite",
    "timeout": 120000,
    "run_in_background": false
  },
  "tool_use_id": "toolu_01ABC123..."
}
```

Die Felder `tool_name`, `tool_input` und `tool_use_id` sind Event-spezifisch. Jeder [Hook-Event](#hook-events)-Abschnitt dokumentiert die zusätzlichen Felder für diesen Event.

<h3 id="exit-code-output">
  Exit-Code-Ausgabe
</h3>

Der Exit-Code aus Ihrem Hook-Befehl teilt Claude Code mit, ob die Aktion fortgesetzt, blockiert oder ignoriert werden soll. Der Exit-Code wirkt nicht allein. Claude Code liest [JSON-Ausgabefelder](#json-output) von stdout bei jedem Exit-Code, nicht nur 0, und für Events, die das Standard-Entscheidungsmodell verwenden, wirkt ein gepartes Objekt, das die Schema-Validierung besteht, neben dem Code. Exit 2's Block ist das einzige Ergebnis, das JSON nicht überschreiben kann.

Zwei Tabellen besitzen die Event-spezifischen Ausnahmen: [Exit-Code-2-Verhalten pro Event](#exit-code-2-behavior-per-event) sagt, was Exit-Codes für jeden Event tun, und [Entscheidungskontrolle](#decision-control) sagt, welche Entscheidungsfelder jeder Event berücksichtigt. Universelle Felder wie `systemMessage` funktionieren über die meisten Events hinweg und sind in der [JSON-Ausgabe](#json-output)-Tabelle aufgelistet.

<h4 id="exit-code-0">
  Exit-Code 0
</h4>

Exit 0 bedeutet Erfolg und ist der beabsichtigte Exit-Code, wenn Sie JSON für strukturierte Kontrolle drucken.

Für die meisten Events schreibt Claude Code stdout in das Debug-Protokoll und zeigt es nicht im Transkript an. Die Ausnahmen sind `UserPromptSubmit`, `UserPromptExpansion`, `SessionStart` und `PostModelSwitch`, wo Claude Code einfachen Text-stdout als Kontext hinzufügt, den Claude sehen und bearbeiten kann.

Ob Claude Code Ihren stdout als [JSON-Ausgabe](#json-output) oder als einfachen Text liest, hängt davon ab, wie er beginnt und endet, wobei umgebender Whitespace ignoriert wird:

* **Beginnt mit `{` und endet mit `}`**: Claude Code parst es als JSON. Wenn die Ausgabe zwei oder mehr Zeilen sind, die jeweils selbst als JSON geparst werden, und keine Zeile ein [JSON-Ausgabe](#json-output)-Objekt ist, das ein Feld setzt, behandelt Claude Code die gesamte Ausgabe als einfachen Text. Wenn eine dieser Zeilen ein Feld setzt, ist die gesamte Ausgabe ein Parse-Fehler, der unten beschrieben wird.
* **Beginnt mit `{` aber endet nicht mit `}`**: Claude Code behandelt es als einfachen Text.
* **Beginnt mit etwas anderem**: Claude Code behandelt es als einfachen Text, ein JSON-Array oder einen zitierten JSON-String enthalten.

Für Events, die das Standard-Entscheidungsmodell verwenden, ist Exit 0 mit einem geparsten Objekt, das die Schema-Validierung nicht besteht, ein nicht blockierender Fehler: die Aktion wird fortgesetzt, und das Transkript zeigt einen `<Hook-Name> hook error`-Hinweis mit der Validierungsmeldung. Das gleiche passiert bei jedem Exit-Code außer 2, während [Exit 2 immer noch blockiert](#exit-code-2).

Für Events, die das Standard-Entscheidungsmodell verwenden, wenn Claude Code versucht, Ihren stdout als JSON zu parsen und kann nicht, meldet es einen nicht blockierenden Fehler bei jedem Exit-Code außer 2. Das Transkript zeigt einen `<Hook-Name> hook error`-Hinweis mit der Parse-Meldung. Bei den Events, die einfachen Text-stdout als Kontext hinzufügen, fügt Claude Code den Text nicht hinzu. Vor v2.1.248 behandelte Claude Code diesen stdout als einfachen Text.

Stderr von einem Hook, der mit 0 beendet wird, geht nur in das Debug-Protokoll, nie in das Transkript, und Claude sieht es nie. Um es selbst zu lesen, aktivieren Sie [Debug-Protokollierung](#debug-hooks). Um eine Warnung an Claude von einem `PostToolUse`- oder `PostToolUseFailure`-Hook zu übermitteln, beenden Sie stattdessen mit 2, damit [Claude den stderr sieht](#exit-code-2-behavior-per-event), obwohl das Tool bereits ausgeführt wurde.

<h4 id="exit-code-2">
  Exit-Code 2
</h4>

Exit 2 bedeutet einen blockierenden Fehler. Bei [Events, die blockieren können](#exit-code-2-behavior-per-event), blockiert Exit 2, unabhängig davon, ob Sie JSON drucken oder nicht: selbst ein JSON `permissionDecision` von `"allow"` kann es nicht überschreiben. Claude Code liest immer noch alle gültigen [JSON-Ausgabe](#json-output) auf stdout. Bei `Elicitation` und `ElicitationResult` wird die `hookSpecificOutput` eines Exit-2-Hooks ignoriert.

Die Blockierungsmeldung ist der Grund aus der Blockierungsentscheidung Ihres JSON, wenn es eine gibt, und Ihr stderr-Text andernfalls. Was der Block tut, variiert je nach Event: `PreToolUse` blockiert den Tool-Aufruf, `UserPromptSubmit` lehnt den Prompt ab, und so weiter. [Exit-Code-2-Verhalten pro Event](#exit-code-2-behavior-per-event) listet die Auswirkung für jeden Event auf, und jeder Event-Abschnitt sagt, wohin die Meldung geht.

Ein Hook, der mit 2 beendet wird, während JSON gedruckt wird, das die [JSON-Ausgabe](#json-output)-Schema-Validierung nicht besteht, blockiert immer noch: Claude Code verwendet stderr als Blockierungsgrund und zeichnet den Validierungsfehler im Debug-Protokoll auf. Vor v2.1.214 behandelte Claude Code diese Kombination als nicht blockierenden Fehler und die Aktion wurde fortgesetzt.

Dieses Skript blockiert `rm`-Befehle durch Beendigung mit 2 und lässt jeden anderen Befehl zum normalen Berechtigungsfluss:

```bash theme={null}
#!/bin/bash
# Reads JSON input from stdin, checks the command
input=$(cat)
command=$(jq -r '.tool_input.command' <<<"$input")

if [[ "$command" == rm* ]]; then
  echo "Blocked: rm commands are not allowed" >&2
  exit 2  # Blocking error: tool call is prevented
fi

exit 0  # No decision: the normal permission flow applies
```

<h4 id="other-exit-codes">
  Andere Exit-Codes
</h4>

Jeder andere Exit-Code blockiert nicht allein für die meisten Hook-Events. Was passiert, hängt von Ihrem stdout ab:

* Mit einem geparsten Objekt, das die Schema-Validierung besteht, für Events, die das Standard-Entscheidungsmodell verwenden, ignoriert Claude Code den Exit-Code und das JSON allein entscheidet das Ergebnis:
  * Jedes Feld, das der Event unterstützt, wird berücksichtigt, einschließlich `permissionDecision`, `additionalContext`, `updatedInput` und `systemMessage`, und der Hook wird nicht als Fehler gemeldet.
  * [Entscheidungskontrolle](#decision-control) listet die Entscheidungsfelder pro Event auf; universelle Felder wie `systemMessage` folgen der [JSON-Ausgabe](#json-output)-Tabelle.
* Mit einem geparsten Objekt, das die Schema-Validierung nicht besteht, für Events, die das Standard-Entscheidungsmodell verwenden, ist es der gleiche nicht blockierende Fehler wie [bei Exit 0](#exit-code-0): die Aktion wird fortgesetzt, und der `<Hook-Name> hook error`-Hinweis trägt die Validierungsmeldung.
* Mit stdout, das Claude Code [versucht als JSON zu parsen](#exit-code-0) und kann nicht, meldet Claude Code den gleichen nicht blockierenden Fehler wie bei Exit 0 für Events, die das Standard-Entscheidungsmodell verwenden. Die Aktion wird fortgesetzt, und der Hinweis trägt die Parse-Meldung.
* Mit stdout, das Claude Code [als einfachen Text behandelt](#exit-code-0), oder mit leerem stdout, ist es ein nicht blockierender Fehler für die meisten Hook-Events: die Aktion wird fortgesetzt, und das Transkript zeigt einen `<Hook-Name> hook error`-Hinweis gefolgt von der ersten Zeile von stderr, mit dem Präfix `Failed with non-blocking status code:`. Um den vollständigen stderr zu erfassen, aktivieren Sie [Debug-Protokollierung](#debug-hooks).

Events außerhalb des Standard-Entscheidungsmodells behalten ihre eigenen Zeilen in der [Pro-Event-Tabelle](#exit-code-2-behavior-per-event): `WorktreeCreate` schlägt die Erstellung bei jedem Nonzero-Exit fehl, unabhängig davon, was Ihr JSON sagt, und Events, die Hook-Ausgabe vollständig verwerfen, wie `StopFailure`, ignorieren Ihr JSON bei jedem Exit-Code, abgesehen von Nebeneffekt-Feldern wie `terminalSequence`, die immer noch ausgelöst werden.

Ein Hook, der nicht starten kann, landet im gleichen nicht blockierenden Bucket. Wenn der Skriptpfad nicht existiert oder nicht ausführbar ist, beendet die Shell mit einem Code wie 127 und Sie sehen den gleichen Hinweis mit der Interpreter-Meldung, zum Beispiel `Failed with non-blocking status code: /bin/sh: /path/to/hook.sh: No such file or directory`. Für die meisten Hook-Events wird die Aktion fortgesetzt. Wenn Sie einen Policy-Hook einrichten, achten Sie auf diesen Hinweis bei seiner ersten Ausführung: ein Tippfehler im Pfad in `settings.json` lässt das Gate stillschweigend deaktiviert.

<Warning>
  Für die meisten Hook-Events ist Exit-Code 2 der einzige Exit-Code, der allein durch den Code blockiert. Ohne gültiges JSON auf stdout behandelt Claude Code Exit-Code 1 als nicht blockierenden Fehler und setzt die Aktion fort, obwohl 1 der konventionelle Unix-Fehlercode ist. Wenn Ihr Hook eine Richtlinie durchsetzen soll, verwenden Sie `exit 2`. Die Worktree-Events unterscheiden sich: jeder Nonzero-Exit-Code von `WorktreeCreate` bricht die Worktree-Erstellung ab, und jeder Nonzero-Exit-Code von `WorktreeRemove` lässt die Worktree-Entfernung fehlschlagen, wenn das Verzeichnis danach noch existiert.
</Warning>

<h4 id="timeouts">
  Timeouts
</h4>

Abgesehen von einem Command Hook, den Sie mit [`async: true`](#run-hooks-in-the-background) ausführen, bricht Claude Code einen `command`-, `http`- oder `mcp_tool`-Hook ab, der sein [`timeout`](#common-fields) erreicht, verwirft die Hook-Ausgabe, sodass bei den meisten Events ein abgelaufener Hook keine Entscheidung rendert.

Bei [`PreModelSwitch`](#premodelswitch) blockiert ein Hook, der bei seinem Timeout abgebrochen wird, den Modellwechsel. Bei `PreToolUse` unterscheiden sich die beiden Hook-Familien:

* Ein abgelaufener `command`-, `http`- oder `mcp_tool`-Hook blockiert den Tool-Aufruf nicht. Der Aufruf wird durch den normalen [Berechtigungsfluss](/docs/de/permissions) fortgesetzt, verlassen Sie sich also nicht auf einen steckengebliebenen Hook, um als Gate zu fungieren.
* Ein [Agent SDK Callback Hook](/docs/de/agent-sdk/hooks), der sein Timeout überschreitet, [blockiert den Tool-Aufruf](#pretooluse).

<h4 id="exit-code-2-behavior-per-event">
  Exit-Code-2-Verhalten pro Event
</h4>

Exit-Code 2 ist die Art, wie ein Hook signalisiert „Stopp, mach das nicht.“ Die Auswirkung hängt vom Event ab, da einige Events Aktionen darstellen, die blockiert werden können (wie ein Tool-Aufruf, der noch nicht stattgefunden hat), und andere Dinge darstellen, die bereits passiert sind oder nicht verhindert werden können.

| Hook-Event | Kann blockieren? | Was passiert bei Exit 2 |
| :- | :- | :- |
| `PreToolUse` | Ja | Blockiert den Tool-Aufruf |
| `PermissionRequest` | Nein | Exit-Code 2 wird für diesen Event nicht berücksichtigt und der Berechtigungsfluss wird unverändert fortgesetzt. Verweigern Sie stattdessen durch das [`decision`-Objekt](#permissionrequest-decision-control) |
| `UserPromptSubmit` | Ja | Blockiert den Prompt, sodass er Claude nie erreicht. Siehe [Was ein blockierter Prompt hinterlässt](#what-a-blocked-prompt-leaves-behind) |
| `UserPromptExpansion` | Ja | Blockiert die Erweiterung |
| `Stop` | Ja | Verhindert, dass Claude stoppt, setzt die Konversation fort |
| `SubagentStop` | Ja | Verhindert, dass der Subagent stoppt |
| `TeammateIdle` | Ja | Verhindert, dass der Teammate untätig wird, sodass er weiterarbeitet |
| `TaskCreated` | Ja | Rollback der Task-Erstellung |
| `TaskCompleted` | Ja | Verhindert, dass die Task als abgeschlossen markiert wird |
| `ConfigChange` | Ja | Blockiert die Konfigurationsänderung von der Wirksamkeit (außer `policy_settings`) |
| `StopFailure` | Nein | Ausgabe und Exit-Code werden ignoriert, außer `terminalSequence` |
| `PostToolUse` | Nein | Zeigt stderr Claude; das Tool ist bereits ausgeführt |
| `PostToolUseFailure` | Nein | Zeigt stderr Claude; das Tool ist bereits fehlgeschlagen |
| `PostToolBatch` | Ja | Stoppt die agentic Loop vor dem nächsten Modellaufruf |
| `PermissionDenied` | Nein | Exit-Code und stderr werden ignoriert, da die Verweigerung bereits aufgetreten ist. Verwenden Sie JSON `hookSpecificOutput.retry: true`, um dem Modell zu sagen, dass es möglicherweise erneut versuchen kann; Claude Code ignoriert `retry: true` für [No-Verdict-Verweigerungen](#permissiondenied-decision-control) |
| `Notification` | Nein | Exit-Code und stderr werden ignoriert |
| `SubagentStart` | Nein | Zeigt stderr nur dem Benutzer |
| `SessionStart` | Nein | Zeigt stderr nur dem Benutzer |
| `Setup` | Nein | Exit-Code und stderr werden ignoriert |
| `SessionEnd` | Nein | Zeigt stderr nur dem Benutzer |
| `CwdChanged` | Nein | Zeigt stderr nur dem Benutzer |
| `DirectoryAdded` | Nein | Stderr geht in das Debug-Protokoll; das Verzeichnis ist bereits hinzugefügt |
| `FileChanged` | Nein | Zeigt stderr nur dem Benutzer |
| `PreCompact` | Ja | Blockiert die Komprimierung |
| `PostCompact` | Nein | Zeigt stderr nur dem Benutzer |
| `PreModelSwitch` | Ja | Blockiert den Modellwechsel und zeigt stderr dem Benutzer |
| `PostModelSwitch` | Nein | Zeigt stderr nur dem Benutzer; das Modell ist bereits gewechselt |
| `Elicitation` | Ja | Verweigert die Elicitation |
| `ElicitationResult` | Ja | Blockiert die Antwort (Aktion wird Ablehnung) |
| `WorktreeCreate` | Ja | Jeder Nonzero-Exit-Code führt dazu, dass die Worktree-Erstellung fehlschlägt |
| `WorktreeRemove` | Ja | Jeder Nonzero-Exit-Code führt dazu, dass die Worktree-Entfernung fehlschlägt, wenn das Verzeichnis danach noch existiert. Siehe [WorktreeRemove](#worktreeremove) für das, was mit dem Verzeichnis passiert |
| `InstructionsLoaded` | Nein | Exit-Code wird ignoriert |
| `MessageDisplay` | Nein | Der ursprüngliche Text wird angezeigt |

Für `SessionStart`, `SubagentStart` und `PostModelSwitch` rendert Claude Code den Exit-Code-2-stderr im Transkript als `<Hook-Name> hook error`-Hinweis, auf die gleiche Weise wie es einen [nicht blockierenden Fehler](#exit-code-output) rendert. Claude sieht es nicht, und die Session oder der Subagent wird fortgesetzt. Für `SubagentStart` erscheint der Hinweis im eigenen Transkript des Subagenten, nicht in der übergeordneten Konversation.

<h3 id="http-response-handling">
  HTTP-Response-Handling
</h3>

HTTP Hooks verwenden HTTP-Statuscodes und Response-Bodies anstelle von Exit-Codes und stdout. Die folgenden Ergebnisse gelten für die meisten Events; ein Event mit seinem eigenen Fehlervertrag in der [Pro-Event-Tabelle](#exit-code-2-behavior-per-event), wie `WorktreeCreate`, wendet diesen Vertrag auch auf einen fehlgeschlagenen HTTP-Hook an:

* **2xx mit leerem Body**: Erfolg, äquivalent zu Exit-Code 0 ohne Ausgabe
* **2xx mit JSON-Objekt-Body**: geparst mit dem gleichen [JSON-Ausgabe](#json-output)-Schema wie Command Hooks. Ein Body, der die Schema-Validierung nicht besteht, ist ein nicht blockierender Fehler
* **2xx mit jedem anderen Body, wie einfacher Text**: nicht blockierender Fehler, behandelt wie ein Nicht-2xx-Status. Claude Code fügt den Text nicht zu Claudes Kontext hinzu
* **Nicht-2xx-Status**: nicht blockierender Fehler, Ausführung wird fortgesetzt
* **Verbindungsfehler**: nicht blockierender Fehler, Ausführung wird fortgesetzt
* **Timeout**: der Hook wird abgebrochen, wie unter [Timeouts](#timeouts) beschrieben

Im Gegensatz zu Command Hooks können HTTP Hooks einen blockierenden Fehler nicht allein durch Statuscodes signalisieren. Um einen Tool-Aufruf zu blockieren oder eine Berechtigung zu verweigern, geben Sie eine 2xx-Response mit einem JSON-Body zurück, der die entsprechenden Entscheidungsfelder enthält.

<h3 id="json-output">
  JSON-Ausgabe
</h3>

Exit-Codes lassen Sie nur blockieren oder schweigen, aber JSON-Ausgabe gibt Ihnen feinere Kontrolle. Anstatt mit Code 2 zu beenden, um zu blockieren, beenden Sie mit 0 und drucken Sie ein JSON-Objekt auf stdout. Claude Code liest spezifische Felder aus diesem JSON, um Verhalten zu steuern, einschließlich [Entscheidungskontrolle](#decision-control) zum Blockieren, Zulassen oder Eskalieren an den Benutzer.

<Note>
  Wählen Sie einen Ansatz pro Hook: Verwenden Sie entweder Exit-Codes allein zum Signalisieren oder beenden Sie mit 0 und drucken Sie JSON für strukturierte Kontrolle. Wenn Sie sie mischen, behält Exit 2 seine [blockierende Auswirkung](#exit-code-2-behavior-per-event), und Claude Code liest immer noch die JSON-Felder, mit der einen Elicitation-Ausnahme, die unter [Exit-Code 2](#exit-code-2) notiert ist.
</Note>

Der stdout Ihres Hooks muss nur das JSON-Objekt enthalten. Wenn Ihr Shell-Profil beim Start Text druckt, kann es die JSON-Analyse beeinträchtigen. Siehe [Hook JSON hat keine Auswirkung](/docs/de/hooks-guide#hook-json-has-no-effect) im Troubleshooting-Leitfaden.

Die Strings `additionalContext`, `systemMessage` und `initialUserMessage` eines Hooks sowie sein einfacher stdout sind auf 10.000 Zeichen begrenzt:

* **Umfang**: Claude Code misst jeden String für sich, auch wenn mehrere Hooks für den gleichen Event ausgeführt werden. Für JSON-Ausgabe wird jedes Feld separat gemessen; einfacher stdout wird als Ganzes gemessen.
* **Über dem Limit**: Claude Code speichert die Ausgabe in einer Datei im Session-Verzeichnis und ersetzt sie durch den Dateipfad und eine Vorschau von bis zu den ersten 2.000 Zeichen. Ein großes gültiges Bash-Ergebnis wird auf die gleiche Weise behandelt, beschrieben unter [Ausgabelimits](/docs/de/tools-reference#output-limits). Im Gegensatz zu dieser Bash-Obergrenze hat diese Obergrenze keine Einstellung oder Umgebungsvariable, um sie zu erhöhen.
* **Datei lesen**: Claude Code bittet Claude nicht, die Datei zu lesen, daher halten Sie alles, das Claude immer sehen muss, innerhalb der Obergrenze.

Das JSON-Objekt unterstützt drei Arten von Feldern:

* **Universelle Felder** wie `continue` sind in der folgenden Tabelle aufgelistet. Jeder Event akzeptiert sie, aber einige Events verwerfen sie oder liefern `systemMessage` an anderer Stelle als dem Transkript. Jeder Event-Abschnitt sagt so. `terminalSequence` funktioniert auch auf diesen Events, mit den Ausnahmen, die unter [Terminal-Benachrichtigungen ausgeben](#emit-terminal-notifications) aufgelistet sind.
* **Top-Level `decision` und `reason`** werden von einigen Events verwendet, um zu blockieren oder Feedback zu geben.
* **`hookSpecificOutput`** ist ein verschachteltes Objekt für Events, die reichere Kontrolle benötigen. Es erfordert ein `hookEventName`-Feld, das auf den Event-Namen gesetzt ist.

| Feld | Standard | Beschreibung |
| :- | :- | :- |
| `continue` | `true` | Wenn `false`, stoppt Claude die Verarbeitung vollständig, nachdem der Hook ausgeführt wird. Hat Vorrang vor allen Event-spezifischen Entscheidungsfeldern |
| `stopReason` | keine | Meldung, die dem Benutzer angezeigt wird, wenn `continue` `false` ist. Sie bleibt in der Konversation, sodass Claude sie sieht, wenn die Konversation fortgesetzt wird |
| `suppressOutput` | `false` | Hat keine Auswirkung: Claude Code akzeptiert das Feld, aber handelt nicht danach. Der stdout eines erfolgreichen Hooks wird nie im Transkript angezeigt und wird im Debug-Protokoll aufgezeichnet |
| `systemMessage` | keine | Warnmeldung, die dem Benutzer angezeigt wird. In [Agent SDK](/docs/de/agent-sdk/overview) und [`--output-format stream-json`](/docs/de/headless)-Ausgabe kann es als [`SDKInformationalMessage`](/docs/de/agent-sdk/typescript#sdkinformationalmessage) ankommen |
| `terminalSequence` | keine | Eine Terminal-Escape-Sequenz, die Claude Code in Ihrem Namen ausgeben soll, wie eine Desktop-Benachrichtigung, einen Fenstertitel oder eine Glocke. Beschränkt auf OSC `0`/`1`/`2`/`9`/`99`/`777` und BEL. Wenn der Wert etwas außerhalb der Zulassungsliste enthält, wird das Feld ignoriert. Verwenden Sie dies anstelle des Schreibens zu `/dev/tty`, das für Hooks nicht verfügbar ist |

Um Claude vollständig zu stoppen:

```json theme={null}
{ "continue": false, "stopReason": "Build failed, fix errors before continuing" }
```

Für `PreToolUse`- und `PostToolUse`-Hooks gilt der Stop auch, wenn der Tool-Aufruf fehlschlägt oder abgeschlossen wird, während Claude immer noch eine Antwort streamt.

<h4 id="emit-terminal-notifications">
  Terminal-Benachrichtigungen ausgeben
</h4>

Hooks werden ohne steuerndes Terminal ausgeführt, daher schlägt das direkte Schreiben von Escape-Sequenzen zu `/dev/tty` fehl. Geben Sie stattdessen die Escape-Sequenz im `terminalSequence`-Feld zurück und Claude Code gibt sie für Sie über seinen eigenen Terminal-Schreibpfad aus. Dies ist race-frei, funktioniert innerhalb von tmux und GNU screen und funktioniert unter Windows, wo es kein `/dev/tty` gibt.

Das Feld akzeptiert einen String von einer oder mehreren zugelassenen Escape-Sequenzen:

* OSC `0`, `1`, `2`: Fenster- und Icon-Titel
* OSC `9`: iTerm2, ConEmu, Windows Terminal und WezTerm-Benachrichtigungen, einschließlich `9;4` Taskleisten-Fortschritt
* OSC `99`: Kitty-Benachrichtigungen
* OSC `777`: urxvt, Ghostty und Warp-Benachrichtigungen
* Bare BEL

Sequenzen können mit BEL oder mit ST beendet werden. Alles außerhalb der Zulassungsliste, einschließlich CSI-Cursor- und Farbsequenzen, OSC-Palettensequenzen, OSC-8-Hyperlinks, OSC-52-Clipboard-Schreibvorgänge und OSC 1337, wird abgelehnt und das Feld wird ignoriert.

Claude Code schreibt die Sequenz selbst, wenn es Ihre Hook-Ausgabe verarbeitet, sodass das Feld bei Events funktioniert, die `systemMessage` und `continue` verwerfen, wie `Notification` und `StopFailure`. Es hat zwei Limits:

* Claude Code schreibt die Sequenz nur in einer interaktiven Session und nur, während seine Schnittstelle auf dem Bildschirm ist. Im nicht-interaktiven Modus mit dem `-p`-Flag und im Agent SDK ignoriert es das Feld.
* Ein `WorktreeCreate`-Command-Hook kann kein JSON zurückgeben, da Claude Code seinen stdout als Worktree-Pfad liest. Ein HTTP-`WorktreeCreate`-Hook gibt JSON zurück und kann das Feld enthalten.

Das folgende Beispiel löst eine Desktop-Benachrichtigung von einem `Notification`-Hook aus. Die Escape-Sequenz wird mit `printf`-Oktal-Escapes erstellt, sodass die Steuerbytes nie auf der Shell-Befehlszeile erscheinen, und `jq -n --arg` erstellt die JSON-Ausgabe, sodass Anführungszeichen, Backslashes und Zeilenumbrüche in der Benachrichtigungsmeldung korrekt escaped werden:

```bash theme={null}
#!/bin/bash
# Notification hook: ping the desktop when Claude Code needs attention.
input=$(cat)
title="Claude Code"
body=$(jq -r '.message // "Needs your attention"' <<<"$input")
seq=$(printf '\033]777;notify;%s;%s\007' "$title" "$body")
jq -nc --arg seq "$seq" '{terminalSequence: $seq}'
```

Die `{ "terminalSequence": "..." }`-Form ist die gleiche aus jeder Shell oder Sprache.

<h4 id="add-context-for-claude">
  Kontext für Claude hinzufügen
</h4>

Das `additionalContext`-Feld übergibt einen String von Ihrem Hook in Claudes Kontextfenster. Claude Code umhüllt den String in eine [Systemerinnerung](/docs/de/glossary#system-reminder) und fügt ihn in die Konversation an dem Punkt ein, an dem der Hook ausgelöst wurde. Claude liest die Erinnerung bei der nächsten Modellanfrage, aber sie erscheint nicht als Chat-Nachricht in der Schnittstelle.

Geben Sie `additionalContext` innerhalb von `hookSpecificOutput` neben dem Event-Namen zurück:

```json theme={null}
{
  "hookSpecificOutput": {
    "hookEventName": "PostToolUse",
    "additionalContext": "This file is generated. Edit src/schema.ts and run `bun generate` instead."
  }
}
```

Wo die Erinnerung erscheint, hängt vom Event ab:

* [SessionStart](#sessionstart) und [SubagentStart](#subagentstart): am Anfang der Konversation, vor dem ersten Prompt
* [UserPromptSubmit](#userpromptsubmit) und [UserPromptExpansion](#userpromptexpansion): neben dem eingereichten Prompt
* [PreToolUse](#pretooluse), [PostToolUse](#posttooluse), [PostToolUseFailure](#posttoolusefailure) und [PostToolBatch](#posttoolbatch): neben dem Tool-Ergebnis
* [Stop](#stop) und [SubagentStop](#subagentstop): am Ende des Turns. Die Konversation wird fortgesetzt, sodass Claude auf das Feedback reagieren kann. Siehe [Stop-Entscheidungskontrolle](#stop-decision-control)
* [PostModelSwitch](#postmodelswitch): mit der nächsten Anfrage nach dem Wechsel. Siehe [PostModelSwitch-Entscheidungskontrolle](#postmodelswitch-decision-control) für Timing

Wenn mehrere Hooks `additionalContext` für den gleichen Event zurückgeben, empfängt Claude alle Werte.

Wenn ein Wert 10.000 Zeichen überschreitet, schreibt Claude Code den Text in eine Datei im Session-Verzeichnis und übergibt Claude stattdessen den Dateipfad mit einer Vorschau von bis zu den ersten 2.000 Zeichen. Claude kann die Datei lesen, aber Claude Code bittet nicht darum.

Verwenden Sie `additionalContext` für Informationen, die Claude über den aktuellen Zustand Ihrer Umgebung oder die gerade ausgeführte Operation wissen sollte:

* **Umgebungszustand**: der aktuelle Branch, Bereitstellungsziel oder aktive Feature-Flags
* **Bedingte Projektregeln**: welcher Test-Befehl für die gerade bearbeitete Datei gilt, welche Verzeichnisse in diesem Worktree schreibgeschützt sind
* **Externe Daten**: offene Issues, die Ihnen zugewiesen sind, aktuelle CI-Ergebnisse, Inhalte, die von einem internen Service abgerufen wurden

Für Anweisungen, die sich nie ändern, bevorzugen Sie [CLAUDE.md](/docs/de/memory). Es wird ohne Ausführung eines Skripts geladen und ist der Standard-Ort für statische Projektkonventionen.

Schreiben Sie den Text als sachliche Aussagen statt imperativer Systembefehle. Formulierungen wie „Das Bereitstellungsziel ist Produktion“ oder „Dieses Repo verwendet `bun test`“ werden als Projektinformationen gelesen. Text, der als Out-of-Band-Systembefehle formuliert ist, kann Claudes Prompt-Injection-Abwehr auslösen, was dazu führt, dass Claude den Text an Sie übermittelt, anstatt ihn als Kontext zu behandeln.

Claude Code speichert den eingefügten Text im Session-Transkript. Für Mid-Session-Events wie `PostToolUse` oder `UserPromptSubmit`, wenn Sie mit `--continue` oder `--resume` fortfahren, spielt Claude Code den gespeicherten Text erneut ab, anstatt den Hook für vergangene Turns erneut auszuführen, sodass Werte wie Zeitstempel oder Commit-SHAs veraltet werden. `SessionStart`-Hooks werden bei Wiederaufnahme mit `source` auf `"resume"` oder `"fork"` gesetzt, wenn Sie `--fork-session` hinzugefügt haben, erneut ausgeführt, sodass sie ihren Kontext aktualisieren können.

<h4 id="decision-control">
  Entscheidungskontrolle
</h4>

Nicht jeder Event unterstützt Blockierung oder Verhaltenskontrolle durch JSON. Die Events, die dies tun, verwenden jeweils einen anderen Satz von Feldern, um diese Entscheidung auszudrücken. Verwenden Sie diese Tabelle als schnelle Referenz, bevor Sie einen Hook schreiben:

| Events | Entscheidungsmuster | Schlüsselfelder |
| :- | :- | :- |
| UserPromptSubmit, UserPromptExpansion, PostToolUse, PostToolUseFailure, PostToolBatch, Stop, SubagentStop, ConfigChange, PreCompact | Top-Level `decision` | `decision: "block"`, `reason`. Stop und SubagentStop akzeptieren auch `hookSpecificOutput.additionalContext` für [nicht-fehlerhafte Rückmeldung, die die Konversation fortsetzt](#stop-decision-control) |
| TeammateIdle, TaskCompleted | Exit-Code oder `continue: false` | Exit-Code 2 blockiert die Aktion mit stderr-Rückmeldung. JSON `{"continue": false, "stopReason": "..."}` stoppt auch den Teammate vollständig, was dem `Stop`-Hook-Verhalten entspricht; [TaskCompleted ignoriert es, wenn das `TaskUpdate`-Tool den Event ausgelöst hat](#taskcompleted-decision-control) |
| TaskCreated | Exit-Code oder Top-Level `decision` | Exit-Code 2 oder `decision: "block"` [bricht die Task ab](#taskcreated-decision-control) und gibt die Meldung an Claude zurück. `continue: false` wird ignoriert |
| PreToolUse | `hookSpecificOutput` | `permissionDecision` (allow/deny/ask/defer), `permissionDecisionReason` |
| PreModelSwitch | `hookSpecificOutput` oder Top-Level `decision` | `permissionDecision` (allow/deny/ask), `permissionDecisionReason`. `decision: "block"` [bricht auch den Wechsel ab](#premodelswitch-decision-control) |
| PermissionRequest | `hookSpecificOutput` | `decision.behavior` (allow/deny) |
| PermissionDenied | `hookSpecificOutput` | `retry: true` teilt dem Modell mit, dass es den verweigerten Tool-Aufruf möglicherweise erneut versuchen kann; Claude Code ignoriert es für [No-Verdict-Verweigerungen](#permissiondenied-decision-control) |
| WorktreeCreate | Pfad-Rückgabe | Command Hook druckt Pfad auf stdout; HTTP Hook gibt `hookSpecificOutput.worktreePath` zurück. Hook-Fehler oder fehlender Pfad schlägt die Erstellung fehl |
| WorktreeRemove | Exit-Code | Jeder Nonzero-Exit-Code lässt die Entfernung fehlschlagen, wenn das Verzeichnis danach noch existiert. JSON-Ausgabe wird verworfen |
| Elicitation | `hookSpecificOutput` | `action` (accept/decline/cancel), `content` (Formularfeldwerte für accept) |
| ElicitationResult | `hookSpecificOutput` | `action` (accept/decline/cancel), `content` (Formularfeldwerte überschreiben) |
| MessageDisplay | `hookSpecificOutput` | `displayContent` ersetzt den angezeigten Text auf dem Bildschirm. Nur Anzeige: das Transkript und das, was Claude sieht, behalten das Original |
| SessionStart, SubagentStart, PostModelSwitch | Nur Kontext | `hookSpecificOutput.additionalContext` fügt Kontext für Claude hinzu. SessionStart akzeptiert auch [`initialUserMessage`, `watchPaths`, `sessionTitle` und `reloadSkills`](#sessionstart-decision-control). Keine Blockierung oder Entscheidungskontrolle |
| Setup, Notification, SessionEnd, PostCompact, InstructionsLoaded, StopFailure, CwdChanged, DirectoryAdded, FileChanged | Keine | Keine Entscheidungskontrolle. Wird für Nebeneffekte wie Protokollierung oder Bereinigung verwendet |

Einige Events können auch Inhalte umschreiben, anstatt nur zu erlauben oder zu blockieren:

* `PreToolUse`: `updatedInput` direkt unter `hookSpecificOutput` ersetzt die Argumente eines Tools, bevor es ausgeführt wird. Siehe [PreToolUse-Entscheidungskontrolle](#pretooluse-decision-control)
* `PermissionRequest`: `updatedInput` innerhalb des `decision`-Objekts. Siehe [PermissionRequest-Entscheidungskontrolle](#permissionrequest-decision-control)
* `PostToolUse`: `updatedToolOutput` ersetzt das Tool-Ergebnis. Siehe [PostToolUse-Entscheidungskontrolle](#posttooluse-decision-control)
* `UserPromptSubmit`: kann den Prompt nicht ersetzen; es injiziert nur `additionalContext` daneben

Für Redaktions- oder Transformationsfälle, fangen Sie bei `PreToolUse` für ausgehende Tool-Eingaben und `PostToolUse` für eingehende Tool-Ergebnisse ab.

Hier sind Beispiele für jedes Muster in Aktion:

<Tabs>
  <Tab title="Top-level decision">
    Der einzige Wert für `decision` ist `"block"`. Um die Aktion fortzusetzen, lassen Sie `decision` aus Ihrem JSON weg oder beenden Sie mit 0 ohne JSON:

    ```json theme={null}
    {
      "decision": "block",
      "reason": "Test suite must pass before proceeding"
    }
    ```
  </Tab>

  <Tab title="PreToolUse">
    Verwendet `hookSpecificOutput` für reichere Kontrolle: erlauben, verweigern oder eskalieren an den Benutzer. Sie können auch Tool-Eingabe vor der Ausführung ändern oder zusätzlichen Kontext für Claude injizieren. Siehe [PreToolUse-Entscheidungskontrolle](#pretooluse-decision-control) für den vollständigen Satz von Optionen.

    ```json theme={null}
    {
      "hookSpecificOutput": {
        "hookEventName": "PreToolUse",
        "permissionDecision": "deny",
        "permissionDecisionReason": "Database writes are not allowed"
      }
    }
    ```
  </Tab>

  <Tab title="PermissionRequest">
    Verwendet `hookSpecificOutput`, um eine Berechtigungsanfrage im Namen des Benutzers zu erlauben oder zu verweigern. Beim Erlauben können Sie auch die Tool-Eingabe ändern oder Berechtigungsregeln anwenden, sodass der Benutzer nicht erneut aufgefordert wird. Siehe [PermissionRequest-Entscheidungskontrolle](#permissionrequest-decision-control) für den vollständigen Satz von Optionen.

    ```json theme={null}
    {
      "hookSpecificOutput": {
        "hookEventName": "PermissionRequest",
        "decision": {
          "behavior": "allow",
          "updatedInput": {
            "command": "npm run lint"
          }
        }
      }
    }
    ```
  </Tab>
</Tabs>

Für erweiterte Beispiele einschließlich Bash-Befehlsvalidierung, Prompt-Filterung und Auto-Approval-Skripte, siehe [Was Sie automatisieren können](/docs/de/hooks-guide#what-you-can-automate) im Leitfaden und die [Bash-Befehlsvalidierungs-Referenzimplementierung](https://github.com/anthropics/claude-code/blob/main/examples/hooks/bash_command_validator_example.py).

<h2 id="hook-events">
  Hook-Ereignisse
</h2>

Jedes Ereignis entspricht einem Punkt im Lebenszyklus von Claude Code, an dem Hooks ausgeführt werden können. Die folgenden Abschnitte sind in der Reihenfolge des Lebenszyklus angeordnet: von der Einrichtung der Sitzung über die Agentenschleife bis zum Ende der Sitzung. Jeder Abschnitt beschreibt, wann das Ereignis ausgelöst wird, welche Matcher es unterstützt, welche JSON-Eingabe es erhält und wie Sie das Verhalten über die Ausgabe steuern.

<h3 id="sessionstart">
  SessionStart
</h3>

Wird ausgeführt, wenn Claude Code eine neue Sitzung startet oder eine bestehende Sitzung fortsetzt. Nützlich, um Entwicklungskontext wie bestehende Issues oder kürzliche Änderungen an Ihrer Codebasis zu laden oder Umgebungsvariablen einzurichten. Für statischen Kontext, der kein Skript erfordert, verwenden Sie stattdessen [CLAUDE.md](/docs/de/memory).

SessionStart wird bei jeder Sitzung ausgeführt, halten Sie diese Hooks daher schnell. Nur Hooks vom Typ `type: "command"` und `type: "mcp_tool"` werden unterstützt. Unter [MCP-Tool-Hook-Felder](#mcp-tool-hook-fields) erfahren Sie, wann `mcp_tool`-Hooks ausgeführt werden.

Der Matcher-Wert entspricht der Art, wie die Sitzung gestartet wurde:

| Matcher | Wann er ausgelöst wird |
| :- | :- |
| `startup` | Neue Sitzung |
| `resume` | `--resume`, `--continue` oder `/resume` |
| `clear` | `/clear` |
| `compact` | Automatische oder manuelle Komprimierung |
| `fork` | Eine neue Sitzung, die von einer bestehenden abgezweigt wurde: `--fork-session` mit `--resume` oder `--continue`, die Hintergrundkopie von `/fork`, `/branch` oder eine Konversation, die Sie [in den Hintergrund verschieben](/docs/de/agent-view#from-inside-a-session) |

Vor v2.1.214 meldeten abgezweigte Sitzungen die Quelle `"resume"`.

Wenn Sie eine interaktive Sitzung starten, beim Start eine Konversation mit `--continue` oder `--resume` fortsetzen oder `/clear` ausführen, laufen SessionStart-Hooks im Hintergrund. Sie können sofort tippen, und eine fortgesetzte Konversation erscheint, ohne auf die Hooks zu warten. Claudes erste Antwort wartet dennoch, bis die Hooks abgeschlossen sind, damit deren Kontext Claude erreicht.

Wenn Sie innerhalb einer Sitzung mit `/resume` die Konversation wechseln, wartet der Wechsel stattdessen, bis die Hooks abgeschlossen sind. Wenn Sie `/clear` ausführen oder zu einer anderen Konversation wechseln, während Hintergrund-Hooks noch laufen, wird nichts von dem, was sie zurückgeben, auf die Sitzung angewendet.

Dieselbe Wartezeit gilt beim Start, auch für eine fortgesetzte Sitzung: Ein Prompt, den Sie senden, während SessionStart-Hooks noch laufen, erreicht Claude erst, wenn diese abgeschlossen sind.

Drücken Sie während einer dieser Wartezeiten `Esc`, um den Prompt zurück in die Eingabe zu holen, ohne ihn zu senden. Die Hooks laufen weiter.

<h4 id="sessionstart-input">
  SessionStart-Eingabe
</h4>

Zusätzlich zu den [gemeinsamen Eingabefeldern](#common-input-fields) erhalten SessionStart-Hooks `source` und optional `model`, `agent_type` und `session_title`:

| Feld | Beschreibung |
| :- | :- |
| `source` | Wie die Sitzung gestartet wurde: `"startup"` für neue Sitzungen, `"resume"` für fortgesetzte Sitzungen, `"clear"` nach `/clear`, `"compact"` nach einer Komprimierung oder `"fork"` für eine neue Sitzung, die von einer bestehenden abgezweigt wurde |
| `model` | Die aktive Modellkennung. Sie kann fehlen, zum Beispiel nach `/clear` oder wenn eine Sitzung über die Konversationswiederherstellung wiederhergestellt wird. Prüfen Sie daher, ob das Feld vorhanden ist, bevor Sie es lesen |
| `agent_type` | Der Name des Agenten, vorhanden, wenn Sie Claude Code mit `claude --agent <name>` starten |
| `session_title` | Der benutzerdefinierte Titel der Sitzung, vorhanden, wenn einer gesetzt ist, zum Beispiel mit `--name`, `/rename`, der `sessionTitle`-Ausgabe eines Hooks oder `renameSession()` des Agent SDK. Ein Hook, der `sessionTitle` ausgibt, kann zuerst dieses Feld prüfen, um einen bestehenden benutzerdefinierten Titel nicht zu überschreiben |

Eine Sitzung, die Sie nicht benannt haben, kann dennoch einen [generierten Titel](/docs/de/sessions#name-your-sessions) haben. Dieser Titel ist kein benutzerdefinierter Titel und erscheint nicht in `session_title`.

Wenn `source` den Wert `"resume"` oder `"fork"` hat und das Transkript mindestens eine Antwort von Claude enthält, erhalten SessionStart-Hooks zusätzlich die folgenden vier Felder. Ihr Hook kann damit vor der ersten Anfrage melden, was das Fortsetzen einer veralteten Konversation kostet, zum Beispiel in einer [`systemMessage`](#json-output). Diese Felder erfordern Claude Code v2.1.251 oder höher.

| Feld | Beschreibung |
| :- | :- |
| `seconds_since_last_response` | Echtzeit in Sekunden seit der letzten Antwort im fortgesetzten Transkript |
| `context_tokens` | Token, die die erste Anfrage der fortgesetzten Sitzung erneut als Prompt sendet |
| `prompt_cache_likely_expired` | `true`, wenn die letzte Antwort älter ist als die [Lebensdauer des Prompt-Cache](/docs/de/prompt-caching#cache-lifetime) der Sitzung oder eine spätere Komprimierung die zwischengespeicherte Konversation ersetzt hat |
| `estimated_cache_write_usd` | Geschätzte Kosten in US-Dollar für das Schreiben von `context_tokens` in den Prompt-Cache mit dem Modell der Sitzung, ohne die Antwort |

Dieses Beispiel zeigt die Eingabe für eine Sitzung, die 90 Minuten nach ihrer letzten Antwort fortgesetzt wurde:

```json theme={null}
{
  "session_id": "abc123",
  "transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",
  "cwd": "/Users/...",
  "hook_event_name": "SessionStart",
  "source": "resume",
  "model": "claude-opus-5",
  "seconds_since_last_response": 5400,
  "context_tokens": 182340,
  "prompt_cache_likely_expired": true,
  "estimated_cache_write_usd": 1.1396
}
```

<h4 id="sessionstart-decision-control">
  SessionStart-Entscheidungssteuerung
</h4>

Claude Code fügt stdout, das es [als reinen Text behandelt](#exit-code-0), zu Claudes Kontext hinzu. Zusätzlich zu den [JSON-Ausgabefeldern](#json-output), die allen Hooks zur Verfügung stehen, können Sie diese ereignisspezifischen Felder zurückgeben:

| Feld | Beschreibung |
| :- | :- |
| `additionalContext` | Zeichenkette, die zu Beginn der Konversation vor dem ersten Prompt zu Claudes Kontext hinzugefügt wird. Unter [Kontext für Claude hinzufügen](#add-context-for-claude) erfahren Sie, wie der Text übermittelt wird und was hineingehört |
| `initialUserMessage` | Zeichenkette, die als erste Benutzernachricht der Sitzung verwendet wird. Gilt im [nicht interaktiven Modus](/docs/de/headless) mit dem Flag `-p`, wo sie zum ersten Turn wird, auch wenn kein Prompt angegeben ist. Wird ein Prompt angegeben, folgt er als nächster Turn. Anders als `additionalContext`, das an einen bestehenden Turn angehängt wird, erzeugt dieses Feld den Turn |
| `sessionTitle` | Setzt den Sitzungstitel, mit derselben Wirkung wie `/rename`. Verwenden Sie es, um Sitzungen automatisch nach dem Startordner, dem Git-Branch oder dem Worktree-Namen zu benennen. Gilt, wenn `source` den Wert `"startup"`, `"resume"` oder `"fork"` hat; wird bei `"clear"` und `"compact"` ignoriert |
| `watchPaths` | Array absoluter Pfade, die während dieser Sitzung auf [FileChanged](#filechanged)-Ereignisse überwacht werden |
| `reloadSkills` | Boolescher Wert. Bei `true` durchsucht Claude Code die [Skill](/docs/de/skills)- und Befehlsverzeichnisse erneut, nachdem die SessionStart-Hooks abgeschlossen sind, sodass vom Hook installierte Skills in derselben Sitzung ab dem ersten Prompt verfügbar sind |

```json theme={null}
{
  "hookSpecificOutput": {
    "hookEventName": "SessionStart",
    "additionalContext": "Current branch: feat/auth-refactor\nUncommitted changes: src/auth.ts, src/login.tsx\nActive issue: #4211 Migrate to OAuth2",
    "sessionTitle": "auth-refactor"
  }
}
```

Da reines stdout bei diesem Ereignis Claude bereits erreicht, kann ein Hook, der nur Kontext lädt, direkt auf stdout ausgeben, ohne JSON zu erzeugen. Verwenden Sie die JSON-Form, wenn Sie Kontext mit anderen Feldern wie `sessionTitle` kombinieren müssen.

Verwenden Sie `reloadSkills`, wenn ein SessionStart-Hook Skills installiert oder aktualisiert. Die Skill-Erkennung läuft normalerweise, bevor SessionStart-Hooks abgeschlossen sind, sodass Dateien, die der Hook in `~/.claude/skills/` oder `.claude/skills/` schreibt, sonst erst in der nächsten Sitzung erscheinen würden. Dieses Beispiel synchronisiert ein gemeinsames Skills-Repository und fordert die erneute Durchsuchung an:

```bash theme={null}
#!/bin/bash

git -C ~/.claude/skills/team-skills pull --quiet 2>/dev/null || \
  git clone --quiet https://git.example.com/your-org/team-skills.git ~/.claude/skills/team-skills

echo '{"hookSpecificOutput": {"hookEventName": "SessionStart", "reloadSkills": true}}'
```

Die Repository-URL ist ein Platzhalter; ersetzen Sie sie durch Ihr eigenes Skills-Repository. Mit dem Platzhalter schlägt das Klonen fehl und gibt eine `fatal:`-Meldung auf stderr aus. Stderr eines SessionStart-Hooks, der mit 0 beendet wird, dient nur zur Information, daher gilt die `reloadSkills`-Anfrage trotzdem.

<h4 id="persist-environment-variables">
  Umgebungsvariablen dauerhaft speichern
</h4>

SessionStart-Hooks haben Zugriff auf die Umgebungsvariable `CLAUDE_ENV_FILE`, die einen Dateipfad bereitstellt, unter dem Sie Umgebungsvariablen für nachfolgende Bash-Befehle dauerhaft speichern können.

Um einzelne Umgebungsvariablen zu setzen, schreiben Sie `export`-Anweisungen in `CLAUDE_ENV_FILE`. Verwenden Sie Anhängen (`>>`), um von anderen Hooks gesetzte Variablen zu erhalten:

```bash theme={null}
#!/bin/bash

if [ -n "$CLAUDE_ENV_FILE" ]; then
  echo 'export NODE_ENV=production' >> "$CLAUDE_ENV_FILE"
  echo 'export DEBUG_LOG=true' >> "$CLAUDE_ENV_FILE"
  echo 'export PATH="$PATH:./node_modules/.bin"' >> "$CLAUDE_ENV_FILE"
fi

exit 0
```

Um alle Umgebungsänderungen durch Einrichtungsbefehle zu erfassen, vergleichen Sie die exportierten Variablen vorher und nachher:

```bash theme={null}
#!/bin/bash

ENV_BEFORE=$(export -p | sort)

# Run your setup commands that modify the environment
source ~/.nvm/nvm.sh
nvm use 20

if [ -n "$CLAUDE_ENV_FILE" ]; then
  ENV_AFTER=$(export -p | sort)
  comm -13 <(echo "$ENV_BEFORE") <(echo "$ENV_AFTER") >> "$CLAUDE_ENV_FILE"
fi

exit 0
```

<Note>
  `CLAUDE_ENV_FILE` ist für SessionStart-, [Setup](#setup)-, [CwdChanged](#cwdchanged)- und [FileChanged](#filechanged)-Hooks verfügbar. Andere Hook-Typen haben keinen Zugriff auf diese Variable.
</Note>

<h3 id="setup">
  Setup
</h3>

Wird nur ausgelöst, wenn Sie Claude Code mit `--init-only` oder mit `--init` bzw. `--maintenance` im [nicht interaktiven Modus](/docs/de/headless) mit dem Flag `-p` starten. Beim normalen Start wird es nicht ausgelöst. Verwenden Sie es für die einmalige Installation von Abhängigkeiten oder für geplante Bereinigungen, die Sie explizit aus CI oder Skripten auslösen, getrennt vom normalen Sitzungsstart. Für die Initialisierung pro Sitzung verwenden Sie stattdessen [SessionStart](#sessionstart).

Der Matcher-Wert entspricht dem CLI-Flag, das den Hook ausgelöst hat:

| Matcher | Wann er ausgelöst wird |
| :- | :- |
| `init` | `claude --init-only` oder `claude -p --init` |
| `maintenance` | `claude -p --maintenance` |

Wenn Sie `claude --init-only` ausführen, führt Claude Code Setup-Hooks und `SessionStart`-Hooks mit dem Matcher `startup` aus und beendet sich dann, ohne eine Konversation zu starten.

Wenn Sie eine Konversation mit `-p` starten oder fortsetzen, müssen Sie außerdem einen Prompt angeben, als Argument oder über stdin weitergeleitet. Sie können den Prompt weglassen, wenn ein `SessionStart`-Hook [`initialUserMessage`](#sessionstart-decision-control) liefert oder wenn Sie eine Sitzung mit einem [zurückgestellten Tool-Aufruf](#defer-a-tool-call-for-later) fortsetzen.

Bei Erfolg gibt `--init-only` nichts im Terminal aus. Um zu bestätigen, dass die Hooks ausgeführt wurden, starten Sie mit `claude --debug-file <path> --init-only`, ersetzen `<path>` durch einen Speicherort für die Logdatei und prüfen das Log auf die Einträge der Setup- und SessionStart-Hooks.

Da Setup nicht bei jedem Start ausgelöst wird, kann sich ein Plugin, das eine installierte Abhängigkeit benötigt, nicht allein auf Setup verlassen. Das praktikable Muster besteht darin, bei der ersten Verwendung auf die Abhängigkeit zu prüfen und sie bei Fehlen zu installieren, zum Beispiel mit einem Hook oder Skill, der auf `${CLAUDE_PLUGIN_DATA}/node_modules` prüft und `npm install` ausführt, wenn es fehlt. Unter [Persistentes Datenverzeichnis](/docs/de/plugins/components#path-variables-and-persistent-data) erfahren Sie, wo installierte Abhängigkeiten gespeichert werden. Wenn Sie Ihr Plugin über einen Marketplace verteilen, benötigen Sie dieses Muster möglicherweise nicht: Claude Code [installiert geeignete Node.js-Paketabhängigkeiten automatisch](/docs/de/plugins/loading#node-js-package-dependencies), wenn es das Plugin im Cache speichert.

<h4 id="setup-input">
  Setup-Eingabe
</h4>

Zusätzlich zu den [gemeinsamen Eingabefeldern](#common-input-fields) erhalten Setup-Hooks ein Feld `trigger`, das entweder auf `"init"` oder `"maintenance"` gesetzt ist:

```json theme={null}
{
  "session_id": "abc123",
  "transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",
  "cwd": "/Users/...",
  "hook_event_name": "Setup",
  "trigger": "init"
}
```

<h4 id="setup-decision-control">
  Setup-Entscheidungssteuerung
</h4>

Setup-Hooks können nicht blockieren; die Ausführung wird bei jedem Exit-Code fortgesetzt. Bei jedem Exit-Code verwirft Claude Code die [JSON-Ausgabefelder](#json-output) eines Setup-Hooks, etwa `systemMessage`, `continue` und `hookSpecificOutput.additionalContext`. Mit `-p` erscheinen stdout, stderr und Exit-Code eines Setup-Hooks in der Ausgabe des Laufs nur als [`hook_response`-Ereignisse](/docs/de/headless#read-session-metadata), wenn Sie mit `--output-format stream-json --verbose` starten.

Setup-Hooks haben Zugriff auf `CLAUDE_ENV_FILE`. In diese Datei geschriebene Variablen bleiben für nachfolgende Bash-Befehle der Sitzung erhalten, wie bei [SessionStart-Hooks](#persist-environment-variables). Bei `Setup` werden nur Hooks vom Typ `type: "command"` ausgeführt. Ein Hook vom Typ `type: "mcp_tool"` bei `Setup` wird immer übersprungen, wie unter [MCP-Tool-Hook-Felder](#mcp-tool-hook-fields) beschrieben.

<h3 id="instructionsloaded">
  InstructionsLoaded
</h3>

Wird ausgelöst, wenn eine `CLAUDE.md`- oder `.claude/rules/*.md`-Datei in den Kontext geladen wird. Dieses Ereignis wird beim Sitzungsstart für sofort geladene Dateien ausgelöst und später erneut, wenn Dateien verzögert geladen werden, zum Beispiel wenn Claude auf ein Unterverzeichnis zugreift, das eine verschachtelte `CLAUDE.md` enthält, oder wenn bedingte Regeln mit `paths:`-Frontmatter zutreffen. Der Hook unterstützt weder Blockieren noch Entscheidungssteuerung. Er läuft asynchron zu Beobachtungszwecken.

Dieses Ereignis wird nicht ausgelöst, wenn Claude über die Einstellung **Project instructions** [`AGENTS.md` direkt liest](/docs/de/memory#agents-md). Es wird ausgelöst, wenn eine `CLAUDE.md` Ihre `AGENTS.md` importiert, wobei `load_reason` wie bei jeder anderen importierten Datei auf `include` gesetzt ist, und wenn `CLAUDE.md` ein Symlink darauf ist, als normales Laden von `CLAUDE.md`.

Der Matcher wird gegen `load_reason` ausgewertet. Verwenden Sie zum Beispiel `"matcher": "session_start"`, um nur für beim Sitzungsstart geladene Dateien auszulösen, oder `"matcher": "path_glob_match|nested_traversal"`, um nur bei verzögertem Laden auszulösen.

<h4 id="instructionsloaded-input">
  InstructionsLoaded-Eingabe
</h4>

Zusätzlich zu den [gemeinsamen Eingabefeldern](#common-input-fields) erhalten InstructionsLoaded-Hooks diese Felder:

| Feld | Beschreibung |
| :- | :- |
| `file_path` | Absoluter Pfad zur geladenen Anweisungsdatei |
| `memory_type` | Geltungsbereich der Datei: `"User"`, `"Project"`, `"Local"` oder `"Managed"` |
| `load_reason` | Warum die Datei geladen wurde: `"session_start"`, `"nested_traversal"`, `"path_glob_match"`, `"include"` oder `"compact"`. Der Wert `"compact"` tritt auf, wenn Anweisungsdateien nach einem Komprimierungsereignis erneut geladen werden |
| `globs` | Pfad-Glob-Muster aus dem `paths:`-Frontmatter der Datei, falls vorhanden. Nur bei `path_glob_match`-Ladevorgängen vorhanden |
| `trigger_file_path` | Pfad zu der Datei, deren Zugriff dieses Laden ausgelöst hat, bei verzögertem Laden |
| `parent_file_path` | Pfad zur übergeordneten Anweisungsdatei, die diese eingebunden hat, bei `include`-Ladevorgängen |

```json theme={null}
{
  "session_id": "abc123",
  "transcript_path": "/Users/.../.claude/projects/.../transcript.jsonl",
  "cwd": "/Users/my-project",
  "hook_event_name": "InstructionsLoaded",
  "file_path": "/Users/my-project/CLAUDE.md",
  "memory_type": "Project",
  "load_reason": "session_start"
}
```

<h4 id="instructionsloaded-decision-control">
  InstructionsLoaded-Entscheidungssteuerung
</h4>

InstructionsLoaded-Hooks haben keine Entscheidungssteuerung. Sie können das Laden von Anweisungen weder blockieren noch verändern. Claude Code verwirft ihre [JSON-Ausgabefelder](#json-output), etwa `systemMessage` und `continue`. Verwenden Sie dieses Ereignis für Audit-Logging, Compliance-Nachverfolgung oder Beobachtbarkeit.

<h3 id="userpromptsubmit">
  UserPromptSubmit
</h3>

Wird ausgeführt, wenn ein Prompt gesendet wird, bevor Claude ihn verarbeitet. Damit können Sie
zusätzlichen Kontext basierend auf dem Prompt bzw. der Konversation hinzufügen, Prompts validieren oder
bestimmte Arten von Prompts blockieren.

`UserPromptSubmit`-Hooks werden nicht nur bei Prompts ausgelöst, die Sie eintippen. Claude Code führt sie auch aus, wenn:

* eine [geplante Aufgabe](/docs/de/scheduled-tasks) ausgelöst wird, einschließlich einer `/loop`-Iteration
* ein [Hintergrund-Subagent](/docs/de/sub-agents#run-subagents-in-foreground-or-background) an die Sitzung zurückmeldet, die ihn gestartet hat
* [eine andere Sitzung eine Nachricht](/docs/de/cross-session-messaging) an Ihre Hauptkonversation sendet

`UserPromptSubmit`-Hooks haben für die Typen `command`, `http` und `mcp_tool` einen Standard-Timeout von 30 Sekunden, kürzer als der Standard von 600 Sekunden für diese Typen bei den meisten anderen Ereignissen. Da dieser Hook vor jedem Prompt ausgeführt wird und die Verarbeitung durch das Modell blockiert, bis er abgeschlossen ist, legt ein hängender Hook die Sitzung lahm. Wenn Ihr Hook mehr Zeit benötigt, setzen Sie das Feld `timeout` im Hook-Eintrag.

Abgesehen von einem Befehls-Hook, den Sie mit [`async: true`](#run-hooks-in-the-background) ausführen, wird ein `UserPromptSubmit`-Befehls-, HTTP- oder MCP-Tool-Hook, der seinen Timeout erreicht, abgebrochen, und seine Ausgabe einschließlich eines etwaigen `additionalContext` wird verworfen. Der Prompt erreicht Claude trotzdem, aber ohne diesen Kontext. Das Transkript zeigt einen Hinweis mit dem Namen des Hooks, dem ausgelösten Timeout und der Angabe, dass die Ausgabe verworfen wurde.

Ein [Agent SDK-Callback-Hook](/docs/de/agent-sdk/hooks) bei `UserPromptSubmit`, der seinen Timeout erreicht, blockiert den Prompt mit einer Meldung, die den Hook und den Timeout nennt, da ein Callback an dieser Stelle als Richtlinien-Gate fungieren kann, das nicht offen fehlschlagen darf. Die Sitzung wird fortgesetzt. Vor v2.1.208 beendete ein Callback-Timeout bei diesem Ereignis den Turn mit einem Ausführungsfehler.

<h4 id="userpromptsubmit-input">
  UserPromptSubmit-Eingabe
</h4>

Zusätzlich zu den [gemeinsamen Eingabefeldern](#common-input-fields) erhalten UserPromptSubmit-Hooks das Feld `prompt` mit dem gesendeten Text. Eingefügter Inhalt, der zu einem Platzhalter `[Pasted text #N]` zusammengeklappt wurde, kommt an Ort und Stelle erweitert an. In Sitzungen, in denen Claude Code [eingefügten Text für Claude kennzeichnet](/docs/de/terminal-config#how-claude-treats-pasted-text), steht dieser erweiterte Inhalt zwischen einer Zeile `<pasted_content id="…">` und einer Zeile `</pasted_content id="…">`; berücksichtigen Sie diese Zeilen, wenn Ihr Hook den Prompt parst.

UserPromptSubmit-Hooks erhalten außerdem `session_title`, wenn die Sitzung einen benutzerdefinierten Titel hat, mit derselben Bedeutung wie das [SessionStart-Feld `session_title`](#sessionstart-input).

```json theme={null}
{
  "session_id": "abc123",
  "transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",
  "cwd": "/Users/...",
  "permission_mode": "default",
  "hook_event_name": "UserPromptSubmit",
  "prompt": "Write a function to calculate the factorial of a number"
}
```

<h4 id="userpromptsubmit-decision-control">
  UserPromptSubmit-Entscheidungssteuerung
</h4>

`UserPromptSubmit`-Hooks können steuern, ob ein gesendeter Prompt verarbeitet wird, und Kontext hinzufügen. Alle [JSON-Ausgabefelder](#json-output) sind verfügbar.

Es gibt zwei Möglichkeiten, bei Exit-Code 0 Kontext zur Konversation hinzuzufügen:

* **Reiner Text auf stdout**: Claude Code fügt stdout, das es [als reinen Text behandelt](#exit-code-0), zu Claudes Kontext hinzu
* **JSON mit `additionalContext`**: Verwenden Sie das unten gezeigte JSON-Format für mehr Kontrolle. Das Feld `additionalContext` wird als Kontext hinzugefügt

Keiner der beiden Kanäle erzeugt einen sichtbaren Eintrag im Transkript. Reines stdout und der Wert von `additionalContext` werden jeweils als System-Erinnerung eingefügt, die mit dem Namen des Hooks beginnt; Claude liest beide. Um die Übermittlung zu bestätigen, prüfen Sie das [Debug-Log](#debug-hooks).

Um einen Prompt zu blockieren, geben Sie ein JSON-Objekt zurück, in dem `decision` auf `"block"` gesetzt ist:

| Feld | Beschreibung |
| :- | :- |
| `decision` | `"block"` hält den Prompt auf, bevor er Claude erreicht. Weglassen, damit der Prompt fortgesetzt wird |
| `reason` | Wird dem Benutzer angezeigt, wenn `decision` den Wert `"block"` hat. Wird nicht zum Kontext hinzugefügt |
| `additionalContext` | Zeichenkette, die neben dem abgesendeten Prompt zu Claudes Kontext hinzugefügt wird. Siehe [Kontext für Claude hinzufügen](#add-context-for-claude) |
| `sessionTitle` | Setzt den Sitzungstitel. Verwenden Sie es, um Sitzungen automatisch anhand des Prompt-Inhalts zu benennen |
| `suppressOriginalPrompt` | Bei `true` lässt es den Prompt-Text aus der Blockierungsmeldung weg, wenn der Hook den Prompt blockiert. Siehe [Was ein blockierter Prompt hinterlässt](#what-a-blocked-prompt-leaves-behind) |

Ein Hook, der durch Beenden mit 2 blockiert, wird genauso behandelt wie `reason`: Die Blockierungsmeldung zeigt dem Benutzer den stderr-Text, und dieser wird nicht zum Kontext hinzugefügt.

```json theme={null}
{
  "decision": "block",
  "reason": "Explanation for decision",
  "hookSpecificOutput": {
    "hookEventName": "UserPromptSubmit",
    "additionalContext": "My additional context here",
    "sessionTitle": "My session title",
    "suppressOriginalPrompt": true
  }
}
```

<h4 id="what-a-blocked-prompt-leaves-behind">
  Was ein blockierter Prompt hinterlässt
</h4>

Ein blockierter Prompt erreicht Claude nie, aber sein Text wird nicht überall entfernt. Standardmäßig endet die dem Benutzer angezeigte Blockierungsmeldung mit `Original prompt:` gefolgt vom abgesendeten Text, und Claude Code schreibt diese Meldung in die Transkriptdatei der Sitzung auf der Festplatte. Um den Text aus der Meldung herauszulassen, geben Sie JSON mit `"suppressOriginalPrompt": true` innerhalb von `hookSpecificOutput` aus. Das funktioniert unabhängig davon, ob der Hook mit `decision: "block"` oder durch Beenden mit 2 blockiert. Ein Hook mit Exit-Code 2, der kein JSON ausgibt, enthält in seiner Blockierungsmeldung immer den Prompt-Text.

`suppressOriginalPrompt` ändert nur die Blockierungsmeldung. Der abgesendete Text kann weiterhin in lokalen Dateien wie dem Sitzungstranskript und Ihrem Prompt-Verlauf erscheinen, ein blockierender Hook ist also kein Mittel, um ein Geheimnis von der Festplatte fernzuhalten. Informationen zum Begrenzen oder Entfernen dieser Dateien finden Sie unter [Klartextspeicherung](/docs/de/claude-directory#plaintext-storage) und [Lokale Daten löschen](/docs/de/claude-directory#clear-local-data).

<h3 id="userpromptexpansion">
  UserPromptExpansion
</h3>

Wird ausgeführt, wenn ein vom Benutzer eingegebener Befehl zu einem Prompt expandiert wird, bevor er Claude erreicht. Verwenden Sie dies, um bestimmte Befehle am direkten Aufruf zu hindern, Kontext für einen bestimmten Skill einzufügen oder zu protokollieren, welche Befehle Benutzer aufrufen. Zum Beispiel kann ein Hook, der auf `deploy` matcht, `/deploy` blockieren, sofern keine Genehmigungsdatei vorhanden ist, oder ein Hook, der auf einen Review-Skill matcht, die Review-Checkliste des Teams als `additionalContext` anhängen.

Dieses Ereignis deckt den Weg ab, den `PreToolUse` nicht abdeckt: Ein `PreToolUse`-Hook, der auf das Tool `Skill` matcht, wird nur ausgelöst, wenn Claude das Tool aufruft, aber die direkte Eingabe von `/skillname` umgeht `PreToolUse`. `UserPromptExpansion` wird auf diesem direkten Weg ausgelöst.

Matcht auf `command_name`. Lassen Sie den Matcher leer, um bei jedem Befehl vom Typ Prompt auszulösen.

<h4 id="userpromptexpansion-input">
  UserPromptExpansion-Eingabe
</h4>

Zusätzlich zu den [gemeinsamen Eingabefeldern](#common-input-fields) erhalten UserPromptExpansion-Hooks `expansion_type`, `command_name`, `command_args`, `command_source` und die ursprüngliche Zeichenkette `prompt`. Das Feld `expansion_type` ist `slash_command` für Skills und benutzerdefinierte Befehle oder `mcp_prompt` für Prompts von MCP-Servern.

```json theme={null}
{
  "session_id": "abc123",
  "transcript_path": "/Users/.../00893aaf.jsonl",
  "cwd": "/Users/...",
  "permission_mode": "default",
  "hook_event_name": "UserPromptExpansion",
  "expansion_type": "slash_command",
  "command_name": "example-skill",
  "command_args": "arg1 arg2",
  "command_source": "plugin",
  "prompt": "/example-skill arg1 arg2"
}
```

<h4 id="userpromptexpansion-decision-control">
  UserPromptExpansion-Entscheidungssteuerung
</h4>

`UserPromptExpansion`-Hooks können die Expansion blockieren oder Kontext hinzufügen. Alle [JSON-Ausgabefelder](#json-output) sind verfügbar.

| Feld | Beschreibung |
| :- | :- |
| `decision` | `"block"` verhindert die Expansion des Befehls. Weglassen, damit er fortgesetzt wird |
| `reason` | Wird dem Benutzer angezeigt, wenn `decision` den Wert `"block"` hat |
| `additionalContext` | Zeichenkette, die neben dem expandierten Prompt zu Claudes Kontext hinzugefügt wird. Siehe [Kontext für Claude hinzufügen](#add-context-for-claude) |

Ein Hook, der durch Beenden mit 2 blockiert, wird genauso behandelt wie `reason`: Die Blockierungsmeldung zeigt dem Benutzer den stderr-Text.

```json theme={null}
{
  "decision": "block",
  "reason": "This slash command is not available",
  "hookSpecificOutput": {
    "hookEventName": "UserPromptExpansion",
    "additionalContext": "Additional context for this expansion"
  }
}
```

<h3 id="messagedisplay">
  MessageDisplay
</h3>

Wird ausgeführt, während eine Assistentennachricht auf den Bildschirm gestreamt wird. Claude Code zeigt die Nachricht in Schritten an: Jedes Mal, wenn ein Stapel neu abgeschlossener Zeilen zur Darstellung bereit ist, wird der Hook einmal mit diesen Zeilen ausgeführt, und Claude Code stellt an ihrer Stelle den Ersatztext des Hooks dar. Eine lange Nachricht erzeugt mehrere Aufrufe; eine kurze Nachricht möglicherweise nur einen.

Verwenden Sie MessageDisplay, um:

* Markdown für eine minimale Anzeige zu entfernen
* den Text umzuwandeln, den eine Agent SDK-Anwendung ihren Benutzern anzeigt
* API-Schlüssel oder interne Hostnamen aus Claudes Antworten zu schwärzen

Claude Code hält jeden Stapel zurück, bis Ihr Hook zurückkehrt, halten Sie den Hook daher schnell. Wenn der Hook fehlschlägt oder eine Zeitüberschreitung auftritt, zeigt Claude Code den ursprünglichen Text an. Der Standard-Timeout für dieses Ereignis beträgt 10 Sekunden; wenn Ihr Hook mehr Zeit benötigt, setzen Sie das Feld `timeout` im Hook-Eintrag.

MessageDisplay dient nur der Anzeige: Der Ersatztext ändert nur, was auf dem Bildschirm dargestellt wird. Das Transkript und das, was Claude sieht, behalten den ursprünglichen Text, Claude sieht den Ersatz also nie, und der ausführliche Modus zeigt das Original. Der Hook erhält nur den Text von Assistentennachrichten, sodass Tool-Ergebnisse und der von Ihnen eingegebene Text unverändert dargestellt werden.

MessageDisplay unterstützt keine Matcher und wird für jede Assistentennachricht ausgelöst, die Text streamt; Nachrichten ohne Text, etwa Antworten, die nur aus Tool-Aufrufen bestehen, lösen es nicht aus.

In nicht interaktiven Läufen, einschließlich Agent SDK-Abfragen und `claude -p`, wird MessageDisplay einmal pro Assistentennachricht statt einmal pro Zeilenstapel ausgeführt. Der einzelne Aufruf erfolgt nach Abschluss der Nachricht und enthält den vollständigen Nachrichtentext: `index` ist `0`, `final` ist `true`, und `delta` enthält die gesamte Nachricht. Ein Hook, der den `delta`-Text jeder Nachricht sammelt, erhält in beiden Modi denselben Gesamttext.

<h4 id="messagedisplay-input">
  MessageDisplay-Eingabe
</h4>

Zusätzlich zu den [gemeinsamen Eingabefeldern](#common-input-fields) erhalten MessageDisplay-Hooks Kennungen für den Turn und die Nachricht, die Position dieses Aufrufs innerhalb der Nachricht und den neuen Text in `delta`. Die Stapelgrenzen hängen davon ab, wie der Text gestreamt wird. Verwenden Sie daher `index` und `final`, um den Fortschritt durch eine Nachricht zu verfolgen, statt zu erwarten, dass Zeilen auf eine bestimmte Weise gruppiert sind.

| Feld | Beschreibung |
| :- | :- |
| `turn_id` | UUID des aktuellen Turns |
| `message_id` | UUID der angezeigten Assistentennachricht. Über alle Stapel derselben Nachricht hinweg stabil. Dies ist nicht die API-ID `msg_…`, daher kann sie nicht mit den Nachrichten-IDs im Transkript abgeglichen werden |
| `index` | Nullbasierter Index dieses Stapels innerhalb der Nachricht |
| `final` | `true` beim letzten Stapel der Nachricht. Jede Nachricht hat genau einen letzten Stapel |
| `delta` | Die seit dem vorherigen Stapel neu abgeschlossenen Zeilen, einschließlich abschließender Zeilenumbrüche. Immer ganze Zeilen, außer beim letzten Stapel, der mitten in einer Zeile enden kann. In interaktiven Läufen ist das Delta des letzten Stapels leer, wenn die Nachricht mit einem Zeilenumbruch endet. Behandeln Sie daher `final` und nicht ein nicht leeres Delta als Signal für das Nachrichtenende. In Agent SDK- und `claude -p`-Läufen enthält der einzelne Aufruf die gesamte Nachricht |

```json theme={null}
{
  "session_id": "abc123",
  "transcript_path": "/Users/.../.claude/projects/.../transcript.jsonl",
  "cwd": "/Users/my-project",
  "hook_event_name": "MessageDisplay",
  "turn_id": "0c9e6a2f-7d41-4f4e-9a15-3f4f7c2b8d10",
  "message_id": "5b2a9c8e-1f63-4d8a-b7c4-9e0d2a6f1c3b",
  "index": 0,
  "final": false,
  "delta": "Here is the plan:\n"
}
```

<h4 id="messagedisplay-output">
  MessageDisplay-Ausgabe
</h4>

Zusätzlich zu den [JSON-Ausgabefeldern](#json-output), die allen Hooks zur Verfügung stehen, können MessageDisplay-Hooks `displayContent` zurückgeben, um das Delta auf dem Bildschirm zu ersetzen:

| Feld | Beschreibung |
| :- | :- |
| `displayContent` | Text, der anstelle des Deltas angezeigt wird. Weglassen, um das Original anzuzeigen |

MessageDisplay-Hooks haben keine Entscheidungssteuerung. Sie können die Nachricht weder blockieren noch ändern, was im Transkript gespeichert oder an Claude gesendet wird. Claude Code verarbeitet `displayContent` aus ihrer JSON-Ausgabe und verwirft `systemMessage` und `continue`.

Dieses Beispiel entfernt Markdown-Formatierung aus Claudes Antworten für eine reine Textanzeige. Das Skript liest jeden Stapel von stdin, entfernt Fettdruck-Markierungen und Backticks für Inline-Code aus `delta` und gibt das Ergebnis als `displayContent` zurück.

<Tabs>
  <Tab title="macOS/Linux">
    Registrieren Sie in Ihrer Einstellungsdatei einen Befehls-Hook für das Ereignis:

    ```json theme={null}
    {
      "hooks": {
        "MessageDisplay": [
          {
            "hooks": [
              {
                "type": "command",
                "command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/plain-display.sh",
                "args": []
              }
            ]
          }
        ]
      }
    }
    ```

    Speichern Sie dieses Skript unter `.claude/hooks/plain-display.sh` in Ihrem Projekt und machen Sie es mit `chmod +x` ausführbar:

    ```bash theme={null}
    #!/bin/bash
    jq '{hookSpecificOutput: {hookEventName: "MessageDisplay", displayContent: (.delta | gsub("\\*\\*"; "") | gsub("`"; ""))}}'
    ```
  </Tab>

  <Tab title="Windows (PowerShell)">
    Registrieren Sie einen Befehls-Hook, der das Skript über PowerShell ausführt:

    ```json theme={null}
    {
      "hooks": {
        "MessageDisplay": [
          {
            "hooks": [
              {
                "type": "command",
                "command": "powershell.exe",
                "args": [
                  "-NoProfile",
                  "-ExecutionPolicy",
                  "Bypass",
                  "-File",
                  "${CLAUDE_PROJECT_DIR}/.claude/hooks/plain-display.ps1"
                ]
              }
            ]
          }
        ]
      }
    }
    ```

    Das Flag `-NoProfile` überspringt das Laden Ihres PowerShell-Profils, damit der Hook schnell startet, und `-ExecutionPolicy Bypass` erlaubt PowerShell, die lokale Skriptdatei auszuführen.

    Speichern Sie dieses Skript unter `.claude/hooks/plain-display.ps1` in Ihrem Projekt:

    ```powershell theme={null}
    $batch = [Console]::In.ReadToEnd() | ConvertFrom-Json
    $text = $batch.delta -replace '\*\*', '' -replace '`', ''
    @{
      hookSpecificOutput = @{
        hookEventName = "MessageDisplay"
        displayContent = $text
      }
    } | ConvertTo-Json
    ```
  </Tab>
</Tabs>

Stapel ohne Markdown werden unverändert durchgereicht. Wenn das Skript fehlschlägt, zum Beispiel weil `jq` fehlt, zeigt Claude Code den ursprünglichen Text an und vermerkt den Fehler nur in der [Debug-Ausgabe](#debug-hooks), nicht in der Sitzung.

<h3 id="pretooluse">
  PreToolUse
</h3>

Wird ausgeführt, nachdem Claude Tool-Parameter erstellt hat und bevor der Tool-Aufruf verarbeitet wird. Matcht auf jeden Tool-Namen außer `EndConversation`: integrierte Tools wie `Bash`, `PowerShell`, `Edit`, `Write`, `Read`, `Glob`, `Grep`, `Agent`, `Workflow`, `WebFetch`, `WebSearch`, `AskUserQuestion` und `ExitPlanMode` sowie beliebige [MCP-Tool-Namen](#match-mcp-tools).

Um einen Hook auszuführen, wenn sich eine bestimmte Datei auf der Festplatte ändert, unabhängig davon, was sie geschrieben hat, verwenden Sie [FileChanged](#filechanged), statt dateibearbeitende Tools nach Namen zu matchen. Anders als PreToolUse führt Claude Code FileChanged-Hooks nach der Änderung aus, und sie haben keine Entscheidungssteuerung, können den Schreibvorgang also nicht blockieren.

<Warning>
  PreToolUse wird nur ausgeführt, wenn Claude ein Tool aufruft. Dateien, die Sie [mit `@` in Ihrem Prompt referenzieren](/docs/de/common-workflows#reference-files-and-directories), werden ohne Tool-Aufruf hinzugefügt: Claude Code fügt ihren Inhalt beim Aufbau des Prompts ein, sodass für sie kein PreToolUse-Hook ausgelöst wird, auch keine Hooks, die auf `Read` matchen. Um bestimmte Pfade für `@`-Referenzen zu sperren, verwenden Sie stattdessen eine [`Read`-deny-Regel](/docs/de/permissions#read-and-edit).

  PreToolUse wird außerdem nicht für [`EndConversation`](/docs/de/tools-reference#endconversation-tool-behavior) ausgelöst.
</Warning>

Verwenden Sie die [PreToolUse-Entscheidungssteuerung](#pretooluse-decision-control), um den Tool-Aufruf zuzulassen, abzulehnen, nachzufragen oder zurückzustellen.

Ein [Agent SDK-Callback-Hook](/docs/de/agent-sdk/hooks) bei `PreToolUse`, der seinen Timeout überschreitet, blockiert den Tool-Aufruf, und Claude erhält ein Fehlerergebnis, das den Timeout nennt. Eine explizite Ablehnung durch einen anderen Hook hat weiterhin Vorrang.

<h4 id="pretooluse-input">
  PreToolUse-Eingabe
</h4>

Zusätzlich zu den [gemeinsamen Eingabefeldern](#common-input-fields) erhalten PreToolUse-Hooks `tool_name`, `tool_input` und `tool_use_id`.

Bei einem [MCP-Tool](#match-mcp-tools) enthält die Eingabe zusätzlich `mcp_server`, ein Objekt mit dem `name` des Servers und einer `source`, die angibt, woher die Definition des Servers stammt. Zu den `source`-Werten gehören `plugin`, `sdk` und Konfigurations-Geltungsbereiche wie `user` und `project`. [`McpServerProvenance`](/docs/de/agent-sdk/typescript#mcpserverprovenance) in der Agent SDK-Referenz listet alle auf und erklärt, wie Sie mit einem Wert umgehen, den Sie nicht kennen. Stützen Sie Vertrauensentscheidungen auf `source` statt auf `name` oder das Tool-Namenspräfix `mcp__<server>__`. Das Feld `mcp_server` erfordert Claude Code v2.1.274 oder höher.

Für die Datei-Tools `Write`, `Edit` und `Read` ist `tool_input.file_path` immer absolut:

* Claude Code expandiert `~` und relative Pfade, bevor Hooks ausgeführt werden, sodass ein Hook, der auf Pfade matcht, nicht über `~` oder eine relative Schreibweise desselben Pfads umgangen werden kann
* Unter Windows kommt der Pfad mit Backslash-Trennzeichen an, auch wenn Ihr Hook unter Git Bash läuft, wo `$PWD` wie `/c/project` aussieht
* Ein Vergleich mit Schrägstrichen, etwa eine Prüfung auf `/src/`, matcht nie einen Backslash-Pfad, und der Tool-Aufruf wird fortgesetzt, als hätte der Hook nichts zu blockieren
* Normalisieren Sie die Trennzeichen vor dem Vergleich: `FILE_PATH="${FILE_PATH//\\//}"` in Bash oder `file_path.replace("\\", "/")` in Python, und matchen Sie dann ein Pfadsegment wie `/src/`, statt mit `^` zu verankern, da der Pfad absolut ist

Ein `Write`-Aufruf unter Windows liefert:

```json theme={null}
{
  "hook_event_name": "PreToolUse",
  "tool_name": "Write",
  "tool_input": {
    "file_path": "C:\\project\\src\\index.ts",
    "content": "..."
  },
  ...
}
```

Die Felder von `tool_input` hängen vom Tool ab:

<a id="bash" />

<h5 id="bash">
  Bash
</h5>

Führt Shell-Befehle aus.

| Feld | Typ | Beispiel | Beschreibung |
| :- | :- | :- | :- |
| `command` | string | `"npm test"` | Der auszuführende Shell-Befehl |
| `description` | string | `"Run test suite"` | Optionale Beschreibung dessen, was der Befehl tut |
| `timeout` | number | `120000` | Optionaler Timeout in Millisekunden. Werte über dem [Maximum](/docs/de/tools-reference#bash-tool-behavior) werden auf das Maximum reduziert statt abgelehnt |
| `run_in_background` | boolean | `false` | Ob der Befehl im Hintergrund ausgeführt werden soll |

Wenn ein Bash-Befehl Dateien in einem Git-Repository ändert, kann Claude Code aufzeichnen, was sich geändert hat. Es zeichnet die Änderungen in jedem Berechtigungsmodus auf, wenn die Einstellung [`bashEditDiffEnabled`](/docs/de/settings-reference#basheditdiffenabled) die Aufzeichnung aktiviert; der Eintrag dieser Einstellung gibt an, welche Dateien sie setzen können. Andernfalls zeichnet es sie nur im Auto-Modus und im Modus `bypassPermissions` auf, und nur dann, wenn Claude Code Claude anweist, Dateien über Bash zu bearbeiten. Setzen Sie `bashEditDiffEnabled` auf `false`, um die Aufzeichnung auszuschalten. Hintergrundbefehle und nur lesende Befehle enthalten keinen Diff.

Ihr [PostToolUse-Hook](#posttooluse) erhält die geänderten Dateien dann in `tool_response.bashEditDiff`. Die Liste umfasst, was sich im Repository geändert hat, während der Befehl lief. Dateien, die Git ignoriert, und Dateien in Submodulen werden nicht aufgeführt. Erfordert Claude Code v2.1.269 oder höher.

<Note>
  Die Liste wird nach bestem Bemühen erstellt und befindet sich in der öffentlichen Beta. Claude Code kann eine Änderung übersehen, eine Datei aufnehmen, die ein anderer Prozess gleichzeitig geändert hat, oder an seinen Größenlimits abbrechen. Die Struktur des Felds kann sich ändern. Verwenden Sie die Liste, um herauszufinden, was überprüft werden sollte, nicht um eine Richtlinie durchzusetzen.
</Note>

`changedFiles` und `files` listen auf, was der Befehl geändert hat; die übrigen Felder geben an, wie vollständig und wie zuverlässig diese Liste ist.

| Feld | Typ | Beispiel | Beschreibung |
| :- | :- | :- | :- |
| `changedFiles` | array | `["/path/to/src/app.ts"]` | Absolute Pfade der Dateien, die der Befehl geändert hat, höchstens 200. Vorhanden, sobald `files` einen Diff enthält oder `moreFiles` größer als null ist |
| `files` | array | `[{"filePath": "/path/to/src/app.ts", "hunks": [...]}]` | Diffs von bis zu 5 geänderten Dateien, zur Anzeige. `created` oder `deleted` ist `true` für eine Datei, die der Befehl hinzugefügt oder entfernt hat |
| `moreFiles` | number | `2` | Anzahl geänderter Dateien ohne Diff in `files` |
| `unavailable` | boolean | `true` | Gesetzt, wenn der Diff unvollständig ist oder nicht erstellt werden konnte |
| `skipped` | boolean | `true` | Gesetzt für einen Git-Befehl, der den Arbeitsbaum verschiebt, etwa `git checkout` oder `git stash`, sodass Claude Code keinen Diff erstellt |
| `shared` | boolean | `true` | Gesetzt, wenn ein anderer Bash-Tool-Aufruf, etwa der eines Subagenten, gleichzeitig im selben Repository lief, sodass einige aufgeführte Änderungen von diesem Befehl stammen können |

<a id="powershell" />

<h5 id="powershell">
  PowerShell
</h5>

Führt PowerShell-Befehle aus. Informationen zur Verfügbarkeit je nach Plattform finden Sie unter [PowerShell-Tool](/docs/de/tools-reference#powershell-tool).

Die Felder entsprechen denen des Bash-Tools, mit der Befehlszeichenkette in `command`:

| Feld | Typ | Beispiel | Beschreibung |
| :- | :- | :- | :- |
| `command` | string | `"Get-ChildItem -Recurse"` | Der auszuführende PowerShell-Befehl |
| `description` | string | `"List files recursively"` | Optionale Beschreibung dessen, was der Befehl tut |
| `timeout` | number | `120000` | Optionaler Timeout in Millisekunden |
| `run_in_background` | boolean | `false` | Ob der Befehl im Hintergrund ausgeführt werden soll |

Matchen Sie in Hooks, die Shell-Befehle prüfen, auf `Bash|PowerShell`, damit sie beide Tools abdecken:

* Unter Windows behandelt Claude PowerShell überall dort, wo das PowerShell-Tool aktiviert ist, als primäre Shell und leitet Shell-Befehle darüber.
* Unter Windows ohne Git Bash wird das Tool automatisch aktiviert, und Claude Code registriert das Bash-Tool überhaupt nicht.
* Ein Hook, der nur auf `Bash` matcht, wird dort nie ausgelöst.

<h5 id="write">
  Write
</h5>

Erstellt oder überschreibt eine Datei.

| Feld | Typ | Beispiel | Beschreibung |
| :- | :- | :- | :- |
| `file_path` | string | `"/path/to/file.txt"` | Absoluter Pfad zur zu schreibenden Datei |
| `content` | string | `"file content"` | In die Datei zu schreibender Inhalt |

<h5 id="edit">
  Edit
</h5>

Ersetzt eine Zeichenkette in einer bestehenden Datei.

| Feld | Typ | Beispiel | Beschreibung |
| :- | :- | :- | :- |
| `file_path` | string | `"/path/to/file.txt"` | Absoluter Pfad zur zu bearbeitenden Datei |
| `old_string` | string | `"original text"` | Zu suchender und zu ersetzender Text |
| `new_string` | string | `"replacement text"` | Ersatztext |
| `replace_all` | boolean | `false` | Ob alle Vorkommen ersetzt werden sollen |

<h5 id="read">
  Read
</h5>

Liest Dateiinhalte.

| Feld | Typ | Beispiel | Beschreibung |
| :- | :- | :- | :- |
| `file_path` | string | `"/path/to/file.txt"` | Absoluter Pfad zur zu lesenden Datei |
| `offset` | number | `10` | Optionale Zeilennummer, ab der gelesen wird |
| `limit` | number | `50` | Optionale Anzahl zu lesender Zeilen |

<h5 id="glob">
  Glob
</h5>

Findet Dateien, die einem Glob-Muster entsprechen.

| Feld | Typ | Beispiel | Beschreibung |
| :- | :- | :- | :- |
| `pattern` | string | `"**/*.ts"` | Glob-Muster, gegen das Dateien abgeglichen werden |
| `path` | string | `"/path/to/dir"` | Optionales Verzeichnis, in dem gesucht wird. Standardmäßig das aktuelle Arbeitsverzeichnis |

<h5 id="grep">
  Grep
</h5>

Durchsucht Dateiinhalte mit regulären Ausdrücken.

| Feld | Typ | Beispiel | Beschreibung |
| :- | :- | :- | :- |
| `pattern` | string | `"TODO.*fix"` | Zu suchendes Muster als regulärer Ausdruck |
| `path` | string | `"/path/to/dir"` | Optionale Datei oder optionales Verzeichnis, in dem gesucht wird |
| `glob` | string | `"*.ts"` | Optionales Glob-Muster zum Filtern von Dateien |
| `output_mode` | string | `"content"` | `"content"`, `"files_with_matches"` oder `"count"`. Standardmäßig `"files_with_matches"` |
| `-i` | boolean | `true` | Suche ohne Berücksichtigung der Groß-/Kleinschreibung |
| `multiline` | boolean | `false` | Mehrzeiliges Matching aktivieren |

<h5 id="webfetch">
  WebFetch
</h5>

Ruft Webinhalte ab und verarbeitet sie.

| Feld | Typ | Beispiel | Beschreibung |
| :- | :- | :- | :- |
| `url` | string | `"https://example.com/api"` | URL, von der Inhalte abgerufen werden |
| `prompt` | string | `"Extract the API endpoints"` | Prompt, der auf den abgerufenen Inhalt angewendet wird |

<h5 id="websearch">
  WebSearch
</h5>

Durchsucht das Web.

| Feld | Typ | Beispiel | Beschreibung |
| :- | :- | :- | :- |
| `query` | string | `"react hooks best practices"` | Suchanfrage |
| `allowed_domains` | array | `["docs.example.com"]` | Optional: nur Ergebnisse von diesen Domains einschließen |
| `blocked_domains` | array | `["spam.example.com"]` | Optional: Ergebnisse von diesen Domains ausschließen |

<h5 id="agent">
  Agent
</h5>

Startet einen [Subagenten](/docs/de/sub-agents).

| Feld | Typ | Beispiel | Beschreibung |
| :- | :- | :- | :- |
| `prompt` | string | `"Find all API endpoints"` | Die Aufgabe, die der Agent ausführen soll |
| `description` | string | `"Find API endpoints"` | Kurze Beschreibung der Aufgabe |
| `subagent_type` | string | `"Explore"` | Typ des zu verwendenden spezialisierten Agenten |
| `model` | string | `"sonnet"` | Optionaler Modell-Alias, um den Standard zu überschreiben |

Wenn ein Agent-Aufruf im Vordergrund abgeschlossen ist, erhält Ihr [PostToolUse-Hook](#posttooluse) das Ergebnis des Subagenten und die Telemetrie des Laufs in `tool_response`. Lesen Sie diese Felder, um den Lauf zu untersuchen; für Token- und Kostenzusammenfassungen über Subagenten hinweg verwenden Sie die [Token- und Kostenzähler](/docs/de/monitoring-usage#token-counter), gefiltert auf `query_source` `"subagent"`, da `totalTokens` und `usage` nur die letzte Anfrage abdecken:

| Feld | Typ | Beispiel | Beschreibung |
| :- | :- | :- | :- |
| `status` | string | `"completed"` | `"completed"` für Subagenten im Vordergrund, `"async_launched"` für Subagenten im Hintergrund. Subagenten laufen standardmäßig im Hintergrund, daher erzeugt auch ein Agent-Aufruf ohne `run_in_background` den Wert `"async_launched"` |
| `agentId` | string | `"a4d2c8f1e0b3a297"` | Kennung des Subagenten-Laufs |
| `content` | array | `[{"type": "text", "text": "Found 12 endpoints..."}]` | Die abschließenden Textblöcke des Subagenten oder, bei einem Subagenten, dessen Bericht über `SubagentHandback` läuft, an ihrer Stelle ein kurzer Hinweis auf diese Übergabe |
| `resolvedModel` | string | `"claude-sonnet-4-5"` | Modell, mit dem der Subagent gestartet ist, das vom angeforderten Modell abweichen kann |
| `modelsUsed` | array | `["claude-sonnet-4-5", "claude-haiku-4-5"]` | Verwendete Modelle in Reihenfolge, wobei aufeinanderfolgende Wiederholungen zusammengefasst werden; nur gesetzt, wenn das Modell während des Laufs gewechselt wurde. Erfordert Claude Code v2.1.212 oder höher |
| `totalTokens` | number | `12450` | Token-Anzahl aus der letzten API-Anfrage des Subagenten: Eingabe-, Ausgabe- und Cache-Token zusammen. Dies ist keine Summe über den gesamten Lauf |
| `totalDurationMs` | number | `48211` | Echtzeitdauer des Subagenten-Laufs |
| `totalToolUseCount` | number | `7` | Anzahl der Tool-Aufrufe, die der Subagent durchgeführt hat |
| `usage` | object | `{"input_tokens": 8320, ...}` | Token-Aufschlüsselung nach Typ für die letzte API-Anfrage: `input_tokens`, `output_tokens`, `cache_creation_input_tokens`, `cache_read_input_tokens` |

Ab Claude Code v2.1.271 liefert ein Subagent, der mit dem Tool [`SubagentHandback`](/docs/de/tools-reference) läuft, das Claude Code im [Auto-Modus](/docs/de/permission-modes#eliminate-prompts-with-auto-mode) bereitstellt, seinen Bericht über dieses Tool, statt ihn als Text zurückzugeben. Das Feld `content` seines `completed`-Ergebnisses enthält dann einen kurzen Hinweis auf diese Übergabe statt des Berichts selbst. Um den Bericht zu lesen, lassen Sie einen `PreToolUse`- oder `PostToolUse`-Hook auf `SubagentHandback` matchen und lesen `tool_input.message`.

Bei Subagenten im Hintergrund kehrt das Tool zurück, wenn die Aufgabe in den Hintergrund wechselt, daher enthält `tool_response` keine Nutzungsfelder: Ein Start im Hintergrund kehrt sofort zurück, und eine Vordergrundaufgabe, die Claude Code während des Laufs in den Hintergrund verschiebt, kehrt bei diesem Übergang zurück. Sie hat `status: "async_launched"`, `agentId`, `description`, `prompt`, `outputFile` und `resolvedModel`.

Bei einer `completed`-Antwort nennt `resolvedModel` das Modell, mit dem der Subagent gestartet ist, das vom `model`-Wert in `tool_input` abweichen kann, etwa wenn `availableModels` oder eine andere Überschreibung greift. Bei einer `async_launched`-Antwort nennt `resolvedModel` das Modell, das verwendet wurde, als der Agent in den Hintergrund wechselte, sodass ein Wechsel vor dem Verschieben in den Hintergrund dort berücksichtigt ist. `modelsUsed` und das Verhalten von `resolvedModel` zum Zeitpunkt des Verschiebens in den Hintergrund erfordern Claude Code v2.1.212 oder höher.

<a id="askuserquestion" />

<h5 id="askuserquestion">
  AskUserQuestion
</h5>

Stellt dem Benutzer ein bis vier Multiple-Choice-Fragen.

| Feld | Typ | Beispiel | Beschreibung |
| :- | :- | :- | :- |
| `questions` | array | `[{"question": "Which framework?", "header": "Framework", "options": [{"label": "React", "description": "Component library"}, {"label": "Vue", "description": "Progressive framework"}], "multiSelect": false}]` | Zu stellende Fragen, jeweils mit einem `question`-String, kurzem `header`, `options`-Array und optionalem `multiSelect`-Flag |
| `answers` | object | `{"Which framework?": "React"}` | Optional. Ordnet den Fragetext dem ausgewählten Optionslabel zu. Antworten mit Mehrfachauswahl verbinden Labels mit Kommas. Claude setzt dieses Feld nicht; liefern Sie es über `updatedInput`, um programmatisch zu antworten |

<h5 id="exitplanmode">
  ExitPlanMode
</h5>

Präsentiert einen Plan und bittet den Benutzer um Genehmigung, bevor Claude den [Plan-Modus](/docs/de/permission-modes#analyze-before-you-edit-with-plan-mode) verlässt. Claude schreibt den Plan vor dem Aufruf des Tools in eine Datei auf der Festplatte, daher ist das wörtliche `tool_input` des Modells in der Regel leer. Claude Code fügt den Planinhalt und den Dateipfad ein, bevor die Eingabe an Hooks übergeben wird.

| Feld | Typ | Beispiel | Beschreibung |
| :- | :- | :- | :- |
| `plan` | string | `"## Refactor auth\n1. Extract..."` | Planinhalt in Markdown. Aus der Plandatei auf der Festplatte eingefügt |
| `planFilePath` | string | `"/Users/.../plans/refactor-auth.md"` | Pfad zur Plandatei. Eingefügt |
| `allowedPrompts` | array | `[{"tool": "Bash", "prompt": "run tests"}]` | Veraltet. Claude Code akzeptiert das Feld, ignoriert es aber. Vor v2.1.205 enthielt es promptbasierte Berechtigungen, die Claude zur Umsetzung des Plans angefordert hat |

In `PostToolUse` ist `tool_response` ein Objekt mit den Feldern `plan` und `filePath`, die den genehmigten Plan enthalten, sowie internen Status-Flags. Lesen Sie `tool_response.plan` für den Planinhalt, statt die Datei erneut von der Festplatte zu lesen.

<h4 id="pretooluse-decision-control">
  PreToolUse-Entscheidungssteuerung
</h4>

`PreToolUse`-Hooks können steuern, ob ein Tool-Aufruf fortgesetzt wird. Anders als andere Hooks, die ein `decision`-Feld auf oberster Ebene verwenden, gibt PreToolUse seine Entscheidung innerhalb eines `hookSpecificOutput`-Objekts zurück. Das ermöglicht eine umfassendere Steuerung: vier Ergebnisse (allow, deny, ask oder defer) sowie die Möglichkeit, die Tool-Eingabe vor der Ausführung zu ändern.

| Feld | Beschreibung |
| :- | :- |
| `permissionDecision` | `"allow"` überspringt die Berechtigungsabfrage, außer bei den [Aktionen, die kein Modus automatisch genehmigt](/docs/de/permission-modes#actions-no-mode-auto-approves), sowie bei `AskUserQuestion` und `ExitPlanMode`, die [`updatedInput` zusammen damit](#allow-with-updatedinput) benötigen. `"deny"` verhindert den Tool-Aufruf. `"ask"` bittet den Benutzer um Bestätigung. `"defer"` beendet sauber, sodass das Tool später fortgesetzt werden kann. [Deny- und ask-Regeln](/docs/de/permissions#manage-permissions) werden unabhängig davon ausgewertet, was der Hook zurückgibt |
| `permissionDecisionReason` | Bei `"ask"` wird er dem Benutzer in der Berechtigungsabfrage angezeigt. Wenn Claude Code [den Aufruf ablehnt](/docs/de/headless#turn-off-permission-prompts-in-unattended-runs), in einem `-p`-Lauf, in dem niemand diese Abfrage beantworten kann, liest Claude den Grund stattdessen im Tool-Ergebnis. Bei `"deny"` wird er Claude angezeigt. Bei `"allow"` und `"defer"` wird er nur in das [Debug-Log](#debug-hooks) geschrieben |
| `updatedInput` | Ändert die Eingabeparameter des Tools vor der Ausführung. Ersetzt das gesamte Eingabeobjekt, nehmen Sie daher unveränderte Felder zusammen mit den geänderten auf. Claude Code wertet Berechtigungsregeln und die [Eignung eines Bash-Befehls für das automatische Verschieben in den Hintergrund](/docs/de/tools-reference#foreground-commands-that-move-to-the-background) anhand der Eingabe aus, die Ihr Hook zurückgibt, nicht anhand der Eingabe, die Claude gesendet hat. Kombinieren Sie es mit `"allow"` für automatische Genehmigung oder mit `"ask"`, um dem Benutzer die geänderte Eingabe anzuzeigen. Bei `"defer"` wird es ignoriert |
| `additionalContext` | Zeichenkette, die neben dem Tool-Ergebnis zu Claudes Kontext hinzugefügt wird. Wird ignoriert, wenn `permissionDecision` den Wert `"defer"` hat. Siehe [Kontext für Claude hinzufügen](#add-context-for-claude) |

Wenn mehrere PreToolUse-Hooks unterschiedliche Entscheidungen zurückgeben, gilt die Rangfolge `deny` > `defer` > `ask` > `allow`.

Ein Hook, der durch Beenden mit 2 blockiert, wird genauso behandelt wie `"deny"`: Claude sieht die stderr-Meldung als Ablehnungsgrund.

Wenn ein Hook `"ask"` zurückgibt, enthält die dem Benutzer angezeigte Berechtigungsabfrage ein Label, das angibt, woher der Hook stammt: `[settings]` für einen Hook aus einer beliebigen Einstellungsdatei oder aus Agenten-Frontmatter, `[plugin:<name>]` für den Hook eines Plugins oder `[skill]` für einen Hook aus Skill-Frontmatter. So können Benutzer nachvollziehen, welche Konfigurationsquelle die Bestätigung anfordert.

Ein `"ask"` eines Hooks erzwingt auch im [Auto-Modus](/docs/de/permission-modes#eliminate-prompts-with-auto-mode) eine Berechtigungsabfrage: Der Klassifikator kann den Tool-Aufruf weiterhin ablehnen, ihn aber nicht stillschweigend genehmigen. Vor v2.1.211 konnte der Klassifikator einen Bash-Befehl, der außerhalb der [Sandbox](/docs/de/sandboxing) lief, genehmigen, ohne die vom Hook angeforderte Abfrage anzuzeigen; der Klassifikator wendete dabei weiterhin seine eigenen Sicherheitsregeln auf diesen Befehl an, und ein `"deny"` eines Hooks wurde immer beachtet.

```json theme={null}
{
  "hookSpecificOutput": {
    "hookEventName": "PreToolUse",
    "permissionDecision": "allow",
    "permissionDecisionReason": "My reason here",
    "updatedInput": {
      "field_to_modify": "new value"
    },
    "additionalContext": "Current environment: production. Proceed with caution."
  }
}
```

<Note>
  PreToolUse verwendete früher die Felder `decision` und `reason` auf oberster Ebene, diese sind für dieses Ereignis jedoch veraltet. Verwenden Sie stattdessen `hookSpecificOutput.permissionDecision` und `hookSpecificOutput.permissionDecisionReason`. Die veralteten Werte `"approve"` und `"block"` entsprechen `"allow"` bzw. `"deny"`. Andere Ereignisse wie PostToolUse und Stop verwenden weiterhin `decision` und `reason` auf oberster Ebene als aktuelles Format.
</Note>

<h4 id="allow-with-updatedinput">
  Tools, die eine Benutzerinteraktion erfordern
</h4>

`AskUserQuestion` und `ExitPlanMode` erfordern eine Benutzerinteraktion. Im [nicht interaktiven Modus](/docs/de/headless) mit dem Flag `-p` bietet Claude Code sie nur an, wenn der Lauf einen [Berechtigungs-Host](/docs/de/headless#turn-off-permission-prompts-in-unattended-runs) hat, der die Abfrage entgegennimmt, etwa einen `canUseTool`-Callback des Agent SDK.

Ein `PreToolUse`-Hook erfüllt diese Anforderung, wenn er Folgendes tut:

1. Er liest die Eingabe des Tools von stdin
2. Er erfasst die Antwort über Ihre eigene Benutzeroberfläche
3. Er gibt `permissionDecision: "allow"` zusammen mit `updatedInput` zurück, das die Antwort enthält, sodass das Tool ohne Abfrage ausgeführt wird

Die alleinige Rückgabe von `"allow"` reicht für diese Tools nicht aus.

Geben Sie bei `AskUserQuestion` das ursprüngliche `questions`-Array zurück und fügen Sie ein [`answers`](#askuserquestion)-Objekt hinzu, das den Text jeder Frage der gewählten Antwort zuordnet. Diese Ausgabe beantwortet eine Frage mit `React`:

```json theme={null}
{
  "hookSpecificOutput": {
    "hookEventName": "PreToolUse",
    "permissionDecision": "allow",
    "updatedInput": {
      "questions": [
        {
          "question": "Which framework?",
          "header": "Framework",
          "options": [{"label": "React", "description": "Component library"}, {"label": "Vue", "description": "Progressive framework"}],
          "multiSelect": false
        }
      ],
      "answers": {"Which framework?": "React"}
    }
  }
}
```

Ein MCP-Tool, das sein Server mit [`_meta["anthropic/requiresUserInteraction"]`](/docs/de/mcp#require-approval-for-a-specific-tool) kennzeichnet, ist strenger: Ein Hook kann dessen Genehmigungsabfrage mit `"allow"` nicht überspringen, weder mit noch ohne `updatedInput`, da Claude Code nicht bestätigen kann, dass der Hook die vom Tool benötigte Interaktion erfasst hat.

<h4 id="defer-a-tool-call-for-later">
  Einen Tool-Aufruf für später zurückstellen
</h4>

`"defer"` ist für Integrationen gedacht, die `claude -p` als Subprozess ausführen und dessen JSON-Ausgabe lesen, etwa eine Agent SDK-App oder eine auf Claude Code aufbauende benutzerdefinierte Oberfläche. Damit kann der aufrufende Prozess Claude bei einem Tool-Aufruf anhalten, Eingaben über seine eigene Oberfläche erfassen und dort weitermachen, wo er aufgehört hat. Claude Code berücksichtigt diesen Wert nur im [nicht interaktiven Modus](/docs/de/headless) mit dem Flag `-p`. In interaktiven Sitzungen protokolliert es eine Warnung und ignoriert das Hook-Ergebnis.

Das Tool `AskUserQuestion` ist der typische Fall: Claude möchte dem Benutzer eine Frage stellen, aber es gibt kein Terminal, in dem geantwortet werden kann. Ein `-p`-Lauf bietet `AskUserQuestion` nur an, wenn er einen [Berechtigungs-Host](/docs/de/headless#turn-off-permission-prompts-in-unattended-runs) hat, etwa ein MCP-Tool, das Sie mit `--permission-prompt-tool` übergeben. Starten Sie den Lauf daher mit einem solchen. Der Ablauf funktioniert so:

1. Claude ruft `AskUserQuestion` auf. Der `PreToolUse`-Hook wird ausgelöst.
2. Der Hook gibt `permissionDecision: "defer"` zurück. Das Tool wird nicht ausgeführt. Der Prozess wird mit `stop_reason: "tool_deferred"` beendet, und der ausstehende Tool-Aufruf bleibt im Transkript erhalten.
3. Der aufrufende Prozess liest `deferred_tool_use` aus dem SDK-Ergebnis, zeigt die Frage in seiner eigenen Oberfläche an und wartet auf eine Antwort.
4. Der aufrufende Prozess führt `claude -p --resume <session-id>` mit demselben Berechtigungs-Host aus. Derselbe Tool-Aufruf löst `PreToolUse` erneut aus.
5. Der Hook gibt `permissionDecision: "allow"` mit der Antwort in `updatedInput` zurück. Das Tool wird ausgeführt, und Claude fährt fort.

Das Feld `deferred_tool_use` enthält `id`, `name` und `input` des Tools. `input` sind die Parameter, die Claude für den Tool-Aufruf erzeugt hat, erfasst vor der Ausführung:

```json theme={null}
{
  "type": "result",
  "subtype": "success",
  "stop_reason": "tool_deferred",
  "session_id": "abc123",
  "deferred_tool_use": {
    "id": "toolu_01abc",
    "name": "AskUserQuestion",
    "input": { "questions": [{ "question": "Which framework?", "header": "Framework", "options": [{"label": "React", "description": "Component library"}, {"label": "Vue", "description": "Progressive framework"}], "multiSelect": false }] }
  }
}
```

Es gibt weder einen Timeout noch ein Limit für Wiederholungsversuche. Die Sitzung bleibt auf der Festplatte, bis Sie sie fortsetzen, vorbehaltlich der Aufbewahrungsbereinigung durch [`cleanupPeriodDays`](/docs/de/settings-reference#cleanupperioddays), die Sitzungsdateien standardmäßig nach 30 Tagen löscht, gemäß den [Regeln der Aufbewahrungsbereinigung](/docs/de/claude-directory#cleaned-up-automatically). Wenn die Antwort beim Fortsetzen noch nicht bereit ist, kann der Hook erneut `"defer"` zurückgeben, und der Prozess wird auf dieselbe Weise beendet. Der aufrufende Prozess bestimmt, wann die Schleife endet, indem er schließlich `"allow"` oder `"deny"` aus dem Hook zurückgibt.

`"defer"` funktioniert nur, wenn Claude im Turn einen einzigen Tool-Aufruf durchführt. Wenn Claude mehrere Tool-Aufrufe gleichzeitig durchführt, wird `"defer"` mit einer Warnung ignoriert, und das Tool durchläuft den normalen Berechtigungsablauf. Diese Einschränkung besteht, weil beim Fortsetzen nur ein Tool erneut ausgeführt werden kann: Es gibt keine Möglichkeit, einen Aufruf aus einem Stapel zurückzustellen, ohne die anderen ungeklärt zu lassen.

Wenn das zurückgestellte Tool beim Fortsetzen nicht mehr verfügbar ist, wird der Prozess mit `stop_reason: "tool_deferred_unavailable"` und `is_error: true` beendet, bevor der Hook ausgelöst wird. Das passiert, wenn ein MCP-Server, der das Tool bereitgestellt hat, für die fortgesetzte Sitzung nicht verbunden ist. Die Payload `deferred_tool_use` ist trotzdem enthalten, sodass Sie erkennen können, welches Tool fehlt.

<Note>
  Um eine zurückgestellte Sitzung im Plan-Modus fortzusetzen, übergeben Sie [`--permission-prompt-tool`](/docs/de/cli-reference#cli-flags) zusammen mit `--resume`, damit Claude Code den Plan zur Genehmigung vorlegen kann. Wenn Sie bestimmte andere Start-Flags übergeben, kehrt der fortgesetzte Lauf nicht in den Plan-Modus zurück; siehe [Im Plan-Modus mit `-p` fortsetzen](/docs/de/sessions#resume-in-plan-mode-with-p). Erfordert Claude Code v2.1.246 oder höher.

  Wenn Sie mit `-p` fortsetzen, stellt Claude Code keinen anderen gespeicherten Berechtigungsmodus wieder her. Es startet den Lauf in dem Berechtigungsmodus, in dem ein neuer `claude -p`-Lauf starten würde. Übergeben Sie daher `--permission-mode` oder `--dangerously-skip-permissions` erneut, wenn die zurückgestellte Sitzung eines davon verwendet hat. Wenn Sie mit `claude --resume <session-id>` ohne `-p` fortsetzen, stellt Claude Code den gespeicherten Berechtigungsmodus wieder her, mit den unter [Berechtigungsmodus beim Fortsetzen](/docs/de/sessions#permission-mode-on-resume) aufgeführten Ausnahmen.
</Note>

<h3 id="permissionrequest">
  PermissionRequest
</h3>

Wird ausgeführt, wenn Claude Code Sie gleich um Erlaubnis zur Verwendung eines Tools bitten wird. In Sitzungen, die keine Abfrage anzeigen können, etwa bei Subagenten im Hintergrund im [nicht interaktiven Modus](/docs/de/headless), führt Claude Code diese Hooks trotzdem aus, und wenn kein Hook eine Entscheidung zurückgibt, lehnt es den Tool-Aufruf ab. Bei einem Aufruf, der ein `--permission-prompt-tool` oder den [`canUseTool`-Callback](/docs/de/agent-sdk/permissions) des Agent SDK erreicht, laufen die Hooks parallel zu Ihrem Host, und es gilt, wer zuerst entscheidet.
Verwenden Sie die [PermissionRequest-Entscheidungssteuerung](#permissionrequest-decision-control), um im Namen des Benutzers zuzulassen oder abzulehnen.

Verwenden Sie dieses Ereignis, wenn Sie ein Signal in dem Moment benötigen, in dem Claude um Erlaubnis zur Verwendung eines Tools bittet. Claude Code führt einen [Notification](#notification)-Hook mit dem Typ `permission_prompt` erst aus, nachdem die Abfrage etwa sechs Sekunden gewartet hat.

Claude Code führt keine PermissionRequest-Hooks für die [Netzwerkanfrage](/docs/de/sandboxing#network-isolation) eines in einer Sandbox ausgeführten Befehls aus. Um für diese Abfrage ein Signal zu erhalten, verwenden Sie den Benachrichtigungstyp `permission_prompt`.

Matcht auf den Tool-Namen, mit denselben Werten wie PreToolUse.

<h4 id="permissionrequest-input">
  PermissionRequest-Eingabe
</h4>

PermissionRequest-Hooks erhalten wie PreToolUse-Hooks die Felder `tool_name` und `tool_input`, jedoch ohne `tool_use_id`. Bei einem MCP-Tool erhalten sie außerdem das Objekt [`mcp_server`](#pretooluse-input). Ein optionales Array `permission_suggestions` enthält die [Berechtigungsaktualisierungen](#permission-update-entries), die Claude Code für diese Anfrage vorschlägt, etwa das Hinzufügen einer allow-Regel oder das Ändern des Berechtigungsmodus.

Das Array `permission_suggestions` ist keine exakte Liste der angezeigten Optionen, da jeder Berechtigungsdialog seine eigenen Optionen aufbaut. Manche Dialoge, etwa der für Dateibearbeitungen, lesen das Array überhaupt nicht und leiten ihre Optionen aus der Anfrage selbst ab. Ein Dialog, der es liest, kann dennoch eine Option zurückhalten, deren Vorschlag im Array verbleibt, zum Beispiel wenn [`allowManagedPermissionRulesOnly`](/docs/de/settings-reference#allowmanagedpermissionrulesonly) Optionen zum Speichern von Regeln ausblendet. Er kann auch Optionen anbieten, für die es keinen Vorschlagseintrag gibt, etwa [**Yes, and switch to auto mode**](/docs/de/permission-modes#switch-permission-modes), das den Berechtigungsmodus direkt ändert statt über eine Berechtigungsaktualisierung.

PreToolUse-Hooks werden vor jedem Tool-Aufruf ausgeführt, unabhängig davon, ob er eine Berechtigung benötigt. PermissionRequest-Hooks werden nur ausgeführt, wenn Claude Code Sie gleich um Erlaubnis bitten wird oder wenn es andernfalls einen Aufruf, der keine Abfrage anzeigen kann, automatisch ablehnen würde. Keines der beiden Ereignisse wird für [`EndConversation`](/docs/de/tools-reference#endconversation-tool-behavior) ausgelöst.

```json theme={null}
{
  "session_id": "abc123",
  "transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",
  "cwd": "/Users/...",
  "permission_mode": "default",
  "hook_event_name": "PermissionRequest",
  "tool_name": "Bash",
  "tool_input": {
    "command": "rm -rf node_modules",
    "description": "Remove node_modules directory"
  },
  "permission_suggestions": [
    {
      "type": "addRules",
      "rules": [{ "toolName": "Bash", "ruleContent": "rm -rf node_modules" }],
      "behavior": "allow",
      "destination": "localSettings"
    }
  ]
}
```

<h4 id="permissionrequest-decision-control">
  PermissionRequest-Entscheidungssteuerung
</h4>

`PermissionRequest`-Hooks können Berechtigungsanfragen zulassen oder ablehnen. Zusätzlich zu den [JSON-Ausgabefeldern](#json-output), die allen Hooks zur Verfügung stehen, kann Ihr Hook-Skript ein `decision`-Objekt mit diesen ereignisspezifischen Feldern zurückgeben:

| Feld | Beschreibung |
| :- | :- |
| `behavior` | `"allow"` erteilt die Berechtigung, `"deny"` lehnt sie ab. [Deny- und ask-Regeln](/docs/de/permissions#manage-permissions) werden weiterhin ausgewertet, sodass ein Hook, der `"allow"` zurückgibt, eine passende deny-Regel nicht überschreibt |
| `updatedInput` | Nur für `"allow"`: ändert die Eingabeparameter des Tools vor der Ausführung. Ersetzt das gesamte Eingabeobjekt, nehmen Sie daher unveränderte Felder zusammen mit den geänderten auf. Die geänderte Eingabe wird erneut gegen deny- und ask-Regeln ausgewertet |
| `updatedPermissions` | Nur für `"allow"`: Array von anzuwendenden [Einträgen für Berechtigungsaktualisierungen](#permission-update-entries), etwa zum Hinzufügen einer allow-Regel oder zum Ändern des Berechtigungsmodus der Sitzung |
| `message` | Nur für `"deny"`: teilt Claude mit, warum die Berechtigung abgelehnt wurde |
| `interrupt` | Nur für `"deny"`: bei `true` wird Claude gestoppt |

Ein Hook, der ohne `decision`-Objekt mit 2 beendet wird, lässt den Berechtigungsablauf unverändert, und sein stderr wird verworfen. Nur das `decision`-Objekt kann die Anfrage genehmigen oder ablehnen.

```json theme={null}
{
  "hookSpecificOutput": {
    "hookEventName": "PermissionRequest",
    "decision": {
      "behavior": "allow",
      "updatedInput": {
        "command": "npm run lint"
      }
    }
  }
}
```

<h4 id="permission-update-entries">
  Einträge für Berechtigungsaktualisierungen
</h4>

Das Ausgabefeld `updatedPermissions` und das [Eingabefeld `permission_suggestions`](#permissionrequest-input) verwenden beide dasselbe Array von Eintragsobjekten. Jeder Eintrag hat einen `type`, der seine übrigen Felder bestimmt, und eine `destination`, die steuert, wohin die Änderung geschrieben wird.

| `type` | Felder | Wirkung |
| :- | :- | :- |
| `addRules` | `rules`, `behavior`, `destination` | Fügt Berechtigungsregeln hinzu. `rules` ist ein Array von `{toolName, ruleContent?}`-Objekten. Lassen Sie `ruleContent` weg, um das gesamte Tool zu matchen. `behavior` ist `"allow"`, `"deny"` oder `"ask"` |
| `replaceRules` | `rules`, `behavior`, `destination` | Ersetzt alle Regeln des angegebenen `behavior` in der `destination` durch die bereitgestellten `rules` |
| `removeRules` | `rules`, `behavior`, `destination` | Entfernt passende Regeln des angegebenen `behavior` |
| `setMode` | `mode`, `destination` | Ändert den Berechtigungsmodus. Gültige Modi sind `default`, `auto`, `acceptEdits`, `dontAsk`, `bypassPermissions`, `plan` sowie `manual` als Alias für `default` |
| `addDirectories` | `directories`, `destination` | Fügt Arbeitsverzeichnisse hinzu. `directories` ist ein Array von Pfadzeichenketten |
| `removeDirectories` | `directories`, `destination` | Entfernt Arbeitsverzeichnisse |

<Note>
  `setMode` mit `bypassPermissions` wird nur wirksam, wenn Sie die Sitzung mit bereits verfügbarem Bypass-Modus gestartet haben: `--dangerously-skip-permissions`, `--permission-mode bypassPermissions`, `--allow-dangerously-skip-permissions` oder `permissions.defaultMode: "bypassPermissions"` in [Benutzereinstellungen, `--settings` oder verwalteten Einstellungen](/docs/de/settings-reference#permissions-defaultmode). Andernfalls hat die Aktualisierung keine Wirkung. Die Aktualisierung hat ebenfalls keine Wirkung, wenn [`permissions.disableBypassPermissionsMode`](/docs/de/permissions#managed-settings) den Modus deaktiviert oder wenn die Sitzung im [eingeschränkten Modus](/docs/de/cli-reference#cli-flags) startet.

  `bypassPermissions` wird unabhängig von `destination` niemals als `defaultMode` gespeichert.
</Note>

Das Feld `destination` jedes Eintrags bestimmt, ob die Änderung nur im Arbeitsspeicher bleibt oder in eine Einstellungsdatei geschrieben wird.

| `destination` | Schreibt in |
| :- | :- |
| `session` | nur im Arbeitsspeicher, wird beim Ende der Sitzung verworfen |
| `localSettings` | `.claude/settings.local.json` |
| `projectSettings` | `.claude/settings.json` |
| `userSettings` | `~/.claude/settings.json` |

Ein Hook kann einen der empfangenen `permission_suggestions` als eigene `updatedPermissions`-Ausgabe zurückgeben.

<h3 id="posttooluse">
  PostToolUse
</h3>

Wird unmittelbar ausgeführt, nachdem ein Tool erfolgreich abgeschlossen wurde.

Matcht auf den Tool-Namen, mit denselben Werten wie PreToolUse.

Matchen Sie breiter, wenn der Tool-Name nicht der richtige Filter ist:

* Um einen Hook nach jedem erfolgreich abgeschlossenen Tool auszuführen, lassen Sie den `matcher` weg oder setzen Sie ihn auf `"*"`. Ihr Hook kann dann selbst ermitteln, was sich geändert hat, beispielsweise durch Ausführen von `git status --porcelain`, das auch nicht verfolgte Dateien auflistet, die `git diff` übersieht. Für fehlgeschlagene Tool-Aufrufe fügen Sie denselben Hook unter [PostToolUseFailure](#posttoolusefailure) hinzu.
* Um einen Hook auszuführen, wenn sich eine bestimmte Datei auf der Festplatte ändert, unabhängig davon, wer sie geschrieben hat, verwenden Sie [FileChanged](#filechanged). Claude Code führt keinen `PostToolUse`-Hook mit dem Matcher `Edit|Write` aus, wenn ein `Bash`-Befehl oder ein Prozess außerhalb von Claude Code dieselbe Datei neu schreibt.

<h4 id="posttooluse-input">
  PostToolUse-Eingabe
</h4>

`PostToolUse`-Hooks werden ausgelöst, nachdem ein Tool bereits erfolgreich ausgeführt wurde. Die Eingabe enthält sowohl `tool_input`, die an das Tool gesendeten Argumente, als auch `tool_response`, das vom Tool zurückgegebene Ergebnis. Das genaue Schema beider Felder hängt vom Tool ab. Pfade in `tool_input` von Datei-Tools kommen im selben Format wie bei [PreToolUse](#pretooluse-input) an: immer absolut, mit den nativen Trennzeichen der Plattform, unter Windows also mit Backslashes. Bei einem MCP-Tool enthält die Eingabe außerdem das Objekt [`mcp_server`](#pretooluse-input).

```json theme={null}
{
  "session_id": "abc123",
  "transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",
  "cwd": "/Users/...",
  "permission_mode": "default",
  "hook_event_name": "PostToolUse",
  "tool_name": "Write",
  "tool_input": {
    "file_path": "/path/to/file.txt",
    "content": "file content"
  },
  "tool_response": {
    "filePath": "/path/to/file.txt",
    "type": "create"
  },
  "tool_use_id": "toolu_01ABC123...",
  "duration_ms": 12
}
```

| Feld | Beschreibung |
| :- | :- |
| `duration_ms` | Optional. Ausführungszeit des Tools in Millisekunden. Schließt die Zeit in Berechtigungsabfragen und PreToolUse-Hooks aus |

<h4 id="posttooluse-decision-control">
  PostToolUse-Entscheidungssteuerung
</h4>

`PostToolUse`-Hooks können Claude nach der Tool-Ausführung Feedback geben. Zusätzlich zu den [JSON-Ausgabefeldern](#json-output), die allen Hooks zur Verfügung stehen, kann Ihr Hook-Skript diese ereignisspezifischen Felder zurückgeben:

| Feld | Beschreibung |
| :- | :- |
| `decision` | `"block"` fügt den `reason` neben dem Tool-Ergebnis hinzu. Claude sieht weiterhin die ursprüngliche Ausgabe; um sie zu ersetzen, verwenden Sie `updatedToolOutput` |
| `reason` | Erklärung, die Claude angezeigt wird, wenn `decision` den Wert `"block"` hat |
| `additionalContext` | Zeichenfolge, die Claudes Kontext zusammen mit dem Tool-Ergebnis hinzugefügt wird. Siehe [Kontext für Claude hinzufügen](#add-context-for-claude) |
| `classifierContext` | Kurze Notiz zum Ergebnis dieses Aufrufs, die für den Klassifikator des [Auto-Modus](/docs/de/permission-modes#eliminate-prompts-with-auto-mode) statt für Claude bestimmt ist. Siehe [Ein Ergebnis für den Klassifikator des Auto-Modus annotieren](#annotate-a-result-for-the-auto-mode-classifier). Erfordert Claude Code v2.1.236 oder höher |
| `updatedToolOutput` | Ersetzt die Ausgabe des Tools durch den angegebenen Wert, bevor sie an Claude gesendet wird. Der Wert muss der Ausgabestruktur des Tools entsprechen |
| `updatedMCPToolOutput` | Ersetzt die Ausgabe nur für [MCP-Tools](#match-mcp-tools). Verwenden Sie vorzugsweise `updatedToolOutput`, das für alle Tools funktioniert |

Das folgende Beispiel ersetzt die Ausgabe eines `Bash`-Aufrufs. Der Ersatzwert entspricht der Ausgabestruktur des `Bash`-Tools:

```json theme={null}
{
  "hookSpecificOutput": {
    "hookEventName": "PostToolUse",
    "additionalContext": "Additional information for Claude",
    "updatedToolOutput": {
      "stdout": "[redacted]",
      "stderr": "",
      "interrupted": false,
      "isImage": false
    }
  }
}
```

<Warning>
  `updatedToolOutput` ändert nur, was Claude sieht. Das Tool wurde bereits ausgeführt, wenn der Hook ausgelöst wird, sodass geschriebene Dateien, ausgeführte Befehle oder gesendete Netzwerkanfragen bereits wirksam sind. Telemetrie wie OpenTelemetry-Tool-Spans und Analyseereignisse erfasst ebenfalls die ursprüngliche Ausgabe, bevor der Hook ausgeführt wird. Um einen Tool-Aufruf vor seiner Ausführung zu verhindern oder zu ändern, verwenden Sie stattdessen einen [PreToolUse](#pretooluse)-Hook.

  Der Ersatzwert muss der Ausgabestruktur des Tools entsprechen. Integrierte Tools geben strukturierte Objekte statt einfacher Zeichenfolgen zurück. Beispielsweise gibt `Bash` ein Objekt mit den Feldern `stdout`, `stderr`, `interrupted` und `isImage` zurück. Bei integrierten Tools wird ein Wert, der nicht dem Ausgabeschema des Tools entspricht, ignoriert und die ursprüngliche Ausgabe verwendet. Die Ausgabe von MCP-Tools wird ohne Schemavalidierung durchgereicht. Das Entfernen von Fehlerdetails, die Claude benötigt, kann dazu führen, dass Claude auf Basis einer falschen Annahme weiterarbeitet.
</Warning>

<h4 id="annotate-a-result-for-the-auto-mode-classifier">
  Ein Ergebnis für den Klassifikator des Auto-Modus annotieren
</h4>

Geben Sie `classifierContext` zurück, um eine kurze Notiz zum Ergebnis des Tool-Aufrufs an den Klassifikator des [Auto-Modus](/docs/de/permission-modes#eliminate-prompts-with-auto-mode) statt an Claude zu senden. Der Klassifikator [erhält niemals die Tool-Ergebnisse selbst](/docs/de/permission-modes#how-the-classifier-evaluates-actions), daher ist dieses Feld der unterstützte Weg, ihm etwas darüber mitzuteilen, was ein Aufruf zurückgegeben hat, bevor er spätere Aktionen prüft. Das Feld erfordert Claude Code v2.1.236 oder höher.

Das folgende Beispiel teilt dem Klassifikator mit, woher die Ausgabe einer Abfrage stammt:

```json theme={null}
{
  "hookSpecificOutput": {
    "hookEventName": "PostToolUse",
    "classifierContext": "This query ran against the staging database, not production."
  }
}
```

Wie stark der Klassifikator die Notiz gewichtet, hängt davon ab, wo Sie den Hook konfiguriert haben:

* **In Claude Code konfigurierte Hooks**: Bei Hooks aus Einstellungsdateien, Plugins, Skills und Agenten-Frontmatter behandelt der Klassifikator die Notiz als nicht verifizierten, von der Anwendung bereitgestellten Kontext. Die Notiz begründet niemals eine Benutzerabsicht, und wenn sie behauptet, Sie hätten etwas genehmigt oder angefordert, prüft der Klassifikator diese Behauptung anhand Ihrer eigenen Nachrichten in der Konversation
* **In-Process-Callbacks des Agent SDK**: Wenn eine Anwendung, die Claude Code einbettet, den Hook als [TypeScript-SDK-Callback](/docs/de/agent-sdk/hooks) registriert und die Notiz während der laufenden Sitzung zurückgibt, kann der Klassifikator eine in der Notiz weitergegebene Benutzeraussage als Benutzerabsicht werten. Eine solche Aussage kann eine Zustimmungsanforderung erfüllen, die der Klassifikator auch von einer von Ihnen gesendeten Nachricht akzeptieren würde, hebt aber niemals eine Blockierung auf, die auch Ihre eigene Nachricht nicht aufheben könnte. Nach dem Fortsetzen einer Sitzung behandelt Claude Code wiederhergestellte Notizen als nicht verifizierten Kontext. Wenn Hooks aus beiden Gruppen denselben Aufruf annotieren, behandelt der Klassifikator die kombinierte Notiz als nicht verifiziert

Claude Code wendet beim Zustellen der Notiz diese Grenzen an:

* **Länge**: Claude Code begrenzt die Notizen für einen Tool-Aufruf auf 2.000 Zeichen und schneidet den Rest ab. Die Grenze gilt gemeinsam für alle Hooks, die auf diesen Aufruf antworten
* **Nur synchrone Antworten**: Claude Code ignoriert das Feld in der Antwort eines Hooks, der [im Hintergrund ausgeführt wird](#run-hooks-in-the-background), da diese Antwort eintrifft, nachdem Claude Code das Tool-Ergebnis aufgezeichnet hat
* **Aufrufe, die der Klassifikator nicht aufzeichnet**: Das Transkript des Klassifikators lässt nur lesende Abfragen wie Dateilesevorgänge und Suchen aus. Claude Code verwirft eine Notiz, die an einen dieser Aufrufe angehängt ist
* **Zusammenspiel mit Umschreibungen**: Wenn die Notiz eine Ausgabe beschreibt, die Sie mit `updatedToolOutput` ersetzen, geben Sie beide Felder in derselben Hook-Antwort zurück. Claude Code verwirft die Notiz, wenn diese Umschreibung abgelehnt wird oder die Umschreibung eines anderen Hooks sie ersetzt. Eine Notiz, die Sie ohne Umschreibung zurückgeben, stellt Claude Code auch dann zu, wenn ein anderer Hook die Ausgabe umschreibt

<Warning>
  Der Klassifikator liest Inhalte, die Sie in `classifierContext` ablegen, als Informationen der Anwendung, die die Sitzung hostet. Kopieren Sie daher keine nicht vertrauenswürdige Tool-Ausgabe oder Texte von Drittanbietern hinein. Beschränken Sie die Notiz auf eine kurze Aussage zu diesem einen Aufruf, etwa eine Tatsache über seine Herkunft oder eine Benutzeraussage dazu; verwenden Sie das Feld nicht, um unzusammenhängende Nachrichten oder einen Strom von Ereignissen zu übermitteln.
</Warning>

<h3 id="posttoolusefailure">
  PostToolUseFailure
</h3>

Wird ausgeführt, wenn ein Tool, dessen Ausführung begonnen hat, fehlschlägt: Das Tool hat einen Fehler ausgelöst, oder ein MCP-Tool hat ein Fehlerergebnis zurückgegeben. Verwenden Sie dies, um Fehler zu protokollieren, Warnungen zu senden oder Claude korrigierendes Feedback zu geben.

Matcht auf den Tool-Namen, mit denselben Werten wie PreToolUse.

<Note>
  Dieses Ereignis wird nicht für Tool-Aufrufe ausgelöst, die vor der Ausführung abgelehnt werden: ein unbekannter Tool-Name, eine Eingabe, die die Schema- oder tool-spezifische Validierung nicht besteht, oder eine verweigerte Berechtigung. Validierungsablehnungen werden als `tool_use_error`-Ergebnisse zurückgegeben und erfolgen, bevor Hooks ausgeführt werden, sodass sie weder `PreToolUse` noch `PostToolUseFailure` auslösen. Verweigerte Berechtigungen lösen `PreToolUse` aus, nicht aber dieses Ereignis; siehe [PermissionDenied](#permissiondenied).
</Note>

<h4 id="posttoolusefailure-input">
  PostToolUseFailure-Eingabe
</h4>

PostToolUseFailure-Hooks erhalten dieselben Felder `tool_name` und `tool_input` wie PostToolUse, zusammen mit Fehlerinformationen als Felder der obersten Ebene. Bei einem MCP-Tool erhalten sie außerdem das Objekt [`mcp_server`](#pretooluse-input). Ein fehlgeschlagener `npm test`-Befehl könnte beispielsweise Folgendes liefern:

```json theme={null}
{
  "session_id": "abc123",
  "transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",
  "cwd": "/Users/...",
  "permission_mode": "default",
  "hook_event_name": "PostToolUseFailure",
  "tool_name": "Bash",
  "tool_input": {
    "command": "npm test",
    "description": "Run test suite"
  },
  "tool_use_id": "toolu_01ABC123...",
  "error": "Exit code 1\nError: Cannot find module 'express'",
  "is_interrupt": false,
  "duration_ms": 4187
}
```

| Feld | Beschreibung |
| :- | :- |
| `error` | Zeichenfolge, die beschreibt, was schiefgelaufen ist. Das Format hängt vom fehlgeschlagenen Tool ab |
| `is_interrupt` | Optionaler Boolean. True, wenn der Fehler Claude Code als Abbruch erreicht hat und nicht als vom Tool gemeldeter Fehler. Das Abbrechen eines laufenden Tools löst diesen Hook nicht aus; stattdessen enthält das Tool-Ergebnis die Unterbrechungsmeldung |
| `duration_ms` | Optional. Ausführungszeit des Tools in Millisekunden. Schließt die Zeit in Berechtigungsabfragen und PreToolUse-Hooks aus |

Die Zeichenfolge `error` ist im Allgemeinen derselbe Text, den Claude als Ergebnis des fehlgeschlagenen Tools erhält. Ihr Format variiert je nach Tool und Fehler. Richten Sie Ihren Hook an `tool_name`, `is_interrupt` und der ersten Zeile `Exit code N` aus; behandeln Sie den Rest der Zeichenfolge als Anzeigetext, nicht als stabiles Format.

* Bei Bash und PowerShell erzeugt ein Befehl, der ausgeführt und beendet wurde, eine erste Zeile `Exit code N`, gefolgt von der gesamten Ausgabe des Befehls als ein Block, in dem stdout und stderr verschachtelt sind
* Eine Payload kann auch eine reine Fehlermeldung ohne Exit-Code-Zeile enthalten, wenn Claude Code den Shell-Prozess selbst nicht starten konnte
* Claude Code kürzt lange Zeichenfolgen in der Mitte um eine Markierung `... [N characters truncated] ...` und kann eigene Zeilen einfügen, etwa `Command timed out after 2m 0s`

<h4 id="posttoolusefailure-decision-control">
  PostToolUseFailure-Entscheidungssteuerung
</h4>

`PostToolUseFailure`-Hooks können Claude nach einem Tool-Fehler Kontext liefern. Zusätzlich zu den [JSON-Ausgabefeldern](#json-output), die allen Hooks zur Verfügung stehen, kann Ihr Hook-Skript diese ereignisspezifischen Felder zurückgeben:

| Feld | Beschreibung |
| :- | :- |
| `additionalContext` | Zeichenfolge, die Claudes Kontext zusammen mit dem Fehler hinzugefügt wird. Siehe [Kontext für Claude hinzufügen](#add-context-for-claude) |

```json theme={null}
{
  "hookSpecificOutput": {
    "hookEventName": "PostToolUseFailure",
    "additionalContext": "Additional information about the failure for Claude"
  }
}
```

<h3 id="posttoolbatch">
  PostToolBatch
</h3>

Wird einmal ausgeführt, nachdem alle Tool-Aufrufe in einem Batch abgeschlossen sind, bevor Claude Code die nächste Anfrage an das Modell sendet. `PostToolUse` wird einmal pro Tool ausgelöst, was bedeutet, dass es parallel ausgelöst wird, wenn Claude parallele Tool-Aufrufe durchführt. `PostToolBatch` wird genau einmal mit dem vollständigen Batch ausgelöst und ist daher der richtige Ort, um Kontext einzufügen, der von der Gesamtheit der ausgeführten Tools abhängt und nicht von einem einzelnen Tool. Für dieses Ereignis gibt es keinen Matcher.

<h4 id="posttoolbatch-input">
  PostToolBatch-Eingabe
</h4>

Zusätzlich zu den [gemeinsamen Eingabefeldern](#common-input-fields) erhalten PostToolBatch-Hooks `tool_calls`, ein Array, das jeden Tool-Aufruf im Batch beschreibt:

```json theme={null}
{
  "session_id": "abc123",
  "transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",
  "cwd": "/Users/...",
  "permission_mode": "default",
  "hook_event_name": "PostToolBatch",
  "tool_calls": [
    {
      "tool_name": "Read",
      "tool_input": {"file_path": "/.../ledger/accounts.py"},
      "tool_use_id": "toolu_01...",
      "tool_response": "1\tfrom __future__ import annotations\n2\t..."
    },
    {
      "tool_name": "Read",
      "tool_input": {"file_path": "/.../ledger/transactions.py"},
      "tool_use_id": "toolu_02...",
      "tool_response": "1\tfrom __future__ import annotations\n2\t..."
    }
  ]
}
```

`tool_response` enthält denselben Inhalt, den das Modell im entsprechenden `tool_result`-Block erhält. Der Wert ist eine serialisierte Zeichenfolge oder ein Content-Block-Array, genau so, wie das Tool ihn ausgegeben hat. Für `Read` bedeutet das Text mit vorangestellten Zeilennummern statt des rohen Dateiinhalts. Antworten können groß sein, parsen Sie daher nur die Felder, die Sie benötigen.

<Note>
  Die Struktur von `tool_response` unterscheidet sich von der in `PostToolUse`. `PostToolUse` übergibt das strukturierte `Output`-Objekt des Tools, etwa `{filePath: "...", type: "create"}` für `Write`; `PostToolBatch` übergibt den serialisierten `tool_result`-Inhalt, den das Modell sieht.
</Note>

<h4 id="posttoolbatch-decision-control">
  PostToolBatch-Entscheidungssteuerung
</h4>

`PostToolBatch`-Hooks können Kontext für Claude einfügen. Zusätzlich zu den [JSON-Ausgabefeldern](#json-output), die allen Hooks zur Verfügung stehen, kann Ihr Hook-Skript diese ereignisspezifischen Felder zurückgeben:

| Feld | Beschreibung |
| :- | :- |
| `additionalContext` | Kontext-Zeichenfolge, die einmal vor dem nächsten Modellaufruf eingefügt wird. Siehe [Kontext für Claude hinzufügen](#add-context-for-claude) für Details zur Zustellung, zum geeigneten Inhalt und dazu, wie fortgesetzte Sitzungen frühere Werte behandeln |

```json theme={null}
{
  "hookSpecificOutput": {
    "hookEventName": "PostToolBatch",
    "additionalContext": "These files are part of the ledger module. Run pytest before marking the task complete."
  }
}
```

Die Rückgabe von `decision: "block"` oder `continue: false` stoppt die Agentenschleife vor dem nächsten Modellaufruf. Die Blockierungsmeldung stammt aus dem JSON-Feld `reason` oder `stopReason` oder bei Exit-Code 2 aus stderr. Sie sehen sie als Warnung im Transkript, und sie bleibt in der Konversation, sodass Claude sie sieht, wenn die Konversation fortgesetzt wird.

<h3 id="permissiondenied">
  PermissionDenied
</h3>

Wird ausgeführt, wenn der [Auto-Modus](/docs/de/permission-modes#eliminate-prompts-with-auto-mode) einen Tool-Aufruf ablehnt, auch wenn er ohne Urteil des Klassifikators ablehnt, weil [eine vom Auto-Modus unabhängige Sicherheitsprüfung die Anfrage des Klassifikators selbst abgelehnt hat](/docs/de/errors#auto-mode-cannot-determine-the-safety-of-an-action) oder seine Antwort nicht geparst werden konnte. Dieser Hook wird nur im Auto-Modus ausgelöst: Er wird nicht ausgeführt, wenn Sie einen Berechtigungsdialog manuell ablehnen, wenn ein `PreToolUse`-Hook einen Aufruf blockiert oder wenn eine `deny`-Regel zutrifft. Verwenden Sie ihn, um Ablehnungen zu protokollieren, die Konfiguration anzupassen oder dem Modell mitzuteilen, dass es den Tool-Aufruf erneut versuchen darf.

Matcht auf den Tool-Namen, mit denselben Werten wie PreToolUse.

<h4 id="permissiondenied-input">
  PermissionDenied-Eingabe
</h4>

Zusätzlich zu den [gemeinsamen Eingabefeldern](#common-input-fields) erhalten PermissionDenied-Hooks `tool_name`, `tool_input`, `tool_use_id` und `reason`. Bei einem MCP-Tool erhalten sie außerdem das Objekt [`mcp_server`](#pretooluse-input).

```json theme={null}
{
  "session_id": "abc123",
  "transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",
  "cwd": "/Users/...",
  "permission_mode": "auto",
  "hook_event_name": "PermissionDenied",
  "tool_name": "Bash",
  "tool_input": {
    "command": "rm -rf /tmp/build",
    "description": "Clean build directory"
  },
  "tool_use_id": "toolu_01ABC123...",
  "reason": "[Irreversible Local Destruction]"
}
```

| Feld | Beschreibung |
| :- | :- |
| `reason` | Der Ablehnungsgrund. Bei einem Urteil des Klassifikators nennt er in den meisten Sitzungen die zutreffende Regel in eckigen Klammern, etwa `[Data Exfiltration]`; siehe [Ablehnungen prüfen](/docs/de/auto-mode-config#review-denials) für die anderen Formen. Bei einer [Ablehnung ohne Urteil](#permissiondenied-decision-control) beginnt er mit `Auto mode could not evaluate this action and is blocking it for safety`. Bei einer Ablehnung, weil das Klassifikatormodell nicht verfügbar war, ist er der feste Text `Classifier unavailable` |

<h4 id="permissiondenied-decision-control">
  PermissionDenied-Entscheidungssteuerung
</h4>

PermissionDenied-Hooks können dem Modell mitteilen, dass es den abgelehnten Tool-Aufruf erneut versuchen darf. Geben Sie ein JSON-Objekt zurück, in dem `hookSpecificOutput.retry` auf `true` gesetzt ist:

```json theme={null}
{
  "hookSpecificOutput": {
    "hookEventName": "PermissionDenied",
    "retry": true
  }
}
```

Wenn `retry` den Wert `true` hat, fügt Claude Code der Konversation eine Nachricht hinzu, die dem Modell mitteilt, dass es den Tool-Aufruf erneut versuchen darf. Claude Code hebt die Ablehnung selbst nicht auf. Wenn Ihr Hook kein JSON oder `retry: false` zurückgibt, bleibt die Ablehnung bestehen und das Modell erhält die ursprüngliche Ablehnungsnachricht.

Claude Code ignoriert `retry: true`, wenn der Klassifikator [kein Urteil über die Aktion](/docs/de/errors#auto-mode-cannot-determine-the-safety-of-an-action) gefällt hat: Seine Antwort konnte nicht geparst werden, oder eine vom Auto-Modus unabhängige Sicherheitsprüfung hat die Anfrage des Klassifikators selbst abgelehnt. Bei diesen Ablehnungen teilt Claude Code dem Modell bereits in der Ablehnungsnachricht mit, ob es später erneut versuchen oder weitermachen soll.

<h3 id="notification">
  Notification
</h3>

Wird ausgeführt, wenn Claude Code Benachrichtigungen sendet. Matcht auf den Benachrichtigungstyp. Lassen Sie den Matcher weg, um Hooks für alle Benachrichtigungstypen auszuführen.

Sie erhalten diese Hook-Ereignisse auch bei deaktivierten Desktop-Benachrichtigungen: Die Einstellung `preferredNotifChannel`, einschließlich `notifications_disabled`, ändert nur, wie Sie benachrichtigt werden, nicht, ob Ihr Hook ausgeführt wird.

| Matcher | Wann er ausgelöst wird |
| :- | :- |
| `permission_prompt` | Claude benötigt Ihre Genehmigung für eine Tool-Nutzung oder die [Netzwerkanfrage](/docs/de/sandboxing#network-isolation) eines in einer Sandbox ausgeführten Befehls, und die Abfrage wartet seit etwa sechs Sekunden |
| `idle_prompt` | Claude hat vor etwa 60 Sekunden die Antwort beendet, und Sie haben seitdem nichts eingegeben |
| `auth_success` | Die Authentifizierung ist abgeschlossen |
| `elicitation_dialog` | Ein MCP-Server öffnet ein Elicitation-Formular, und Sie haben seit etwa sechs Sekunden nichts eingegeben |
| `elicitation_url_dialog` | Ein MCP-Server fordert Sie auf, eine Browser-URL zu öffnen, und Sie haben seit etwa sechs Sekunden nichts eingegeben |
| `elicitation_complete` | Ein MCP-Server meldet, dass eine [Elicitation im URL-Modus](#elicitation-input) abgeschlossen ist |
| `elicitation_response` | Eine MCP-Elicitation-Antwort wird an den Server zurückgesendet |
| `agent_needs_input` | Eine Hintergrundsitzung beginnt, auf Ihre Eingabe zu warten, während die [Agentenansicht](/docs/de/agent-view) in einem Terminal geöffnet ist. Wird auch ausgelöst, wenn eine Terminal-Sitzung Ihnen die [Frage eines Agent-Team-Teammitglieds zur Terminal-Einrichtung](/docs/de/agent-teams#choose-a-display-mode) oder den Hinweis des Auto-Modus zu [Gebühren für Klassifikatoranfragen](/docs/de/auto-mode-classifier-billing) anzeigt und Sie seit etwa sechs Sekunden nichts eingegeben haben |
| `agent_completed` | Eine Hintergrundsitzung wird beendet oder schlägt fehl. Wird nur ausgelöst, während die [Agentenansicht](/docs/de/agent-view) in einem Terminal geöffnet ist |
| `quota_auto_resume_fired` | Claude Code setzt Ihre Aufgabe fort, nachdem ein claude.ai-Nutzungslimit sie pausiert hat: beim Zurücksetzen oder früher, wenn etwas, das Sie während der Wartezeit in Claude Code tun, etwa das Hinzufügen von Nutzungsguthaben, ein Upgrade Ihres Plans oder ein Modellwechsel, die Nutzung wieder verfügbar macht, mit der [Ausnahme für die Modelleinstellung](/docs/de/interactive-mode#wait-for-a-usage-limit-to-reset) |
| `quota_auto_resume_stale` | Ein claude.ai-Nutzungslimit wurde zurückgesetzt, während Ihr Computer länger als etwa 30 Minuten im Ruhezustand war. Claude Code wartet, bis Sie `Enter` drücken, anstatt fortzufahren. Nach einem kürzeren Ruhezustand fährt es fort und löst stattdessen `quota_auto_resume_fired` aus |
| `quota_auto_resume_disabled` | Claude Code beendet seine Wartezeit auf ein claude.ai-Nutzungslimit, ohne Ihre Aufgabe fortzusetzen: [`autoContinueAtUsageLimit`](/docs/de/settings-reference#autocontinueatusagelimit) wurde ausgeschaltet oder das Zurücksetzen wurde während einer Wartezeit, die Claude Code selbst begonnen hat, um mehr als 24 Stunden verschoben, die fortgesetzte Aufgabe stieß wiederholt an das Limit, oder die Fortsetzung wurde blockiert, bevor sie das Modell erreichte. Wird nicht ausgelöst, wenn Sie `Esc` oder `Ctrl+C` drücken oder **Don't continue automatically** wählen |

Die Typen `quota_auto_resume_fired`, `quota_auto_resume_stale` und `quota_auto_resume_disabled` erfordern Claude Code v2.1.234 oder höher.

In Terminal-Sitzungen erfordert `permission_prompt` für die Netzwerkanfrage eines in einer Sandbox ausgeführten Befehls Claude Code v2.1.246 oder höher.

`agent_needs_input` für die Frage eines Teammitglieds zur Terminal-Einrichtung erfordert Claude Code v2.1.248 oder höher.

<Note>
  Die Typen `permission_prompt`, `idle_prompt`, `elicitation_dialog` und `elicitation_url_dialog` teilen ihr Timing mit Desktop-Benachrichtigungen, sodass Sie sie in Terminal-Sitzungen nur sehen, wenn Sie scheinbar nicht am Terminal sind:

  * Rechnen Sie mit `permission_prompt`, sobald Sie etwa sechs Sekunden lang nichts eingegeben haben. Der Timer startet, wenn die Berechtigungsabfrage erscheint, und jeder Tastendruck verzögert ihn. Um einen Hook sofort auszuführen, wenn Claude um Erlaubnis zur Nutzung eines Tools bittet, verwenden Sie stattdessen [PermissionRequest](#permissionrequest).
  * Rechnen Sie mit `idle_prompt` etwa 60 Sekunden, nachdem Claude die Antwort beendet hat, und nur, wenn Sie seitdem nichts eingegeben haben und kein Hintergrundagent, etwa ein [Subagent](/docs/de/sub-agents) im Hintergrund, noch läuft. Claude Code sendet `idle_prompt` nicht, während es auf das Zurücksetzen eines claude.ai-Nutzungslimits wartet. Wenn die Wartezeit von selbst endet, wird stattdessen einer der Typen `quota_auto_resume_*` ausgelöst.
  * Rechnen Sie mit `elicitation_dialog` für ein Elicitation-Formular oder `elicitation_url_dialog` für eine Browser-URL-Anfrage, sobald Sie etwa sechs Sekunden lang nichts eingegeben haben. Beide teilen dieselbe Sechs-Sekunden-Schwelle wie `permission_prompt`: Der Timer startet, wenn der Dialog erscheint, und jeder Tastendruck verzögert ihn.

  Eine Berechtigungsanfrage oder Elicitation, die eintrifft, während ein anderer Dialog angezeigt wird, behält dieselbe Sechs-Sekunden-Schwelle, gemessen ab dem Eintreffen der Anfrage. Ihre Benachrichtigung kann Sie erreichen, während die Anfrage noch hinter dem geöffneten Dialog wartet.
</Note>

Claude Code steuert das Timing von `permission_prompt` anders in Sitzungen, in denen es Berechtigungsanfragen an den [`canUseTool`-Callback](/docs/de/agent-sdk/user-input) des Agent SDK sendet. Auf diese Weise hosten Claude Desktop und die VS Code-Erweiterung Claude Code:

* Rechnen Sie mit `permission_prompt` etwa sechs Sekunden, nachdem Claude um Erlaubnis bittet. Claude Code verzögert es nicht, während Sie tippen.
* Wenn Sie oder ein [PermissionRequest](#permissionrequest)-Hook früher antworten, führt Claude Code `permission_prompt` nicht aus.
* Setzen Sie [`CLAUDE_CODE_DISABLE_PERMISSION_PROMPT_NOTIFY_HOOKS`](/docs/de/env-vars) auf `1`, um `permission_prompt` in diesen Sitzungen auszuschalten.

Vor v2.1.233 wurde `permission_prompt` in diesen Sitzungen nicht ausgelöst.

Verwenden Sie separate Matcher, um je nach Benachrichtigungstyp unterschiedliche Handler auszuführen. Diese Konfiguration löst ein berechtigungsspezifisches Warnskript aus, wenn Claude eine Berechtigungsgenehmigung benötigt, und eine andere Benachrichtigung, wenn Claude untätig war:

```json theme={null}
{
  "hooks": {
    "Notification": [
      {
        "matcher": "permission_prompt",
        "hooks": [
          {
            "type": "command",
            "command": "/path/to/permission-alert.sh"
          }
        ]
      },
      {
        "matcher": "idle_prompt",
        "hooks": [
          {
            "type": "command",
            "command": "/path/to/idle-notification.sh"
          }
        ]
      }
    ]
  }
}
```

<h4 id="notification-input">
  Notification-Eingabe
</h4>

Zusätzlich zu den [gemeinsamen Eingabefeldern](#common-input-fields) erhalten Notification-Hooks `message` mit dem Benachrichtigungstext, ein optionales `title` und `notification_type`, das angibt, welcher Typ ausgelöst wurde.

```json theme={null}
{
  "session_id": "abc123",
  "transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",
  "cwd": "/Users/...",
  "hook_event_name": "Notification",
  "message": "Claude needs your permission",
  "title": "Permission needed",
  "notification_type": "permission_prompt"
}
```

Notification-Hooks können Benachrichtigungen weder blockieren noch ändern. Claude Code verwirft ihre Felder `systemMessage` und `continue`, gibt aber weiterhin [`terminalSequence`](#emit-terminal-notifications) aus, worauf das Beispiel für Desktop-Benachrichtigungen beruht. Notification-Hooks sind für Nebeneffekte gedacht, etwa die Weiterleitung der Benachrichtigung an einen externen Dienst.

<h3 id="subagentstart">
  SubagentStart
</h3>

Wird ausgeführt, wenn Claude mit dem Agent-Tool einen Subagenten startet, wenn Claude [einen Subagenten fortsetzt](/docs/de/sub-agents#resume-subagents) und jedes Mal, wenn ein In-Process-Teammitglied eines [Agent-Teams](/docs/de/agent-teams) eine neue Nachricht verarbeitet. Unterstützt Matcher zum Filtern nach dem Namen des Agententyps. Bei integrierten Agenten ist dies der Agentenname wie `general-purpose`, `Explore` oder `Plan`. Bei [benutzerdefinierten Subagenten](/docs/de/sub-agents) ist dies das Feld `name` aus dem Frontmatter des Agenten, nicht der Dateiname.

Bei Subagenten, die von einem [Plugin](/docs/de/plugins/overview) bereitgestellt werden, ist der Agententyp der plugin-bezogene Bezeichner wie `my-plugin:reviewer`, nicht der reine Frontmatter-Name. Der Doppelpunkt führt dazu, dass ein plugin-bezogener Name als regulärer Ausdruck ausgewertet wird. Verankern Sie den Matcher daher für eine exakte Übereinstimmung mit `^` und `$`: `^my-plugin:reviewer$`.

<h4 id="subagentstart-input">
  SubagentStart-Eingabe
</h4>

Zusätzlich zu den [gemeinsamen Eingabefeldern](#common-input-fields) erhalten SubagentStart-Hooks `agent_id` mit dem eindeutigen Bezeichner des Subagenten und `agent_type` mit dem Agentennamen, auf den der Matcher filtert.

```json theme={null}
{
  "session_id": "abc123",
  "transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",
  "cwd": "/Users/...",
  "hook_event_name": "SubagentStart",
  "agent_id": "agent-abc123",
  "agent_type": "Explore"
}
```

SubagentStart-Hooks können die Erstellung eines Subagenten nicht blockieren, aber Kontext in den Subagenten einfügen. Zusätzlich zu den [JSON-Ausgabefeldern](#json-output), die allen Hooks zur Verfügung stehen, können Sie Folgendes zurückgeben:

| Feld | Beschreibung |
| :- | :- |
| `additionalContext` | Zeichenfolge, die dem Kontext des Subagenten zu Beginn seiner Konversation vor seinem ersten Prompt hinzugefügt wird. Siehe [Kontext für Claude hinzufügen](#add-context-for-claude) |

```json theme={null}
{
  "hookSpecificOutput": {
    "hookEventName": "SubagentStart",
    "additionalContext": "Follow security guidelines for this task"
  }
}
```

Wenn der Hook für denselben Subagenten erneut ausgeführt wird, fügt Claude Code den zurückgegebenen Kontext nur ein, wenn der Kontext des Subagenten die Kopie aus einem früheren Durchlauf noch nicht enthält. Die beim Start eingefügte Kopie bleibt bestehen, sodass der [Prompt-Cache](/docs/de/prompt-caching#subagents-and-the-cache) des Subagenten intakt bleibt. Nachdem die [automatische Komprimierung](/docs/de/sub-agents#auto-compaction) diese Kopie verworfen hat, fügt Claude Code den Kontext des nächsten Durchlaufs erneut ein.

<h3 id="subagentstop">
  SubagentStop
</h3>

Wird ausgeführt, wenn ein Claude Code-Subagent seine Antwort beendet hat. Matcht auf den Agententyp, mit denselben Werten wie SubagentStart.

<h4 id="subagentstop-input">
  SubagentStop-Eingabe
</h4>

Zusätzlich zu den [gemeinsamen Eingabefeldern](#common-input-fields) erhalten SubagentStop-Hooks `stop_hook_active`, `agent_id`, `agent_type`, `agent_transcript_path` und `last_assistant_message`. Das Feld `agent_type` ist der Wert, der für die Matcher-Filterung verwendet wird. `transcript_path` ist das Transkript der Hauptsitzung, während `agent_transcript_path` das eigene Transkript des Subagenten ist, das in einem verschachtelten Ordner `subagents/` gespeichert wird. Das Feld `last_assistant_message` enthält den Textinhalt der letzten Antwort des Subagenten, sodass Hooks darauf zugreifen können, ohne die Transkriptdatei zu parsen.

Nicht jedes SubagentStop-Ereignis stammt von einem Subagenten, den Claude gestartet hat. Claude Code führt für einige seiner eigenen Funktionen auch interne Agenten aus, etwa für [Prompt-Vorschläge](/docs/de/interactive-mode#prompt-suggestions) und [`/btw`-Nebenfragen](/docs/de/interactive-mode#side-questions-with-%2Fbtw), und SubagentStop wird auch ausgelöst, wenn einer davon beendet wird. Bei diesen Ereignissen ist `agent_type` der Agentenname, unter dem die Sitzung selbst läuft, etwa einer, der mit [`--agent`](/docs/de/cli-reference#cli-flags) oder der [Einstellung `agent`](/docs/de/settings-reference#agent) festgelegt wurde, und eine leere Zeichenfolge, wenn die Sitzung ohne einen solchen läuft.

Ein `matcher`, der Agententypen benennt, matcht keinen leeren `agent_type`. Ein Hook, dessen Matcher weggelassen, `""` oder `"*"` ist oder ein regulärer Ausdruck ist, der eine leere Zeichenfolge matcht, wird auch für Ereignisse mit leerem `agent_type` ausgeführt.

Ab Claude Code v2.1.271 übermittelt ein Subagent, der mit dem Tool [`SubagentHandback`](/docs/de/tools-reference) läuft, seinen Bericht über dieses Tool, bevor er stoppt. Das Feld `last_assistant_message` enthält dann den abschließenden Text des Subagenten, falls vorhanden, der nicht der übermittelte Bericht ist. Der Bericht ist die `message`-Eingabe dieses Aufrufs, die ein `PreToolUse`- oder `PostToolUse`-Hook mit dem Matcher `SubagentHandback` als `tool_input.message` erhält.

SubagentStop-Hooks erhalten außerdem die Arrays `background_tasks` und `session_crons`, die unter [Stop-Eingabe](#stop-input) beschrieben sind. Beide Arrays beziehen sich auf die übergeordnete Sitzung, nicht auf den Subagenten.

```json theme={null}
{
  "session_id": "abc123",
  "transcript_path": "~/.claude/projects/.../abc123.jsonl",
  "cwd": "/Users/...",
  "permission_mode": "default",
  "hook_event_name": "SubagentStop",
  "stop_hook_active": false,
  "agent_id": "def456",
  "agent_type": "Explore",
  "agent_transcript_path": "~/.claude/projects/.../abc123/subagents/agent-def456.jsonl",
  "last_assistant_message": "Analysis complete. Found 3 potential issues...",
  "background_tasks": [],
  "session_crons": []
}
```

SubagentStop-Hooks verwenden dasselbe Format zur Entscheidungssteuerung wie [Stop-Hooks](#stop-decision-control), einschließlich `hookSpecificOutput.additionalContext` mit `hookEventName` auf `"SubagentStop"` gesetzt, für Feedback ohne Fehlercharakter, das den Subagenten weiterlaufen lässt. Die Rückgabe von `decision: "block"` mit einem `reason` lässt den Subagenten weiterlaufen und übermittelt `reason` an den Subagenten als seine nächste Anweisung. Ein Hook, der durch Exit-Code 2 blockiert, übermittelt seine stderr-Meldung auf dieselbe Weise. Um Kontext in die übergeordnete Sitzung einzufügen, nachdem ein Subagent zurückgekehrt ist, verwenden Sie stattdessen einen [`PostToolUse`](#posttooluse)-Hook für das `Agent`-Tool.

<h3 id="taskcreated">
  TaskCreated
</h3>

Wird ausgeführt, wenn eine Aufgabe über das Tool `TaskCreate` erstellt wird. Verwenden Sie dies, um Namenskonventionen durchzusetzen, Aufgabenbeschreibungen zu verlangen oder die Erstellung bestimmter Aufgaben zu verhindern. In einer [Sitzung ohne die Task-Tools](/docs/de/tools-reference#task-tool-availability) wird dieses Ereignis nicht ausgelöst.

TaskCreated-Hooks unterstützen keine Matcher und werden bei jedem Vorkommen ausgelöst.

<h4 id="taskcreated-input">
  TaskCreated-Eingabe
</h4>

Zusätzlich zu den [gemeinsamen Eingabefeldern](#common-input-fields) erhalten TaskCreated-Hooks `task_id`, `task_subject` und optional `task_description`, `teammate_name` und `team_name`.

```json theme={null}
{
  "session_id": "abc123",
  "transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",
  "cwd": "/Users/...",
  "hook_event_name": "TaskCreated",
  "task_id": "task-001",
  "task_subject": "Implement user authentication",
  "task_description": "Add login and signup endpoints",
  "teammate_name": "implementer",
  "team_name": "session-a1b2c3d4"
}
```

| Feld | Beschreibung |
| :- | :- |
| `task_id` | Bezeichner der zu erstellenden Aufgabe |
| `task_subject` | Titel der Aufgabe |
| `task_description` | Ausführliche Beschreibung der Aufgabe. Kann fehlen |
| `teammate_name` | Name des Teammitglieds, das die Aufgabe erstellt. Kann fehlen |
| `team_name` | Veraltet. Aus der Sitzung abgeleiteter Teamname; wird in einer zukünftigen Version entfernt |

<h4 id="taskcreated-decision-control">
  TaskCreated-Entscheidungssteuerung
</h4>

Ein TaskCreated-Hook kann die Erstellung auf zwei Arten blockieren. In beiden Fällen löscht Claude Code die Aufgabe und gibt Ihre Nachricht als Fehler des Tools an Claude zurück. Claude Code ignoriert `continue: false` bei diesem Ereignis, und Claude arbeitet weiter.

* **Exit-Code 2**: Claude Code gibt den stderr-Text als Nachricht zurück.
* **JSON `{"decision": "block", "reason": "..."}`**: Claude Code gibt `reason` als Nachricht zurück.

Dieses Beispiel blockiert Aufgaben, deren Betreff nicht dem erforderlichen Format entspricht:

```bash theme={null}
#!/bin/bash
INPUT=$(cat)
TASK_SUBJECT=$(echo "$INPUT" | jq -r '.task_subject')

if [[ ! "$TASK_SUBJECT" =~ ^\[TICKET-[0-9]+\] ]]; then
  echo "Task subject must start with a ticket number, e.g. '[TICKET-123] Add feature'" >&2
  exit 2
fi

exit 0
```

<h3 id="taskcompleted">
  TaskCompleted
</h3>

Wird ausgeführt, wenn eine Aufgabe als abgeschlossen markiert wird. Dies wird in zwei Situationen ausgelöst: wenn ein beliebiger Agent eine Aufgabe über das Tool TaskUpdate ausdrücklich als abgeschlossen markiert oder wenn ein Teammitglied eines [Agent-Teams](/docs/de/agent-teams) seinen Turn mit laufenden Aufgaben beendet. Verwenden Sie dies, um Abschlusskriterien wie bestandene Tests oder Lint-Prüfungen durchzusetzen, bevor eine Aufgabe geschlossen werden kann.

TaskCompleted-Hooks unterstützen keine Matcher und werden bei jedem Vorkommen ausgelöst.

<h4 id="taskcompleted-input">
  TaskCompleted-Eingabe
</h4>

Zusätzlich zu den [gemeinsamen Eingabefeldern](#common-input-fields) erhalten TaskCompleted-Hooks `task_id`, `task_subject` und optional `task_description`, `teammate_name` und `team_name`.

```json theme={null}
{
  "session_id": "abc123",
  "transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",
  "cwd": "/Users/...",
  "permission_mode": "default",
  "hook_event_name": "TaskCompleted",
  "task_id": "task-001",
  "task_subject": "Implement user authentication",
  "task_description": "Add login and signup endpoints",
  "teammate_name": "implementer",
  "team_name": "session-a1b2c3d4"
}
```

| Feld | Beschreibung |
| :- | :- |
| `task_id` | Bezeichner der abzuschließenden Aufgabe |
| `task_subject` | Titel der Aufgabe |
| `task_description` | Ausführliche Beschreibung der Aufgabe. Kann fehlen |
| `teammate_name` | Name des Teammitglieds, das die Aufgabe abschließt. Kann fehlen |
| `team_name` | Veraltet. Aus der Sitzung abgeleiteter Teamname; wird in einer zukünftigen Version entfernt |

<h4 id="taskcompleted-decision-control">
  TaskCompleted-Entscheidungssteuerung
</h4>

TaskCompleted-Hooks unterstützen zwei Möglichkeiten, den Aufgabenabschluss zu steuern:

* **Exit-Code 2**: Die Aufgabe wird nicht als abgeschlossen markiert, und die stderr-Meldung wird dem Modell als Feedback zurückgegeben.
* **JSON `{"continue": false, "stopReason": "..."}`**: Wenn ein Teammitglied, das seinen Turn beendet, das Ereignis ausgelöst hat, wird das Teammitglied vollständig gestoppt, entsprechend dem Verhalten des `Stop`-Hooks. Der `stopReason` wird dem Benutzer angezeigt. Wenn das Tool `TaskUpdate` das Ereignis ausgelöst hat, ignoriert Claude Code `continue: false`; Exit-Code 2 blockiert den Abschluss weiterhin.

Dieses Beispiel führt Tests aus und blockiert den Aufgabenabschluss, wenn sie fehlschlagen:

```bash theme={null}
#!/bin/bash
INPUT=$(cat)
TASK_SUBJECT=$(echo "$INPUT" | jq -r '.task_subject')

# Run the test suite
if ! npm test 2>&1; then
  echo "Tests not passing. Fix failing tests before completing: $TASK_SUBJECT" >&2
  exit 2
fi

exit 0
```

<h3 id="stop">
  Stop
</h3>

Wird ausgeführt, wenn der Haupt-Agent von Claude Code seine Antwort beendet hat. Wird nicht ausgeführt, wenn
das Stoppen durch eine Unterbrechung des Benutzers verursacht wurde. API-Fehler lösen
stattdessen [StopFailure](#stopfailure) aus.

<Tip>
  Der Befehl [`/goal`](/docs/de/goal) ist eine integrierte Abkürzung für einen sitzungsbezogenen, prompt-basierten Stop-Hook. Verwenden Sie ihn, wenn Claude auf eine Bedingung hinarbeiten soll, ohne dass Sie eine Hook-Konfiguration schreiben.
</Tip>

<h4 id="stop-input">
  Stop-Eingabe
</h4>

Zusätzlich zu den [allgemeinen Eingabefeldern](#common-input-fields) erhalten Stop-Hooks `stop_hook_active`, `last_assistant_message`, `background_tasks` und `session_crons`. Das Feld `stop_hook_active` ist `true`, wenn Claude Code bereits infolge eines Stop-Hooks fortfährt. Prüfen Sie diesen Wert oder verarbeiten Sie das Transkript, um zu vermeiden, dass Sie auf eine Bedingung blockieren, die sich nie auflöst.

Claude Code wendet eine Obergrenze von 8 aufeinanderfolgenden Fortsetzungen an: Nachdem Stop-Hooks den Turn achtmal hintereinander fortgesetzt haben, überschreibt Claude Code die nächste Blockierung und beendet den Turn. Die Anzahl aufeinanderfolgender Fortsetzungen wird jedes Mal zurückgesetzt, wenn Claude ein Tool aufruft. Um die Obergrenze anzuheben, setzen Sie [`CLAUDE_CODE_STOP_HOOK_BLOCK_CAP`](/docs/de/env-vars).

Das Feld `last_assistant_message` enthält den Textinhalt von Claudes letzter Antwort, sodass Hooks darauf zugreifen können, ohne die Transkriptdatei zu parsen. Für Hooks, die auf den gerade abgeschlossenen Turn reagieren, etwa Vorlese- oder Benachrichtigungs-Hooks, verwenden Sie dieses Feld, anstatt `transcript_path` zu lesen: Es ist nicht in allen Versionen garantiert, dass die Transkriptdatei zum Stop-Zeitpunkt die letzte Nachricht enthält.

Mit den Arrays `background_tasks` und `session_crons` können Hooks unterscheiden zwischen „Sitzung ist beendet“ und „Sitzung ist pausiert und wartet darauf, dass Hintergrundarbeit sie wieder aufweckt“. Beide Arrays sind vorhanden, wenn die Aufgabenregistrierung erreichbar ist, und leer, wenn nichts läuft oder geplant ist.

Jeder Eintrag in `background_tasks` beschreibt eine laufende Aufgabe und verwendet diese Felder:

| Feld | Beschreibung |
| :- | :- |
| `id` | Aufgabenbezeichner |
| `type` | Lesbare Bezeichnung des Aufgabentyps wie `shell`, `subagent`, `monitor`, `workflow`, `teammate`, `cloud session` oder `MCP task`. Jede Bezeichnung gibt an, welche Claude Code-Funktion die Aufgabe erstellt hat. Fällt bei nicht erkannten Typen auf den rohen Diskriminator zurück |
| `status` | Aktueller Aufgabenstatus |
| `description` | Freitextbeschreibung, begrenzt auf 1000 Zeichen, mit einer Markierung `… [+N chars]` in der Zeichenfolge bei Kürzung |
| `command` | Shell-Befehlszeile, begrenzt auf 1000 Zeichen. Nur bei `shell`-Aufgaben vorhanden |
| `agent_type` | Name des Subagententyps. Nur bei `subagent`-Aufgaben vorhanden |
| `server` | Name des MCP-Servers. Nur bei `monitor`- und `MCP task`-Aufgaben vorhanden |
| `tool` | Name des MCP-Tools. Nur bei `monitor`- und `MCP task`-Aufgaben vorhanden |
| `name` | Name des Workflows. Nur bei `workflow`-Aufgaben vorhanden |

Jeder Eintrag in `session_crons` beschreibt ein sitzungsbezogenes geplantes Aufwecken, das aus `CronCreate`, `ScheduleWakeup` und `/loop` stammt:

| Feld | Beschreibung |
| :- | :- |
| `id` | Bezeichner der Cron-Aufgabe |
| `schedule` | Cron-Ausdruck, zum Beispiel `0 9 * * 1-5` |
| `recurring` | `false` für einmalige Aufweckvorgänge, deren Zeitplan einen einzigen Auslösezeitpunkt codiert, `true` für Aufgaben, die bei jeder Übereinstimmung erneut ausgelöst werden |
| `prompt` | Prompt, der beim Auslösen des Cron-Jobs übermittelt wird, begrenzt auf 1000 Zeichen mit derselben Markierung `… [+N chars]` |

Dieses Beispiel zeigt eine Stop-Eingabe mit einer laufenden Shell-Aufgabe und einem wiederkehrenden Cron-Job:

```json theme={null}
{
  "session_id": "abc123",
  "transcript_path": "~/.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",
  "cwd": "/Users/...",
  "permission_mode": "default",
  "hook_event_name": "Stop",
  "stop_hook_active": true,
  "last_assistant_message": "I've completed the refactoring. Here's a summary...",
  "background_tasks": [
    {
      "id": "task-001",
      "type": "shell",
      "status": "running",
      "description": "tail logs",
      "command": "tail -f /var/log/syslog"
    }
  ],
  "session_crons": [
    {
      "id": "cron-001",
      "schedule": "0 9 * * 1-5",
      "recurring": true,
      "prompt": "check the build"
    }
  ]
}
```

<h4 id="stop-decision-control">
  Stop-Entscheidungssteuerung
</h4>

`Stop`- und `SubagentStop`-Hooks können steuern, ob Claude fortfährt. Zusätzlich zu den [JSON-Ausgabefeldern](#json-output), die allen Hooks zur Verfügung stehen, kann Ihr Hook-Skript diese ereignisspezifischen Felder zurückgeben:

| Feld | Beschreibung |
| :- | :- |
| `decision` | `"block"` verhindert, dass Claude stoppt. Weglassen, um Claude das Stoppen zu erlauben |
| `reason` | Erforderlich, wenn `decision` den Wert `"block"` hat. Teilt Claude mit, warum es fortfahren soll |
| `hookSpecificOutput.additionalContext` | Feedback für Claude ohne Fehlercharakter. Die Konversation wird fortgesetzt, damit Claude darauf reagieren kann, aber anders als bei `decision: "block"` wird es im Transkript als Hook-Feedback und nicht als Hook-Fehler angezeigt |

Ein Hook, der durch Exit-Code 2 blockiert, wird genauso weitergeleitet wie `reason`: Claude erhält die stderr-Meldung als Erklärung, warum es fortfahren soll.

```json theme={null}
{
  "decision": "block",
  "reason": "Must be provided when Claude is blocked from stopping"
}
```

Verwenden Sie `additionalContext`, wenn der Hook wie vorgesehen funktioniert und Claude Orientierung gibt, etwa „führe die Testsuite vor dem Abschluss aus“. Es hält die Konversation über dieselben Schleifenschutzmechanismen wie `decision: "block"` am Laufen, nämlich die Eingabe `stop_hook_active` und die Obergrenze von 8 aufeinanderfolgenden Fortsetzungen, aber das Transkript kennzeichnet es als `Stop hook feedback`, und es wird keine Hook-Fehlerbenachrichtigung angezeigt:

```json theme={null}
{
  "hookSpecificOutput": {
    "hookEventName": "Stop",
    "additionalContext": "Please run the test suite before finishing"
  }
}
```

<h3 id="stopfailure">
  StopFailure
</h3>

Wird anstelle von [Stop](#stop) ausgeführt, wenn der Turn aufgrund eines API-Fehlers endet. Claude Code ignoriert die Ausgabe und den Exit-Code des Hooks, abgesehen von [`terminalSequence`](#emit-terminal-notifications). Verwenden Sie dies, um Fehler zu protokollieren, Warnungen zu senden oder Wiederherstellungsmaßnahmen zu ergreifen, wenn Claude eine Antwort aufgrund von Rate-Limits, Authentifizierungsproblemen oder anderen API-Fehlern nicht abschließen kann.

<h4 id="stopfailure-input">
  StopFailure-Eingabe
</h4>

Zusätzlich zu den [gemeinsamen Eingabefeldern](#common-input-fields) erhalten StopFailure-Hooks `error`, optional `error_details` und optional `last_assistant_message`. Das Feld `error` gibt den Fehlertyp an und wird für die Matcher-Filterung verwendet.

| Feld | Beschreibung |
| :- | :- |
| `error` | Fehlertyp: `rate_limit`, `overloaded`, `authentication_failed`, `oauth_org_not_allowed`, `account_on_hold`, `billing_error`, `invalid_request`, `model_not_found`, `server_error`, `max_output_tokens`, `cloud_credential_error` oder `unknown` |
| `error_details` | Zusätzliche Details zum Fehler, sofern verfügbar |
| `last_assistant_message` | Der gerenderte Fehlertext, der in der Konversation angezeigt wird. Anders als bei `Stop` und `SubagentStop`, wo dieses Feld Claudes Konversationsausgabe enthält, enthält es bei `StopFailure` die API-Fehlerzeichenfolge selbst, etwa `"API Error: Rate limit reached"` |

```json theme={null}
{
  "session_id": "abc123",
  "transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",
  "cwd": "/Users/...",
  "hook_event_name": "StopFailure",
  "error": "rate_limit",
  "error_details": "429 Too Many Requests",
  "last_assistant_message": "API Error: Rate limit reached"
}
```

StopFailure-Hooks haben keine Entscheidungssteuerung. Sie dienen ausschließlich Benachrichtigungs- und Protokollierungszwecken.

<h3 id="teammateidle">
  TeammateIdle
</h3>

Wird ausgeführt, wenn ein Teammitglied eines [Agent-Teams](/docs/de/agent-teams) nach dem Beenden seines Turns kurz davor ist, untätig zu werden. Verwenden Sie dies, um Qualitätsschranken durchzusetzen, bevor ein Teammitglied die Arbeit einstellt, etwa durch das Verlangen bestandener Lint-Prüfungen oder die Überprüfung, ob Ausgabedateien existieren.

TeammateIdle-Hooks unterstützen keine Matcher und werden bei jedem Vorkommen ausgelöst.

<h4 id="teammateidle-input">
  TeammateIdle-Eingabe
</h4>

Zusätzlich zu den [gemeinsamen Eingabefeldern](#common-input-fields) erhalten TeammateIdle-Hooks `teammate_name` und `team_name`.

```json theme={null}
{
  "session_id": "abc123",
  "transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",
  "cwd": "/Users/...",
  "permission_mode": "default",
  "hook_event_name": "TeammateIdle",
  "teammate_name": "researcher",
  "team_name": "session-a1b2c3d4"
}
```

| Feld | Beschreibung |
| :- | :- |
| `teammate_name` | Name des Teammitglieds, das kurz davor ist, untätig zu werden |
| `team_name` | Veraltet. Aus der Sitzung abgeleiteter Teamname; wird in einer zukünftigen Version entfernt |

<h4 id="teammateidle-decision-control">
  TeammateIdle-Entscheidungssteuerung
</h4>

TeammateIdle-Hooks unterstützen zwei Möglichkeiten, das Verhalten von Teammitgliedern zu steuern:

* **Exit-Code 2**: Das Teammitglied erhält die stderr-Meldung als Feedback und arbeitet weiter, anstatt untätig zu werden.
* **JSON `{"continue": false, "stopReason": "..."}`**: Stoppt das Teammitglied vollständig, entsprechend dem Verhalten des `Stop`-Hooks. Der `stopReason` wird dem Benutzer angezeigt.

Dieses Beispiel prüft, ob ein Build-Artefakt existiert, bevor ein Teammitglied untätig werden darf:

```bash theme={null}
#!/bin/bash

if [ ! -f "./dist/output.js" ]; then
  echo "Build artifact missing. Run the build before stopping." >&2
  exit 2
fi

exit 0
```

<h3 id="configchange">
  ConfigChange
</h3>

Wird ausgeführt, wenn sich während einer Sitzung eine Konfigurationsdatei ändert. Verwenden Sie dies, um Einstellungsänderungen zu prüfen, Sicherheitsrichtlinien durchzusetzen oder nicht autorisierte Änderungen an Konfigurationsdateien zu blockieren.

Claude Code führt ConfigChange-Hooks aus, wenn sich eine Einstellungsdatei, eine Datei mit verwalteten Richtlinien oder eine Skill-Datei ändert. Bei verwalteten Richtlinien führt es sie nur aus, wenn sich `managed-settings.json` oder eine Datei in `managed-settings.d/` ändert. [Serververwaltete Einstellungen](/docs/de/server-managed-settings) sowie Änderungen an verwalteten macOS-Einstellungen oder Windows-Registrierungsrichtlinien wendet es an, ohne die Hooks auszuführen. Unter WSL mit [`wslInheritsWindowsSettings`](/docs/de/settings-reference#wslinheritswindowssettings) wendet es bei seiner Richtlinienabfrage auch eine geänderte Windows-seitige Datei mit verwalteten Einstellungen an, ohne die Hooks auszuführen.

Der Matcher filtert nach der Konfigurationsquelle:

| Matcher | Wann er ausgelöst wird |
| :- | :- |
| `user_settings` | `~/.claude/settings.json` ändert sich |
| `project_settings` | `.claude/settings.json` ändert sich |
| `local_settings` | `.claude/settings.local.json` ändert sich |
| `policy_settings` | `managed-settings.json` oder eine Datei in `managed-settings.d/` ändert sich |
| `skills` | Eine Skill-Datei in `.claude/skills/` ändert sich |

Dieses Beispiel protokolliert alle Konfigurationsänderungen für Sicherheitsaudits:

```json theme={null}
{
  "hooks": {
    "ConfigChange": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/audit-config-change.sh",
            "args": []
          }
        ]
      }
    ]
  }
}
```

<h4 id="configchange-input">
  ConfigChange-Eingabe
</h4>

Zusätzlich zu den [gemeinsamen Eingabefeldern](#common-input-fields) erhalten ConfigChange-Hooks `source` und optional `file_path`. Das Feld `source` gibt an, welcher Konfigurationstyp sich geändert hat, und `file_path` liefert den Pfad zur konkret geänderten Datei.

```json theme={null}
{
  "session_id": "abc123",
  "transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",
  "cwd": "/Users/...",
  "hook_event_name": "ConfigChange",
  "source": "project_settings",
  "file_path": "/Users/.../my-project/.claude/settings.json"
}
```

<h4 id="configchange-decision-control">
  ConfigChange-Entscheidungssteuerung
</h4>

ConfigChange-Hooks können verhindern, dass Konfigurationsänderungen wirksam werden. Verwenden Sie Exit-Code 2 oder ein JSON-`decision`, um die Änderung zu verhindern. Bei einer Blockierung werden die neuen Einstellungen nicht auf die laufende Sitzung angewendet.

| Feld | Beschreibung |
| :- | :- |
| `decision` | `"block"` verhindert, dass die Konfigurationsänderung angewendet wird. Weglassen, um die Änderung zu erlauben |
| `reason` | Wird akzeptiert, aber nie angezeigt |

```json theme={null}
{
  "decision": "block",
  "reason": "Configuration changes to project settings require admin approval"
}
```

Änderungen an `policy_settings` können nicht blockiert werden. Hooks werden für `policy_settings`-Quellen weiterhin ausgelöst, wenn sich eine Datei mit verwalteten Einstellungen auf dem Rechner ändert, sodass Sie sie zum Protokollieren dieser Änderungen verwenden können, aber jede Blockierungsentscheidung wird ignoriert. Dadurch wird sichergestellt, dass unternehmensweit verwaltete Einstellungen immer wirksam werden. Claude Code führt keine `ConfigChange`-Hooks aus, wenn [serververwaltete Einstellungen](/docs/de/server-managed-settings) eintreffen oder aktualisiert werden.

Claude Code berücksichtigt die Blockierungsentscheidung aus der JSON-Ausgabe eines ConfigChange-Hooks und verwirft `systemMessage` und `continue`. Eine blockierte Änderung zeigt weder Ihnen noch Claude eine Nachricht an, unabhängig davon, ob Sie mit `reason` oder mit stderr bei Exit-Code 2 blockieren. Claude Code schreibt lediglich eine Zeile in das Debug-Log.

<h3 id="cwdchanged">
  CwdChanged
</h3>

Wird ausgeführt, wenn ein Shell-Befehl in der Hauptkonversation das Arbeitsverzeichnis ändert, beispielsweise wenn Claude einen `cd`-Befehl ausführt. Verwenden Sie dies, um auf Verzeichniswechsel zu reagieren: Umgebungsvariablen neu laden, projektspezifische Toolchains aktivieren oder Einrichtungsskripte automatisch ausführen. Lässt sich mit [FileChanged](#filechanged) kombinieren für Tools wie [direnv](https://direnv.net/), die verzeichnisspezifische Umgebungen verwalten.

CwdChanged-Hooks haben Zugriff auf [`CLAUDE_ENV_FILE`](#persist-environment-variables). In diese Datei geschriebene Variablen bleiben für nachfolgende Bash-Befehle bis zum nächsten CwdChanged-Ereignis erhalten, bei dem Claude Code sie löscht.

CwdChanged unterstützt keine Matcher und wird bei jedem Vorkommen ausgelöst.

<h4 id="cwdchanged-input">
  CwdChanged-Eingabe
</h4>

Zusätzlich zu den [gemeinsamen Eingabefeldern](#common-input-fields) erhalten CwdChanged-Hooks `old_cwd` und `new_cwd`.

```json theme={null}
{
  "session_id": "abc123",
  "transcript_path": "/Users/.../.claude/projects/.../transcript.jsonl",
  "cwd": "/Users/my-project/src",
  "hook_event_name": "CwdChanged",
  "old_cwd": "/Users/my-project",
  "new_cwd": "/Users/my-project/src"
}
```

<h4 id="cwdchanged-output">
  CwdChanged-Ausgabe
</h4>

Zusätzlich zu den [JSON-Ausgabefeldern](#json-output), die allen Hooks zur Verfügung stehen, können CwdChanged-Hooks `watchPaths` zurückgeben, um dynamisch festzulegen, welche Dateipfade [FileChanged](#filechanged) überwacht:

| Feld | Beschreibung |
| :- | :- |
| `watchPaths` | Array absoluter Pfade. Ersetzt die aktuelle dynamische Überwachungsliste. Pfade aus Ihrer `matcher`-Konfiguration werden immer überwacht. Die Rückgabe eines leeren Arrays leert die dynamische Liste, was beim Wechsel in ein neues Verzeichnis typisch ist |

CwdChanged-Hooks haben keine Entscheidungssteuerung. Sie können den Verzeichniswechsel nicht blockieren.

Claude Code liest `watchPaths` und `systemMessage` aus ihrer JSON-Ausgabe und verwirft `continue`. In interaktiven Sitzungen zeigt es die `systemMessage` als kurze Terminal-Benachrichtigung an. Die Nachricht erreicht den SDK-Nachrichtenstrom nicht.

<h3 id="directoryadded">
  DirectoryAdded
</h3>

Wird ausgeführt, nachdem Sie während einer Sitzung mit dem Befehl `/add-dir` ein Arbeitsverzeichnis hinzugefügt haben oder nachdem ein SDK-Client eines mit der Steuerungsanfrage `register_repo_root` hinzugefügt hat. Verwenden Sie dies, um ein neu hinzugefügtes Repository vorzubereiten, beispielsweise durch Installieren seiner Abhängigkeiten.

Claude Code löst dieses Ereignis nicht aus, wenn:

* Sie ein Verzeichnis mit dem Start-Flag `--add-dir` übergeben; [SessionStart](#sessionstart) deckt diese Verzeichnisse ab
* Sie ein Verzeichnis auf dem Tab Workspace von `/permissions` hinzufügen
* Sie ein Verzeichnis hinzufügen, das bereits ein Arbeitsverzeichnis ist oder sich in einem befindet

Claude Code löst DirectoryAdded aus, nachdem der Sandbox- und Berechtigungsstatus aktualisiert wurde, sodass in einer Sandbox ausgeführte Tools das neue Verzeichnis bereits sehen, wenn Ihr Hook ausgeführt wird. Hook-Befehle selbst werden außerhalb der Sandbox ausgeführt.

Claude Code wartet nicht auf den Hook: Das Hinzufügen wird sofort abgeschlossen, und der Hook läuft im Hintergrund mit dem Standard-Timeout von 600 Sekunden.

Der Matcher filtert danach, wie das Verzeichnis hinzugefügt wurde:

| Matcher | Wann er ausgelöst wird |
| :- | :- |
| `slash_command` | Sie fügen ein Verzeichnis mit `/add-dir` hinzu |
| `register_repo_root` | Ein SDK-Client fügt ein Verzeichnis mit der Steuerungsanfrage `register_repo_root` hinzu |

<h4 id="directoryadded-input">
  DirectoryAdded-Eingabe
</h4>

Zusätzlich zu den [gemeinsamen Eingabefeldern](#common-input-fields) erhalten DirectoryAdded-Hooks `directory` und `source`.

| Feld | Beschreibung |
| :- | :- |
| `directory` | Absoluter Pfad des hinzugefügten Verzeichnisses |
| `source` | Wie das Verzeichnis hinzugefügt wurde: `"slash_command"` für `/add-dir` oder `"register_repo_root"` für die SDK-Steuerungsanfrage |

```json theme={null}
{
  "session_id": "abc123",
  "transcript_path": "/Users/.../.claude/projects/.../transcript.jsonl",
  "cwd": "/Users/my-project",
  "hook_event_name": "DirectoryAdded",
  "directory": "/Users/my-other-repo",
  "source": "slash_command"
}
```

DirectoryAdded-Hooks haben keine Entscheidungssteuerung. Sie können das Hinzufügen nicht blockieren, da es bereits abgeschlossen ist, wenn der Hook ausgeführt wird. Claude Code verwirft das Feld `continue` aus ihrer JSON-Ausgabe und behandelt den Rest je nach Quelle unterschiedlich:

* `slash_command`: Claude Code übermittelt die `systemMessage` des Hooks im nächsten Konversations-Turn als Kontext an Claude, anstatt sie Ihnen anzuzeigen. Die Anzahl fehlgeschlagener Hooks erscheint im Transkript. Die vollständige Fehlerausgabe geht in das Debug-Log
* `register_repo_root`: Claude Code schreibt die `systemMessage`-Ausgabe und die Fehlerausgabe nur in das Debug-Log

<h3 id="filechanged">
  FileChanged
</h3>

Wird ausgeführt, wenn sich eine überwachte Datei auf der Festplatte ändert. Claude Code erkennt Änderungen mit einem Dateisystem-Watcher, nicht durch Prüfen von Tool-Aufrufen, und führt den Hook daher unabhängig davon aus, was die Datei geändert hat: ein `Edit`- oder `Write`-Tool-Aufruf, ein Skript, das Claude mit `Bash` ausführt, oder ein Prozess vollständig außerhalb von Claude Code. Ein häufiger Anwendungsfall ist das Neuladen von Umgebungsvariablen, wenn sich Projektkonfigurationsdateien ändern.

Der `matcher` für dieses Ereignis erfüllt zwei Aufgaben:

* **Überwachungsliste aufbauen**: Der Wert wird an `|` aufgeteilt, und jedes Segment wird als literaler Dateiname im Arbeitsverzeichnis registriert, sodass `".envrc|.env"` genau diese beiden Dateien überwacht. Regex-Muster sind hier nicht sinnvoll: Ein Wert wie `^\.env` würde eine Datei überwachen, die buchstäblich `^\.env` heißt.
* **Filtern, welche Hooks ausgeführt werden**: Wenn sich eine überwachte Datei ändert, filtert derselbe Wert anhand der Standard-[Matcher-Regeln](#matcher-patterns) gegen den Basisnamen der geänderten Datei, welche Hook-Gruppen ausgeführt werden.

Dieses Beispiel normalisiert die Zeilenenden in `data.csv` nach jeder Änderung, auch wenn ein `Bash`-Befehl oder ein externes Skript die Datei neu schreibt:

```json theme={null}
{
  "hooks": {
    "FileChanged": [
      {
        "matcher": "data.csv",
        "hooks": [
          {
            "type": "command",
            "command": "/path/to/normalize-line-endings.sh"
          }
        ]
      }
    ]
  }
}
```

Der Hook liest den absoluten Pfad der geänderten Datei aus dem Feld `file_path` der [JSON-Eingabe](#filechanged-input) auf stdin. Seine `grep`-Prüfung testet auf dasselbe, was `perl` entfernt, nämlich ein CR am Zeilenende, sodass der Durchlauf nach einer Normalisierung beendet wird, ohne die Datei anzurühren. Eine lockerere Prüfung führt zu einer Endlosschleife, weil `perl -i` die Datei auch dann neu schreibt, wenn es nichts ersetzt, und Claude Code den Hook nach jedem Neuschreiben erneut ausführt. Speichern Sie dieses Skript unter `/path/to/normalize-line-endings.sh` und machen Sie es ausführbar:

```bash theme={null}
#!/bin/bash
FILE=$(jq -r .file_path)
if grep -q $'\r$' "$FILE"; then
  perl -pi -e 's/\r$//' "$FILE"
fi
```

Um zu bestätigen, dass der Hook funktioniert, bitten Sie Claude, mit einem `Bash`-Befehl eine CRLF-Zeile an `data.csv` anzuhängen. Claude Code führt den Hook aus, und die Datei hat anschließend LF-Zeilenenden.

Um Dateien zu überwachen, die Sie nicht im Voraus benennen können, geben Sie aus einem Hook [`watchPaths`](#filechanged-output) zurück, um die Überwachungsliste dynamisch zu aktualisieren. Claude Code startet den Watcher nur, wenn etwas eine zu überwachende Datei benennt. Befüllen Sie die Liste daher mit einer FileChanged-Gruppe, deren Matcher mindestens eine Datei benennt, oder mit einem [SessionStart](#sessionstart-decision-control)- oder [CwdChanged](#cwdchanged)-Hook, der `watchPaths` zurückgibt. Der Matcher filtert weiterhin, welche Hook-Gruppen ausgeführt werden, wenn sich eine überwachte Datei ändert. Lassen Sie daher bei der Gruppe, die dynamische Pfade verarbeitet, den Matcher weg; ein weggelassener Matcher matcht jede überwachte Datei und fügt der Überwachungsliste nichts hinzu. Ein `"*"`-Matcher matcht ebenfalls jede Datei, aber Claude Code registriert ihn wie jeden anderen Wert in der Überwachungsliste, als literale Datei namens `*`.

FileChanged-Hooks haben Zugriff auf [`CLAUDE_ENV_FILE`](#persist-environment-variables). In diese Datei geschriebene Variablen bleiben für nachfolgende Bash-Befehle bis zum nächsten [CwdChanged](#cwdchanged)-Ereignis erhalten, bei dem Claude Code sie löscht.

<h4 id="filechanged-input">
  FileChanged-Eingabe
</h4>

Zusätzlich zu den [gemeinsamen Eingabefeldern](#common-input-fields) erhalten FileChanged-Hooks `file_path` und `event`.

| Feld | Beschreibung |
| :- | :- |
| `file_path` | Absoluter Pfad zur geänderten Datei |
| `event` | Was passiert ist: `"change"` für eine geänderte Datei, `"add"` für eine erstellte Datei oder `"unlink"` für eine gelöschte Datei |

```json theme={null}
{
  "session_id": "abc123",
  "transcript_path": "/Users/.../.claude/projects/.../transcript.jsonl",
  "cwd": "/Users/my-project",
  "hook_event_name": "FileChanged",
  "file_path": "/Users/my-project/.envrc",
  "event": "change"
}
```

<h4 id="filechanged-output">
  FileChanged-Ausgabe
</h4>

Zusätzlich zu den [JSON-Ausgabefeldern](#json-output), die allen Hooks zur Verfügung stehen, können FileChanged-Hooks `watchPaths` zurückgeben, um dynamisch zu aktualisieren, welche Dateipfade überwacht werden:

| Feld | Beschreibung |
| :- | :- |
| `watchPaths` | Array absoluter Pfade. Ersetzt die aktuelle dynamische Überwachungsliste. Pfade aus Ihrer `matcher`-Konfiguration werden immer überwacht. Verwenden Sie dies, wenn Ihr Hook-Skript anhand der geänderten Datei weitere zu überwachende Dateien ermittelt |

FileChanged-Hooks haben keine Entscheidungssteuerung. Sie können die Dateiänderung nicht verhindern.

Claude Code liest `watchPaths` und `systemMessage` aus ihrer JSON-Ausgabe und verwirft `continue`. In interaktiven Sitzungen zeigt es die `systemMessage` als kurze Terminal-Benachrichtigung an. Die Nachricht erreicht den SDK-Nachrichtenstrom nicht.

<h3 id="worktreecreate">
  WorktreeCreate
</h3>

Wird ausgeführt, wenn ein Worktree erstellt wird, sei es über `claude --worktree`, durch einen [Subagenten mit `isolation: "worktree"`](/docs/de/sub-agents#choose-the-subagent-scope) oder für eine [Hintergrundsitzung](/docs/de/agent-view#how-file-edits-are-isolated), die Claude Code in einem eigenen Worktree isoliert. Standardmäßig erstellt Claude Code die isolierte Arbeitskopie mit `git worktree`. Das Konfigurieren eines WorktreeCreate-Hooks ersetzt dieses standardmäßige Git-Verhalten, sodass Sie ein anderes Versionskontrollsystem wie SVN, Perforce oder Mercurial verwenden können.

Da der Hook das Standardverhalten vollständig ersetzt, wird [`.worktreeinclude`](/docs/de/worktrees#copy-gitignored-files-into-worktrees) nicht verarbeitet. Wenn Sie lokale Konfigurationsdateien wie `.env` in den neuen Worktree kopieren müssen, tun Sie dies in Ihrem Hook-Skript.

Der Hook muss den Pfad zum erstellten Worktree-Verzeichnis zurückgeben. Claude Code verwendet diesen Pfad als Arbeitsverzeichnis für die isolierte Sitzung. Siehe [WorktreeCreate-Ausgabe](#worktreecreate-output) dazu, wie jeder Hook-Typ den Pfad zurückgibt.

Claude Code berücksichtigt den Erfolg des Hooks und den zurückgegebenen Pfad und verwirft `systemMessage` und `continue`.

Dieses Beispiel erstellt eine SVN-Arbeitskopie und gibt den Pfad aus, den Claude Code verwenden soll. Ersetzen Sie die Repository-URL durch Ihre eigene:

```json theme={null}
{
  "hooks": {
    "WorktreeCreate": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "bash -c 'NAME=$(jq -r .name); DIR=\"$HOME/.claude/worktrees/$NAME\"; svn checkout https://svn.example.com/repo/trunk \"$DIR\" >&2 && echo \"$DIR\"'"
          }
        ]
      }
    ]
  }
}
```

Der Hook liest den Worktree-`name` aus der JSON-Eingabe auf stdin, checkt eine neue Kopie in ein neues Verzeichnis aus und gibt den Verzeichnispfad aus. Das `echo` in der letzten Zeile ist das, was Claude Code als Worktree-Pfad liest. Leiten Sie jede andere Ausgabe nach stderr um, damit sie den Pfad nicht beeinträchtigt.

<h4 id="worktreecreate-input">
  WorktreeCreate-Eingabe
</h4>

Zusätzlich zu den [gemeinsamen Eingabefeldern](#common-input-fields) erhalten WorktreeCreate-Hooks das Feld `name`. Dies ist ein Slug-Bezeichner für den neuen Worktree, entweder vom Benutzer angegeben oder automatisch generiert, zum Beispiel `bold-oak-a3f2`.

```json theme={null}
{
  "session_id": "abc123",
  "transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",
  "cwd": "/Users/...",
  "hook_event_name": "WorktreeCreate",
  "name": "feature-auth"
}
```

<h4 id="worktreecreate-output">
  WorktreeCreate-Ausgabe
</h4>

WorktreeCreate-Hooks verwenden nicht das übliche Entscheidungsmodell aus Zulassen und Blockieren. Stattdessen bestimmt der Erfolg oder Misserfolg des Hooks das Ergebnis. Der Hook muss den Pfad zum erstellten Worktree-Verzeichnis zurückgeben:

* **Befehls-Hooks** (`type: "command"`): Geben Sie den Pfad als letzte nicht leere Zeile auf stdout aus. Claude Code entfernt ANSI-Escape-Codes, bevor es diese Zeile liest, sodass Shell-Startbanner, die vor Ihrem `echo` ausgegeben werden, ignoriert werden. Leiten Sie jede andere Ausgabe des Hooks nach stderr um.
* **HTTP-Hooks** (`type: "http"`): Geben Sie `{ "hookSpecificOutput": { "hookEventName": "WorktreeCreate", "worktreePath": "/absolute/path" } }` im Response-Body zurück.

Wenn der Hook fehlschlägt oder keinen Pfad liefert, schlägt die Erstellung des Worktrees mit einem Fehler fehl.

Claude Code löst einen relativen Pfad relativ zu dem Verzeichnis auf, in dem der Hook ausgeführt wurde, und löst dabei alle `.`- oder `..`-Segmente auf. Wenn der resultierende Pfad kein Verzeichnis ist, das Claude Code betreten kann, gibt die Sitzung einen Fehler mit dem Pfad aus und wird mit Exit-Code 1 beendet.

Claude Code lehnt einen absoluten Pfad ab, der `.`- oder `..`-Segmente enthält, sowie jeden Pfad, der unterhalb des Repository-Stammverzeichnisses durch einen Symlink führt, da ein im Repository committeter Symlink den Worktree aus dem Repository heraus umleiten könnte. Die Fehlermeldung nennt die abgelehnte Komponente. Geben Sie einen normalisierten Pfad zurück, der nicht durch einen Symlink innerhalb des Repositorys führt. Vor v2.1.216 folgte die Worktree-Erstellung dem Pfad des Hooks ohne diese Prüfung.

<h3 id="worktreeremove">
  WorktreeRemove
</h3>

Wird ausgeführt, wenn ein Worktree entfernt wird. Dies ist das Gegenstück zu [WorktreeCreate](#worktreecreate) für die Bereinigung. Das Ereignis wird ausgelöst, wenn:

* Sie eine `--worktree`-Sitzung beenden und sich für das Entfernen entscheiden
* ein Subagent mit `isolation: "worktree"` fertig ist
* Sie eine [Hintergrundsitzung](/docs/de/agent-view#what-deleting-a-session-removes) löschen, deren Worktree der Hook erstellt hat

Bei Git-basierten Worktrees übernimmt Claude Code die Bereinigung automatisch mit `git worktree remove`. Wenn Sie einen WorktreeCreate-Hook konfiguriert haben, kombinieren Sie ihn mit einem WorktreeRemove-Hook, um die Bereinigung der von ihm erstellten Worktrees zu steuern:

* **Kein WorktreeRemove-Hook**: Wenn Sie eine `--worktree`-Sitzung beenden und das Entfernen wählen, greift Claude Code ersatzweise auf `git worktree remove --force` für den Pfad zurück, den Ihr WorktreeCreate-Hook zurückgegeben hat, sodass ein Worktree, den Git erkennt, entfernt wird. Ein Worktree, den Git nicht erkennt, etwa einer, den Ihr Hook mit einem anderen Versionskontrollsystem als Git erstellt hat, bleibt auf der Festplatte. Was beim Löschen einer [Hintergrundsitzung](/docs/de/agent-view#what-deleting-a-session-removes) mit einem vom Hook erstellten Worktree geschieht, erfahren Sie in den Löschregeln der Agentenansicht.
* **Hook endet mit 0**: Der Worktree gilt als entfernt. Claude Code liest nichts weiter vom Hook, stellen Sie also sicher, dass Ihr Hook das Verzeichnis gelöscht hat.
* **Hook endet mit einem Wert ungleich 0**: Das Entfernen schlägt fehl, wenn das Verzeichnis unter `worktree_path` danach noch existiert, und der Worktree bleibt ohne Git-Fallback auf der Festplatte. Ein Hook, der das Verzeichnis gelöscht hat, bevor er mit einem Wert ungleich 0 endet, gilt als entfernt. Wie der Fehler gemeldet wird, erfahren Sie unter [WorktreeRemove-Eingabe](#worktreeremove-input).

Claude Code löscht niemals einen Branch, der zu einem vom Hook erstellten Worktree gehört, da es nur den Pfad kennt, den Ihr WorktreeCreate-Hook zurückgegeben hat. Wenn Ihr WorktreeCreate-Hook einen Branch erstellt, löschen Sie ihn in Ihrem WorktreeRemove-Hook.

Claude Code verwirft die [JSON-Ausgabefelder](#json-output) eines WorktreeRemove-Hooks, etwa `systemMessage` und `continue`.

Beim Löschen einer Hintergrundsitzung überprüft Claude Code den gespeicherten Worktree-Pfad, bevor der Hook ausgeführt wird, und lehnt einen Pfad ab, der ein Symlink ist oder unterhalb des Repository-Stammverzeichnisses durch einen Symlink führt. Für einen Worktree, der noch Dateien enthält, wird der Hook nur ausgeführt, wenn Sie das Löschen in der [Agentenansicht](/docs/de/agent-view#what-deleting-a-session-removes) bestätigen; für einen solchen Worktree behält [`claude rm`](/docs/de/agent-view#manage-sessions-from-the-shell) stattdessen die Sitzung und den Worktree bei. Vor v2.1.216 wurde der Hook ohne diese Prüfungen für den gespeicherten Pfad ausgeführt.

Claude Code übergibt den von WorktreeCreate zurückgegebenen Pfad als `worktree_path` in der Hook-Eingabe. Dieses Beispiel liest diesen Pfad und entfernt das Verzeichnis:

```json theme={null}
{
  "hooks": {
    "WorktreeRemove": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "bash -c 'jq -r .worktree_path | xargs rm -rf'"
          }
        ]
      }
    ]
  }
}
```

<h4 id="worktreeremove-input">
  WorktreeRemove-Eingabe
</h4>

Zusätzlich zu den [gemeinsamen Eingabefeldern](#common-input-fields) erhalten WorktreeRemove-Hooks das Feld `worktree_path`, das den absoluten Pfad zum zu entfernenden Worktree enthält.

```json theme={null}
{
  "session_id": "abc123",
  "transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",
  "cwd": "/Users/...",
  "hook_event_name": "WorktreeRemove",
  "worktree_path": "/Users/.../my-project/.claude/worktrees/feature-auth"
}
```

Der Exit-Code eines WorktreeRemove-Hooks bestimmt das Ergebnis. Wenn ein Hook mit einem Wert ungleich 0 endet und das Verzeichnis unter `worktree_path` danach noch existiert, schlägt das Entfernen fehl:

* Der Worktree bleibt auf der Festplatte, und der Befehl sowie stderr des Hooks werden in das [Debug-Log](#debug-hooks) geschrieben.
* Wenn Sie eine Hintergrundsitzung gelöscht haben, bleibt auch die Sitzung bestehen. Die Ablehnungsmeldung in der [Agentenansicht](/docs/de/agent-view#what-deleting-a-session-removes) gibt an, wie der Hook beendet wurde, etwa `exited 1`, zitiert den Anfang seiner stderr-Ausgabe und gibt an, ob ein erneutes Löschen der Sitzung das Verzeichnis trotzdem entfernt.

<h3 id="precompact">
  PreCompact
</h3>

Wird ausgeführt, bevor Claude Code einen Komprimierungsvorgang startet.

Der Matcher-Wert gibt an, ob die Komprimierung manuell oder automatisch ausgelöst wurde:

| Matcher | Wann er ausgelöst wird |
| :- | :- |
| `manual` | `/compact` |
| `auto` | Automatische Komprimierung, wenn die Konversation das [Fenster für die automatische Komprimierung](/docs/de/model-config#set-the-auto-compact-window) erreicht |

Beenden Sie mit Exit-Code 2, um die Komprimierung zu blockieren. Bei einem manuellen `/compact` wird die stderr-Meldung dem Benutzer angezeigt. Sie können auch blockieren, indem Sie JSON mit `"decision": "block"` zurückgeben.

Das Blockieren der automatischen Komprimierung hat je nach Zeitpunkt unterschiedliche Auswirkungen. Wurde die Komprimierung vorsorglich vor dem Kontextlimit ausgelöst, überspringt Claude Code sie, und die Konversation wird unkomprimiert fortgesetzt. Wurde die Komprimierung ausgelöst, um sich von einem bereits von der API zurückgegebenen Kontextlimit-Fehler zu erholen, tritt der zugrunde liegende Fehler zutage, und die aktuelle Anfrage schlägt fehl.

Claude Code verwirft die Felder `systemMessage` und `continue` eines PreCompact-Hooks.

<h4 id="precompact-input">
  PreCompact-Eingabe
</h4>

Zusätzlich zu den [gemeinsamen Eingabefeldern](#common-input-fields) erhalten PreCompact-Hooks `trigger` und `custom_instructions`. Bei `manual` enthält `custom_instructions` das, was der Benutzer an `/compact` übergibt, und ist `null`, wenn nichts übergeben wird. Bei `auto` ist `custom_instructions` `null`.

```json theme={null}
{
  "session_id": "abc123",
  "transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",
  "cwd": "/Users/...",
  "hook_event_name": "PreCompact",
  "trigger": "manual",
  "custom_instructions": null
}
```

<h3 id="postcompact">
  PostCompact
</h3>

Wird ausgeführt, nachdem Claude Code einen Komprimierungsvorgang abgeschlossen hat. Verwenden Sie dieses Ereignis, um auf den neuen komprimierten Zustand zu reagieren, etwa um die generierte Zusammenfassung zu protokollieren oder externen Zustand zu aktualisieren. Claude Code verwirft die Felder `systemMessage` und `continue` eines PostCompact-Hooks.

Es gelten dieselben Matcher-Werte wie für `PreCompact`:

| Matcher | Wann er ausgelöst wird |
| :- | :- |
| `manual` | Nach `/compact` |
| `auto` | Nach der automatischen Komprimierung, wenn die Konversation das [Fenster für die automatische Komprimierung](/docs/de/model-config#set-the-auto-compact-window) erreicht |

<h4 id="postcompact-input">
  PostCompact-Eingabe
</h4>

Zusätzlich zu den [gemeinsamen Eingabefeldern](#common-input-fields) erhalten PostCompact-Hooks `trigger` und `compact_summary`. Das Feld `compact_summary` enthält die vom Komprimierungsvorgang generierte Zusammenfassung der Konversation.

```json theme={null}
{
  "session_id": "abc123",
  "transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",
  "cwd": "/Users/...",
  "hook_event_name": "PostCompact",
  "trigger": "manual",
  "compact_summary": "Summary of the compacted conversation..."
}
```

PostCompact-Hooks haben keine Entscheidungssteuerung. Sie können das Ergebnis der Komprimierung nicht beeinflussen, aber Folgeaufgaben ausführen.

<h3 id="premodelswitch">
  PreModelSwitch
</h3>

Wird ausgeführt, bevor Claude Code einen Modellwechsel anwendet, den Sie oder ein Client angefordert haben. Verwenden Sie es, um einen Wechsel zu blockieren, eine Bestätigung zu verlangen oder anzuzeigen, was der Wechsel kosten wird, bevor er erfolgt.

PreModelSwitch erfordert Claude Code v2.1.251 oder höher. Claude Code führt es für diese Anfragen aus:

* `/model <name>` und die `/model`-Auswahl
* Die Modellauswahl über `Option+P` oder `Alt+P`
* Die Einstellung „Model“ in `/config`
* Das Einschalten des [Fast-Modus](/docs/de/fast-mode), wenn dadurch das Modell der Sitzung geändert wird
* Eine `set_model`-Anfrage oder eine Modelländerung in einer `apply_flag_settings`-Anfrage von einem [Agent SDK](/docs/de/agent-sdk/typescript#query-object)-Host oder über [Remote Control](/docs/de/remote-control)

Claude Code führt PreModelSwitch-Hooks nicht für Wechsel aus, die es selbst vornimmt, etwa einen [automatischen Modell-Fallback](/docs/de/model-config#automatic-model-fallback) oder das Wiederherstellen des Modells beim Fortsetzen einer Sitzung. Diese Änderungen erreichen nur [PostModelSwitch](#postmodelswitch).

Claude Code vergleicht den Matcher mit dem kanonischen Namen des Modells, zu dem die Sitzung wechselt, und ignoriert dabei ein etwaiges `[1m]`-Suffix. Ein Alias wie `opus`, eine datierte Modell-ID und eine anbieterspezifische ID wie eine Amazon-Bedrock-Modell-ID stimmen alle mit dem einen kanonischen Namen überein, in den sie aufgelöst werden, sodass `claude-opus-5` jede Schreibweise von Opus 5 abdeckt.

Wenn Claude Code keinen kanonischen Namen für das Ziel ermitteln kann, etwa bei einer benutzerdefinierten Modell-ID, die nur Ihr [LLM-Gateway](/docs/de/llm-gateway) kennt, führt es jeden PreModelSwitch-Hook unabhängig vom Matcher aus. Ein blockierender Hook sollte daher `to_model` aus seiner Eingabe prüfen, statt sich allein auf den Matcher zu verlassen.

Schreiben Sie den Matcher als exakten Namen, als durch `|` getrennte Liste wie `claude-opus-4-6|claude-opus-5` oder als regulären Ausdruck wie `.*opus.*`. Dieses Beispiel verwendet einen Matcher mit exaktem Namen und prüft zusätzlich `to_model` aus der Hook-Eingabe, sodass es einen Wechsel zu Opus 4.6 durch Beenden mit Exit-Code 2 ablehnt und jedes andere Ziel durchlässt:

<Tabs>
  <Tab title="macOS/Linux">
    Der Befehl prüft `to_model` mit `jq`:

    ```json theme={null}
    {
      "hooks": {
        "PreModelSwitch": [
          {
            "matcher": "claude-opus-4-6",
            "hooks": [
              {
                "type": "command",
                "command": "jq -e '.to_model | test(\"opus-4-6\")' > /dev/null && { echo 'Opus 4.6 is retired for this project. Use a newer model.' >&2; exit 2; }; exit 0"
              }
            ]
          }
        ]
      }
    }
    ```
  </Tab>

  <Tab title="Windows (PowerShell)">
    Registrieren Sie einen Befehls-Hook, der ein Skript über PowerShell ausführt:

    ```json theme={null}
    {
      "hooks": {
        "PreModelSwitch": [
          {
            "matcher": "claude-opus-4-6",
            "hooks": [
              {
                "type": "command",
                "command": "powershell.exe",
                "args": [
                  "-NoProfile",
                  "-ExecutionPolicy",
                  "Bypass",
                  "-File",
                  "${CLAUDE_PROJECT_DIR}/.claude/hooks/block-opus-46.ps1"
                ]
              }
            ]
          }
        ]
      }
    }
    ```

    Speichern Sie dieses Skript in Ihrem Projekt unter `.claude/hooks/block-opus-46.ps1`:

    ```powershell theme={null}
    $hookInput = [Console]::In.ReadToEnd() | ConvertFrom-Json
    if ($hookInput.to_model -match 'opus-4-6') {
      [Console]::Error.WriteLine('Opus 4.6 is retired for this project. Use a newer model.')
      exit 2
    }
    exit 0
    ```
  </Tab>
</Tabs>

Um zu prüfen, ob der Hook funktioniert, führen Sie `/model claude-opus-4-6` in einer Sitzung aus, die ein anderes Modell verwendet. Claude Code behält das aktuelle Modell bei und meldet, dass ein PreModelSwitch-Hook den Wechsel blockiert hat, mit Ihrer Meldung als Grund.

<h4 id="premodelswitch-input">
  PreModelSwitch-Eingabe
</h4>

Zusätzlich zu den [gemeinsamen Eingabefeldern](#common-input-fields) erhalten PreModelSwitch-Hooks die Felder in dieser Tabelle. Die letzten fünf beschreiben, was das erneute Senden der Konversation an das neue Modell kostet, sodass ein Hook diesen Wert vor dem Wechsel anzeigen kann.

| Feld | Typ | Beschreibung |
| :- | :- | :- |
| `from_model` | string | Modell-ID, von der gewechselt wird |
| `to_model` | string | Modell-ID, zu der gewechselt wird. Der Matcher wird mit dem kanonischen Namen dieses Modells verglichen |
| `requested_model` | string oder `null` | Das in der Anfrage genannte Modell: ein Alias wie `opus`, eine vollständige Modell-ID oder `null`, wenn das Standardmodell angefordert wurde |
| `source` | string | Woher die Anfrage kam: `"command"` für `/model <name>`, die Einstellung „Model“ in `/config` oder das Einschalten des Fast-Modus; `"picker"` für eine Modellauswahl; `"sdk"` für eine `set_model`-Anfrage oder eine Modelländerung in einer `apply_flag_settings`-Anfrage von einem Agent-SDK-Host oder über Remote Control |
| `context_tokens` | number | Token, die die nächste Anfrage erneut als Prompt sendet: die Eingabe-, Cache-Lese-, Cache-Erstellungs- und Ausgabe-Token der letzten Antwort in der Hauptkonversation zusammengenommen. `0` vor der ersten Antwort |
| `prompt_cache_warm` | boolean | Ob der Prompt-Cache des aktuellen Modells wahrscheinlich noch warm ist, was bedeutet, dass er durch den Wechsel verloren geht |
| `cache_ttl` | string | [Lebensdauer des Prompt-Caches](/docs/de/prompt-caching#cache-lifetime), die Claude Code für diese Sitzung anfordert: `"5m"` oder `"1h"` |
| `estimated_cache_write_usd` | number | Geschätzte Kosten in US-Dollar für das Schreiben von `context_tokens` in den Prompt-Cache auf `to_model` zum `cache_ttl`-Tarif, ohne die nächste Antwort. Der Server muss möglicherweise nicht den gesamten Kontext erneut zwischenspeichern, betrachten Sie den Wert daher als Schätzung |
| `pricing` | string | Wie Claude Code `estimated_cache_write_usd` berechnet hat: `"configured"` zu den eigenen Tarifen Ihrer Organisation, sofern diese konfiguriert sind, `"catalog"` zum Listenpreis oder `"default"`, wenn für `to_model` kein Preis bekannt ist und Claude Code einen Standardtarif angenommen hat |

Dieses Beispiel zeigt die Eingabe für `/model opus` in einer Sitzung, die Sonnet 5 verwendet:

```json theme={null}
{
  "session_id": "abc123",
  "transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",
  "cwd": "/Users/...",
  "hook_event_name": "PreModelSwitch",
  "from_model": "claude-sonnet-5",
  "to_model": "claude-opus-5",
  "requested_model": "opus",
  "source": "command",
  "context_tokens": 182340,
  "prompt_cache_warm": true,
  "cache_ttl": "5m",
  "estimated_cache_write_usd": 1.1396,
  "pricing": "catalog"
}
```

<h4 id="premodelswitch-decision-control">
  PreModelSwitch-Entscheidungssteuerung
</h4>

`PreModelSwitch`-Hooks können den Wechsel abbrechen, den Benutzer um Bestätigung bitten oder ihn fortfahren lassen. Exit-Code 2 oder ein `decision: "block"` auf oberster Ebene bricht den Wechsel ab.

Für eine feinere Steuerung geben Sie `permissionDecision` und `permissionDecisionReason` in einem `hookSpecificOutput`-Objekt zurück, wie bei [PreToolUse](#pretooluse-decision-control). `PreModelSwitch` akzeptiert `"allow"`, `"deny"` und `"ask"`. Es akzeptiert weder `"defer"` noch `updatedInput` oder `additionalContext`. Die folgende Tabelle beschreibt beide Felder:

| Feld | Beschreibung |
| :- | :- |
| `permissionDecision` | `"allow"` fährt fort und überspringt die [Bestätigung, die Claude Code anzeigt, solange der Prompt-Cache warm ist](/docs/de/prompt-caching#switching-models). `"deny"` bricht den Wechsel ab. `"ask"` bittet den Benutzer um Bestätigung |
| `permissionDecisionReason` | Bei `"deny"` wird der Wert dem Benutzer als Grund für das Blockieren des Wechsels angezeigt oder bei einer `set_model`-Anfrage als Fehler zurückgegeben. Bei `"ask"` wird er in der Bestätigungsabfrage angezeigt. Bei `"allow"` wird er ignoriert |

Nur `/model` in einer interaktiven Sitzung kann die `"ask"`-Abfrage anzeigen. Auf allen anderen Oberflächen, einschließlich des nicht interaktiven Modus mit dem Flag `-p`, `/config` und `set_model`-Anfragen, behandelt Claude Code `"ask"` als Ablehnung.

Dieses Beispiel bittet den Benutzer um Bestätigung und nennt die Token-Anzahl aus `context_tokens`:

```json theme={null}
{
  "hookSpecificOutput": {
    "hookEventName": "PreModelSwitch",
    "permissionDecision": "ask",
    "permissionDecisionReason": "Switching now re-sends about 180k tokens to the new model. Continue?"
  }
}
```

Wenn mehrere PreModelSwitch-Hooks unterschiedliche Entscheidungen zurückgeben, gilt die Rangfolge `deny` > `ask` > `allow`.

Claude Code zeigt dem Benutzer jede `systemMessage` an, die Ihr Hook zurückgibt, unabhängig von der Entscheidung, sodass ein Hook zur Kostenanzeige `{"systemMessage": "..."}` zurückgeben und mit 0 enden kann.

Ein PreModelSwitch-Hook, der nicht vor Ablauf seines Timeouts antwortet, blockiert den Wechsel. Bei [PreToolUse](#timeouts) hingegen lässt ein Befehls-Hook mit Zeitüberschreitung den Tool-Aufruf fortfahren. Der Standard-Timeout für dieses Ereignis beträgt 30 Sekunden. `PreModelSwitch` führt nur `command`-, `http`- und `mcp_tool`-Hooks aus, daher gelten die Standardwerte für `prompt` und `agent` nicht.

Ein Hook, der mit einem anderen Code als 0 oder 2 endet und keine JSON-Entscheidung ausgibt, blockiert nicht: Claude Code zeigt seine stderr-Ausgabe an und wendet den Wechsel an, wie unter [Andere Exit-Codes](#other-exit-codes) beschrieben.

<h3 id="postmodelswitch">
  PostModelSwitch
</h3>

Wird ausgeführt, nachdem sich das Modell der Sitzung geändert hat. Verwenden Sie es, um Claude modellspezifische Hinweise zu geben, ohne jede CLAUDE.md zu bearbeiten, etwa eine organisationsweite Anweisung, die für bestimmte Modelle gilt.

PostModelSwitch erfordert Claude Code v2.1.251 oder höher. Es kann nicht blockieren, da sich das Modell bereits geändert hat. Claude Code führt PostModelSwitch-Hooks nach jeder dieser Änderungen aus:

* Ein Wechsel, den Sie oder ein Client angefordert haben
* Ein [automatischer Modell-Fallback](/docs/de/model-config#automatic-model-fallback), der das Modell der Sitzung ändert
* Eine Einstellung wie [`opusplan`](/docs/de/model-config#opusplan-model-setting), die den Plan-Modus betritt oder verlässt
* Claude Code stellt das Modell wieder her, wenn Sie eine Sitzung fortsetzen

Claude Code führt PostModelSwitch-Hooks nicht aus, wenn ein Modell aus einer [Fallback-Modellkette](/docs/de/model-config#fallback-model-chains) einen Turn bedient, da diese Ersetzung nur einen Turn dauert und das Modell der Sitzung unverändert lässt.

Der Matcher folgt denselben Regeln wie bei [PreModelSwitch](#premodelswitch): Claude Code vergleicht ihn mit dem kanonischen Namen des Modells, zu dem die Sitzung gewechselt ist.

Dieses Beispiel fügt Hinweise hinzu, sobald das Modell der Sitzung zu einem beliebigen Opus-Modell wechselt:

```json theme={null}
{
  "hooks": {
    "PostModelSwitch": [
      {
        "matcher": ".*opus.*",
        "hooks": [
          {
            "type": "command",
            "command": "echo 'On Opus, delegate implementation work to subagents and keep this conversation for planning and review.'"
          }
        ]
      }
    ]
  }
}
```

Um zu prüfen, ob der Hook funktioniert, wechseln Sie in einer Sitzung mit einem anderen Modell zu einem Opus-Modell, führen Sie beispielsweise `/model opus` in einer Sonnet-Sitzung aus, und fragen Sie Claude dann, welche Hinweise es zum aktuellen Modell hat.

<h4 id="postmodelswitch-input">
  PostModelSwitch-Eingabe
</h4>

PostModelSwitch-Hooks erhalten dieselben Felder wie [PreModelSwitch](#premodelswitch-input), wobei `hook_event_name` auf `"PostModelSwitch"` gesetzt ist und es zwei weitere `source`-Werte gibt: `"auto"` für einen automatischen Fallback oder eine andere Änderung, die Claude Code selbst vorgenommen hat, und `"resume"` für das Modell, das beim Fortsetzen einer Sitzung wiederhergestellt wurde.

`requested_model` ist `null`, wenn `source` den Wert `"auto"` hat. Wenn `source` den Wert `"resume"` hat, ist es die gespeicherte Modelleinstellung, die Claude Code wiederhergestellt hat.

<h4 id="postmodelswitch-decision-control">
  PostModelSwitch-Entscheidungssteuerung
</h4>

Claude Code übernimmt die [Klartext-Ausgabe auf stdout](#exit-code-0) Ihres Hooks bei Exit-Code 0 oder `additionalContext` aus der JSON-Ausgabe und übermittelt sie Claude mit der nächsten Anfrage nach dem Wechsel. Zusätzlich zu den [JSON-Ausgabefeldern](#json-output), die allen Hooks zur Verfügung stehen, können Sie Folgendes zurückgeben:

| Feld | Beschreibung |
| :- | :- |
| `additionalContext` | Zeichenfolge, die mit der nächsten Anfrage zu Claudes Kontext hinzugefügt wird. Siehe [Kontext für Claude hinzufügen](#add-context-for-claude) |

Wenn der Hook nicht innerhalb von fünf Sekunden nach dem Senden des nächsten Prompts fertig ist, sendet Claude Code diese Anfrage ohne die Ausgabe und hängt sie stattdessen an die darauffolgende Anfrage an. Wenn sich das Modell vor der nächsten Anfrage mehrmals ändert, übermittelt Claude Code nur die Ausgabe für das Zielmodell des letzten Wechsels.

<h3 id="sessionend">
  SessionEnd
</h3>

Wird ausgeführt, wenn eine Claude-Code-Sitzung endet. Nützlich für Bereinigungsaufgaben, das Protokollieren von Sitzungsstatistiken
oder das Speichern des Sitzungszustands. Unterstützt Matcher, um nach dem Beendigungsgrund zu filtern.

Das Feld `reason` in der Hook-Eingabe gibt an, warum die Sitzung beendet wurde:

| Grund | Beschreibung |
| :- | :- |
| `clear` | Sitzung mit dem Befehl `/clear` geleert |
| `resume` | Sitzung über das interaktive `/resume` gewechselt |
| `logout` | Benutzer hat sich abgemeldet |
| `prompt_input_exit` | Benutzer hat beendet, während das Prompt-Eingabefeld sichtbar war |
| `other` | Andere Beendigungsgründe |
| `bypass_permissions_disabled` | In v2.1.234 entfernt; Claude Code sendet diesen Wert nicht. Entfernen Sie ihn aus Ihren `SessionEnd`-Matchern |

<h4 id="sessionend-input">
  SessionEnd-Eingabe
</h4>

Zusätzlich zu den [gemeinsamen Eingabefeldern](#common-input-fields) erhalten SessionEnd-Hooks ein Feld `reason`, das angibt, warum die Sitzung beendet wurde. Alle Werte finden Sie in der [Tabelle der Gründe](#sessionend) oben.

```json theme={null}
{
  "session_id": "abc123",
  "transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",
  "cwd": "/Users/...",
  "hook_event_name": "SessionEnd",
  "reason": "other"
}
```

SessionEnd-Hooks haben keine Entscheidungssteuerung. Sie können das Beenden der Sitzung nicht blockieren, aber Bereinigungsaufgaben ausführen. Claude Code verwirft ihre [JSON-Ausgabefelder](#json-output), etwa `systemMessage`.

SessionEnd-Hooks haben einen Standard-Timeout von 1,5 Sekunden. Er gilt, wenn Sie beenden, `/clear` ausführen oder mit dem interaktiven `/resume` die Sitzung wechseln. Sie können einem Hook auf zwei Arten mehr Zeit geben:

* **`timeout` pro Hook**: Setzen Sie `timeout` in der Konfiguration des jeweiligen Hooks. Das Gesamtbudget steigt automatisch auf den höchsten `timeout`-Wert pro Hook in Ihren Einstellungsdateien, bis zu 60 Sekunden. Wenn Sie das Budget auf diese Weise erhöhen, behält ein Hook ohne eigenen `timeout` weiterhin den Standardwert. Timeouts, die für von Plugins bereitgestellte Hooks festgelegt sind, erhöhen das Budget nicht.
* **`CLAUDE_CODE_SESSIONEND_HOOKS_TIMEOUT_MS`**: Setzen Sie diese Umgebungsvariable in Millisekunden, um das Budget explizit zu überschreiben. Der von Ihnen festgelegte Wert wird außerdem zum Timeout für jeden Hook ohne eigenen `timeout`.

Dieses Beispiel setzt das Budget auf 5 Sekunden:

```bash theme={null}
CLAUDE_CODE_SESSIONEND_HOOKS_TIMEOUT_MS=5000 claude
```

Vor v2.1.268 erhöhte `CLAUDE_CODE_SESSIONEND_HOOKS_TIMEOUT_MS` nur das Gesamtbudget, und ein Hook ohne eigenen `timeout` wurde weiterhin nach 1,5 Sekunden abgebrochen.

<h3 id="elicitation">
  Elicitation
</h3>

Wird ausgeführt, wenn ein MCP-Server während einer Aufgabe Benutzereingaben anfordert. Standardmäßig zeigt Claude Code einen interaktiven Dialog an, in dem der Benutzer antworten kann. Hooks können diese Anfrage abfangen und programmatisch beantworten, wodurch der Dialog vollständig übersprungen wird.

Das Matcher-Feld wird mit dem Namen des MCP-Servers abgeglichen.

<h4 id="elicitation-input">
  Elicitation-Eingabe
</h4>

Zusätzlich zu den [gemeinsamen Eingabefeldern](#common-input-fields) erhalten Elicitation-Hooks die Felder `mcp_server_name` und `message` sowie die optionalen Felder `mode`, `url`, `elicitation_id` und `requested_schema`.

Für eine Elicitation im Formularmodus, den häufigsten Fall:

```json theme={null}
{
  "session_id": "abc123",
  "transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",
  "cwd": "/Users/...",
  "hook_event_name": "Elicitation",
  "mcp_server_name": "my-mcp-server",
  "message": "Please provide your credentials",
  "mode": "form",
  "requested_schema": {
    "type": "object",
    "properties": {
      "username": { "type": "string", "title": "Username" }
    }
  }
}
```

Für eine Elicitation im URL-Modus, die für browserbasierte Authentifizierung verwendet wird:

```json theme={null}
{
  "session_id": "abc123",
  "transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",
  "cwd": "/Users/...",
  "hook_event_name": "Elicitation",
  "mcp_server_name": "my-mcp-server",
  "message": "Please authenticate",
  "mode": "url",
  "url": "https://auth.example.com/login"
}
```

<h4 id="elicitation-output">
  Elicitation-Ausgabe
</h4>

Um programmatisch zu antworten, ohne den Dialog anzuzeigen, geben Sie ein JSON-Objekt mit `hookSpecificOutput` zurück:

```json theme={null}
{
  "hookSpecificOutput": {
    "hookEventName": "Elicitation",
    "action": "accept",
    "content": {
      "username": "alice"
    }
  }
}
```

| Feld | Werte | Beschreibung |
| :- | :- | :- |
| `action` | `accept`, `decline`, `cancel` | Ob die Anfrage angenommen, abgelehnt oder abgebrochen werden soll |
| `content` | object | Zu übermittelnde Werte der Formularfelder. Wird nur verwendet, wenn `action` den Wert `accept` hat |

Exit-Code 2 lehnt die Elicitation ab. Claude Code zeigt Ihre stderr-Meldung nirgends an.

Claude Code verarbeitet `hookSpecificOutput` aus der JSON-Ausgabe eines Elicitation-Hooks und verwirft `systemMessage` und `continue`.

<h3 id="elicitationresult">
  ElicitationResult
</h3>

Wird ausgeführt, nachdem ein Benutzer auf eine MCP-Elicitation geantwortet hat. Hooks können die Antwort beobachten, ändern oder blockieren, bevor sie an den MCP-Server zurückgesendet wird.

Das Matcher-Feld wird mit dem Namen des MCP-Servers abgeglichen.

<h4 id="elicitationresult-input">
  ElicitationResult-Eingabe
</h4>

Zusätzlich zu den [gemeinsamen Eingabefeldern](#common-input-fields) erhalten ElicitationResult-Hooks die Felder `mcp_server_name` und `action` sowie die optionalen Felder `mode`, `elicitation_id` und `content`.

```json theme={null}
{
  "session_id": "abc123",
  "transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",
  "cwd": "/Users/...",
  "hook_event_name": "ElicitationResult",
  "mcp_server_name": "my-mcp-server",
  "action": "accept",
  "content": { "username": "alice" },
  "mode": "form",
  "elicitation_id": "elicit-123"
}
```

<h4 id="elicitationresult-output">
  ElicitationResult-Ausgabe
</h4>

Um die Antwort des Benutzers zu überschreiben, geben Sie ein JSON-Objekt mit `hookSpecificOutput` zurück:

```json theme={null}
{
  "hookSpecificOutput": {
    "hookEventName": "ElicitationResult",
    "action": "decline",
    "content": {}
  }
}
```

| Feld | Werte | Beschreibung |
| :- | :- | :- |
| `action` | `accept`, `decline`, `cancel` | Überschreibt die Aktion des Benutzers |
| `content` | object | Überschreibt die Werte der Formularfelder. Nur sinnvoll, wenn `action` den Wert `accept` hat |

Exit-Code 2 blockiert die Antwort und ändert die effektive Aktion in `decline`. Claude Code zeigt Ihre stderr-Meldung nirgends an.

Claude Code verarbeitet `hookSpecificOutput` aus der JSON-Ausgabe eines ElicitationResult-Hooks und verwirft `systemMessage` und `continue`.

<h2 id="prompt-based-hooks">
  Prompt-basierte Hooks
</h2>

Zusätzlich zu Command-, HTTP- und MCP-Tool-Hooks unterstützt Claude Code Prompt-basierte Hooks (`type: "prompt"`), die ein LLM verwenden, um zu evaluieren, ob eine Aktion zuzulassen oder zu blockieren ist, und Agent-Hooks (`type: "agent"`), die einen agentengesteuerten Verifizierer mit Tool-Zugriff spawnen. Nicht alle Ereignisse unterstützen jeden Hook-Typ.

Ereignisse, die alle fünf Hook-Typen unterstützen (`command`, `http`, `mcp_tool`, `prompt` und `agent`):

* `PermissionDenied`
* `PostToolBatch`
* `PostToolUse`
* `PostToolUseFailure`
* `PreToolUse`
* `Stop`
* `SubagentStop`
* `TaskCompleted`
* `TaskCreated`
* `TeammateIdle`
* `UserPromptExpansion`
* `UserPromptSubmit`

`PermissionRequest` unterstützt `command`, `http`, `mcp_tool` und `prompt` Hooks, aber keine `agent` Hooks. Wenn Sie einen Agent-Hook bei diesem Ereignis konfigurieren, überspringt Claude Code ihn und der Genehmigungsfluss wird unverändert fortgesetzt. Um von einem Hook aus zuzulassen oder zu verweigern, geben Sie das [Entscheidungsobjekt](#permissionrequest-decision-control) von einem Command- oder HTTP-Hook zurück.

Ereignisse, die `command`, `http` und `mcp_tool` Hooks unterstützen, aber nicht `prompt` oder `agent`:

* `ConfigChange`
* `CwdChanged`
* `DirectoryAdded`
* `Elicitation`
* `ElicitationResult`
* `FileChanged`
* `InstructionsLoaded`
* `MessageDisplay`
* `Notification`
* `PostCompact`
* `PostModelSwitch`
* `PreCompact`
* `PreModelSwitch`
* `SessionEnd`
* `StopFailure`
* `SubagentStart`
* `WorktreeCreate`
* `WorktreeRemove`

`SessionStart` und `Setup` unterstützen `command` und `mcp_tool` Hooks, und [MCP-Tool-Hook-Felder](#mcp-tool-hook-fields) beschreibt, wann ihre `mcp_tool` Hooks ausgeführt werden. Sie unterstützen keine `http`, `prompt` oder `agent` Hooks.

<h3 id="how-prompt-based-hooks-work">
  Wie Prompt-basierte Hooks funktionieren
</h3>

Anstatt einen Bash-Befehl auszuführen, Prompt-basierte Hooks:

1. Senden die Hook-Eingabe und Ihren Prompt an ein Claude-Modell, standardmäßig das Modell, das Claude Code für [Hintergrundfunktionalität](/docs/de/costs#background-token-usage) verwendet
2. Das LLM antwortet mit strukturiertem JSON, das eine Entscheidung enthält
3. Claude Code verarbeitet die Entscheidung automatisch

<h3 id="prompt-hook-configuration">
  Prompt-Hook-Konfiguration
</h3>

Setzen Sie `type` auf `"prompt"` und geben Sie eine `prompt`-Zeichenkette anstelle eines `command` an. Verwenden Sie den Platzhalter `$ARGUMENTS`, um die Hook-Eingabedaten in Ihren Prompt-Text einzufügen.

Dieser `Stop`-Hook fragt das LLM, ob Claude stoppen sollte, bevor Claude beendet wird:

```json theme={null}
{
  "hooks": {
    "Stop": [
      {
        "hooks": [
          {
            "type": "prompt",
            "prompt": "Evaluate if Claude should stop: $ARGUMENTS. Check if all tasks are complete."
          }
        ]
      }
    ]
  }
}
```

| Feld | Erforderlich | Beschreibung |
| :- | :- | :- |
| `type` | ja | Muss `"prompt"` sein |
| `prompt` | ja | Der Prompt-Text zum Senden an das LLM. Verwenden Sie `$ARGUMENTS` als Platzhalter für die Hook-Eingabe JSON. Wenn `$ARGUMENTS` nicht vorhanden ist, wird die Eingabe JSON an den Prompt angehängt |
| `model` | nein | Modell zur Verwendung für die Evaluierung. Standardwert ist das Modell, das Claude Code für [Hintergrundfunktionalität](/docs/de/costs#background-token-usage) verwendet |
| `timeout` | nein | Timeout in Sekunden. Standard: 30 |
| `continueOnBlock` | nein | Bei den Ereignissen, auf die es zutrifft, speist `true` einen `ok: false` Grund an Claude zurück und setzt den Turn fort, anstatt ihn zu beenden. Standard: `false`. Siehe [Response-Schema](#response-schema) für ereignisspezifisches Verhalten |

<h3 id="response-schema">
  Response-Schema
</h3>

Das LLM muss mit JSON antworten, das Folgendes enthält:

```json theme={null}
{
  "ok": true | false,
  "reason": "Explanation for the decision",
  "impossible": true | false
}
```

| Feld | Beschreibung |
| :- | :- |
| `ok` | `true` erlaubt die Aktion. Bei `false` siehe das ereignisspezifische Verhalten unten |
| `reason` | Erforderlich, wenn `ok` `false` ist |
| `impossible` | Optional. Das Modell gibt es mit `ok: false` zurück, wenn es beurteilt, dass die Bedingung niemals erfüllt werden kann. Bei `Stop` und `SubagentStop` lässt Claude Code dann den Turn enden, anstatt den Grund zurückzugeben. Agent-Hooks und andere Ereignisse ignorieren es |

Was bei `ok: false` passiert, hängt vom Ereignis ab:

* `Stop` und `SubagentStop`: der Grund wird an Claude als nächste Anweisung zurückgegeben und der Turn wird fortgesetzt, es sei denn, die Antwort setzt auch `impossible: true`, in welchem Fall Claude Code den Stop zulässt und der Turn endet
* `PreToolUse`: der Tool-Aufruf wird verweigert; standardmäßig endet der Turn und der Verweigerungsgrund wird im Chat als Warnzeile angezeigt. Setzen Sie `continueOnBlock: true`, um den Grund stattdessen an Claude als Tool-Fehler zurückzugeben, damit es anpassen und fortfahren kann, äquivalent zu einem Command-Hook mit `permissionDecision: "deny"`. Vor v2.1.210 wurde der Verweigerungsgrund an Claude als Tool-Fehler zurückgegeben und der Turn wurde fortgesetzt
* `PostToolUse`: standardmäßig endet der Turn und der Grund wird im Chat als Warnzeile angezeigt. Setzen Sie `continueOnBlock: true`, um den Grund an Claude zurückzugeben und den Turn stattdessen fortzusetzen
* `PostToolBatch`, `UserPromptSubmit` und `UserPromptExpansion`: der Turn endet und der Grund wird als Warnzeile angezeigt. Diese Ereignisse beenden den Turn bei `decision: "block"` unabhängig von `continue`
* `PostToolUseFailure` und `TaskCreated`: der Grund wird an Claude als Tool-Fehler zurückgegeben und der Turn wird fortgesetzt, unabhängig von `continueOnBlock`
* `TaskCompleted`: wenn es ausgelöst wird, weil eine Aufgabe während eines Turns als abgeschlossen markiert wird, wird der Grund an Claude als Tool-Fehler zurückgegeben und der Turn wird fortgesetzt, unabhängig von `continueOnBlock`. Wenn es ausgelöst wird, weil ein Teammate stoppt, verhält es sich wie `TeammateIdle` und stoppt den Teammate standardmäßig
* `TeammateIdle`: standardmäßig stoppt der Teammate und der Grund wird als Warnzeile angezeigt. Setzen Sie `continueOnBlock: true`, um den Grund an den Teammate zurückzugeben und ihn stattdessen weiterarbeiten zu lassen
* `PermissionRequest`: `ok: false` hat keine Auswirkung. Um eine Genehmigung von einem Hook zu verweigern, verwenden Sie einen [Command-Hook](#command-hook-fields) mit `hookSpecificOutput.decision.behavior: "deny"`
* `PermissionDenied`: `ok: false` hat keine Auswirkung, da die Verweigerung bereits erfolgt ist. Die einzige Ausgabe, die dieses Ereignis liest, ist `hookSpecificOutput.retry`, die Prompt- und Agent-Hooks nicht setzen können. Sie werden bei diesem Ereignis ausgeführt, aber ihre Ausgabe wird verworfen. Verwenden Sie einen [Command-Hook](#command-hook-fields), um `retry` zurückzugeben

Wenn Sie eine feinere Kontrolle bei einem Ereignis benötigen, verwenden Sie einen [Command-Hook](#command-hook-fields) mit den ereignisspezifischen Feldern, die in [Entscheidungskontrolle](#decision-control) beschrieben sind.

<h3 id="check-multiple-conditions-before-stopping">
  Mehrere Bedingungen vor dem Stoppen überprüfen
</h3>

Dieser `Stop`-Hook verwendet einen detaillierten Prompt, um drei Bedingungen zu überprüfen, bevor Claude stoppen darf. `SubagentStop`-Hooks verwenden das gleiche Format, um zu evaluieren, ob ein [Subagent](/docs/de/sub-agents) stoppen sollte. Wenn das Modell `"ok": false` zurückgibt, weil die Bedingung noch nicht erfüllt ist, setzt Claude die Arbeit mit dem bereitgestellten Grund als nächste Anweisung fort:

```json theme={null}
{
  "hooks": {
    "Stop": [
      {
        "hooks": [
          {
            "type": "prompt",
            "prompt": "You are evaluating whether Claude should stop working. Context: $ARGUMENTS\n\nAnalyze the conversation and determine if:\n1. All user-requested tasks are complete\n2. Any errors need to be addressed\n3. Follow-up work is needed\n\nRespond with JSON: {\"ok\": true} to allow stopping, or {\"ok\": false, \"reason\": \"your explanation\"} to continue working.",
            "timeout": 30
          }
        ]
      }
    ]
  }
}
```

<h2 id="agent-based-hooks">
  Agent-basierte Hooks
</h2>

<Warning>
  Agent-Hooks sind experimentell. Das Verhalten und die Konfiguration können sich in zukünftigen Versionen ändern. Für Produktions-Workflows bevorzugen Sie [Command Hooks](#command-hook-fields).
</Warning>

Agent-basierte Hooks (`type: "agent"`) sind wie Prompt-basierte Hooks, aber mit Multi-Turn-Tool-Zugriff. Anstelle eines einzelnen LLM-Aufrufs spawnt ein Agent-Hook einen Subagenten, der Dateien lesen, Code durchsuchen und die Codebasis überprüfen kann, um Bedingungen zu überprüfen. Agent-Hooks unterstützen die gleichen Ereignisse wie [Prompt-basierte Hooks](#prompt-based-hooks), mit Ausnahme von `PermissionRequest`.

<h3 id="how-agent-hooks-work">
  Wie Agent-Hooks funktionieren
</h3>

Wenn ein Agent-Hook ausgelöst wird:

1. Claude Code spawnt einen Subagenten mit Ihrem Prompt und der Hook-Eingabe JSON
2. Der Subagent kann Tools wie Read, Grep und Glob verwenden, um zu untersuchen
3. Nach bis zu 50 Turns gibt der Subagent eine strukturierte `{ "ok": true/false }`-Entscheidung zurück
4. Claude Code erlaubt die Aktion, wenn `ok` `true` ist. Wenn `ok` `false` ist, verarbeitet Claude Code die Blockierung auf die gleiche Weise wie ein Prompt-Hook mit `continueOnBlock: true` bei diesem Ereignis, wie unter [Response-Schema](#response-schema) aufgelistet

Agent-Hooks sind nützlich, wenn die Überprüfung das Überprüfen tatsächlicher Dateien oder Test-Ausgabe erfordert, nicht nur die Evaluierung der Hook-Eingabedaten allein.

<h3 id="agent-hook-configuration">
  Agent-Hook-Konfiguration
</h3>

Setzen Sie `type` auf `"agent"` und geben Sie eine `prompt`-Zeichenkette an, wobei Sie `$ARGUMENTS` als Platzhalter für die Hook-Eingabe JSON verwenden. Die Konfigurationsfelder sind die gleichen wie [Prompt-Hooks](#prompt-hook-configuration), mit der Ausnahme, dass Agent-Hooks ein längeres Standard-Timeout von 60 Sekunden haben und kein `continueOnBlock`-Feld haben.

Das Response-Schema ist `{ "ok": true }` zum Zulassen oder `{ "ok": false, "reason": "..." }` zum Blockieren. Bei `ok: false` verarbeitet Claude Code einen Agent-Hook auf die gleiche Weise wie einen [Prompt-Hook mit `continueOnBlock: true`](#response-schema) bei demselben Ereignis; Agent-Hooks haben kein `continueOnBlock`-Feld und unterstützen nicht das Prompt-Hook-Feld `impossible`.

Dieser `Stop`-Hook überprüft, dass alle Unit-Tests bestanden sind, bevor Claude fertig ist:

```json theme={null}
{
  "hooks": {
    "Stop": [
      {
        "hooks": [
          {
            "type": "agent",
            "prompt": "Verify that all unit tests pass. Run the test suite and check the results. $ARGUMENTS",
            "timeout": 120
          }
        ]
      }
    ]
  }
}
```

<h2 id="run-hooks-in-the-background">
  Hooks im Hintergrund ausführen
</h2>

Standardmäßig blockieren Hooks die Ausführung von Claude, bis sie abgeschlossen sind. Für lang laufende Aufgaben wie Bereitstellungen, Test-Suites oder externe API-Aufrufe setzen Sie `"async": true`, um den Hook im Hintergrund auszuführen, während Claude weiterarbeitet. Asynchrone Hooks können nicht blockieren oder das Verhalten von Claude steuern: Response-Felder wie `decision`, `permissionDecision` und `continue` haben keine Auswirkung, da die Aktion, die sie steuern würden, bereits abgeschlossen ist.

<h3 id="configure-an-async-hook">
  Konfigurieren Sie einen asynchronen Hook
</h3>

Fügen Sie `"async": true` zur Konfiguration eines Command-Hooks hinzu, um ihn im Hintergrund auszuführen, ohne Claude zu blockieren. Dieses Feld ist nur auf `type: "command"`-Hooks verfügbar.

Dieser Hook führt ein Test-Skript nach jedem `Write`-Tool-Aufruf aus. Claude arbeitet sofort weiter, während `run-tests.sh` ausgeführt wird. Wenn das Skript fertig ist, wird seine Ausgabe beim nächsten Gesprächsturn geliefert:

```json theme={null}
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write",
        "hooks": [
          {
            "type": "command",
            "command": "/path/to/run-tests.sh",
            "async": true
          }
        ]
      }
    ]
  }
}
```

Sobald ein asynchroner Hook im Hintergrund ausgeführt wird, erzwingt Claude Code kein `timeout` darauf. Claude Code erzwingt immer noch `timeout` auf einem Hook, den Sie mit `asyncRewake` ausführen.

Claude Code liefert die Ergebnisse eines asynchronen Hooks nur während der Sitzung:

* Im [nicht-interaktiven Modus](/docs/de/headless) mit dem Flag `-p` beendet Claude Code jeden noch laufenden asynchronen Hook beim Herunterfahren und finalisiert ihn mit dem Ergebnis `cancelled`
* Wenn die Arbeit Ihres Hooks eine `claude -p`-Sitzung überdauern muss, starten Sie einen vollständig abgelösten Prozess davon

<h3 id="how-async-hooks-execute">
  Wie asynchrone Hooks ausgeführt werden
</h3>

Wenn ein asynchroner Hook ausgelöst wird, startet Claude Code den Hook-Prozess und setzt sofort fort, ohne auf den Abschluss zu warten. Der Hook erhält die gleiche JSON-Eingabe über stdin wie ein synchroner Hook.

Nachdem der Hintergrund-Prozess beendet ist, liefert Claude Code die Felder `additionalContext` und `systemMessage` aus der JSON-Response des Hooks Claude beim nächsten Gesprächsturn. Im Gegensatz zu einem synchronen Hook's `systemMessage` wird keines dieser Felder Ihnen angezeigt.

Claude Code validiert diese JSON-Response gegen das gleiche [Ausgabeschema](#json-output) wie synchrone Hooks und verwirft jedes Feld, dessen Wert den falschen Typ hat, wie z. B. eine `systemMessage`, die keine Zeichenkette ist, anstatt es zu liefern. Führen Sie mit `--debug` aus, um eine Warnung zu sehen, die jedes verworfene Feld benennt. Vor v2.1.202 konnte fehlerhafte JSON-Ausgabe von einem asynchronen Hook die Sitzung zum Absturz bringen, und der Absturz trat jedes Mal auf, wenn die Sitzung fortgesetzt wurde.

Benachrichtigungen über den Abschluss asynchroner Hooks werden standardmäßig unterdrückt. Um sie zu sehen, aktivieren Sie den ausführlichen Modus mit `Ctrl+O` oder starten Sie Claude Code mit `--verbose`.

<h3 id="run-tests-after-file-changes">
  Tests nach Dateiänderungen ausführen
</h3>

Dieser Hook startet eine Test-Suite im Hintergrund, wenn Claude eine Datei schreibt, und meldet die Ergebnisse Claude, wenn die Tests fertig sind. Speichern Sie dieses Skript unter `.claude/hooks/run-tests-async.sh` in Ihrem Projekt und machen Sie es mit `chmod +x` ausführbar:

```bash theme={null}
#!/bin/bash
# run-tests-async.sh

# Hook-Eingabe von stdin lesen
INPUT=$(cat)
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty')

# Tests nur für Quelldateien ausführen
if [[ "$FILE_PATH" != *.ts && "$FILE_PATH" != *.js ]]; then
  exit 0
fi

# Tests ausführen und Ergebnisse über additionalContext an Claude melden
RESULT=$(npm test 2>&1)
EXIT_CODE=$?

if [ $EXIT_CODE -eq 0 ]; then
  MSG="Tests passed after editing $FILE_PATH"
else
  MSG="Tests failed after editing $FILE_PATH: $RESULT"
fi
jq -nc --arg msg "$MSG" '{hookSpecificOutput: {hookEventName: "PostToolUse", additionalContext: $msg}}'
```

Fügen Sie dann diese Konfiguration zu `.claude/settings.json` im Projekt-Root hinzu. Das Flag `async: true` ermöglicht es Claude, weiterarbeiten zu können, während Tests ausgeführt werden:

```json theme={null}
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [
          {
            "type": "command",
            "command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/run-tests-async.sh",
            "args": [],
            "async": true
          }
        ]
      }
    ]
  }
}
```

<h3 id="limitations">
  Einschränkungen
</h3>

Asynchrone Hooks haben zusätzliche Einschränkungen im Vergleich zu synchronen Hooks:

* Hook-Ausgabe wird beim nächsten Gesprächsturn geliefert. Wenn die Sitzung untätig ist, wartet die Response, bis die nächste Benutzerinteraktion erfolgt. Ausnahme: Ein `asyncRewake`-Hook, der mit Code 2 beendet wird, weckt Claude sofort auf, auch wenn die Sitzung untätig ist.
* Jede Ausführung erstellt einen separaten Hintergrund-Prozess. Es gibt keine Deduplizierung über mehrere Auslösungen des gleichen asynchronen Hooks.

<h2 id="security-considerations">
  Sicherheitsüberlegungen
</h2>

<h3 id="disclaimer">
  Haftungsausschluss
</h3>

<Warning>
  Command-Hooks führen Shell-Befehle mit Ihren vollständigen Benutzerberechtigungen aus. Sie können alle Dateien ändern, löschen oder zugreifen, auf die Ihr Benutzerkonto zugreifen kann. Überprüfen und testen Sie alle Hook-Befehle, bevor Sie sie zu Ihrer Konfiguration hinzufügen.
</Warning>

<h3 id="workspace-trust">
  Workspace-Vertrauen
</h3>

Claude Code überprüft das Workspace-Vertrauen, bevor es einen Hook aus einer Einstellungsdatei ausführt. Was als vertrauenswürdig gilt, hängt vom Sitzungstyp ab:

* **Interaktive Sitzung**: Claude Code hält Hooks aus jeder Einstellungsdatei zurück, einschließlich Ihrer eigenen `~/.claude/settings.json`, bis Sie den [Workspace-Vertrauensdialog](/docs/de/permissions#project-allow-rules-and-workspace-trust) für den Ordner oder für ein übergeordnetes Verzeichnis, dessen Vertrauen sich darauf erstreckt, akzeptieren
* **`-p` oder SDK-Sitzung**: Claude Code zeigt den Dialog nie an und behandelt den Ordner als vertrauenswürdig, sodass Hooks, die in der `.claude/settings.json` eines Repositorys committed sind, in einem Ordner ausgeführt werden, dem Sie nie vertraut haben

Bevor Sie `claude -p` über ein Repository ausführen, das Sie nicht geschrieben haben, überprüfen Sie seine `.claude/`-Einstellungsdateien, starten Sie mit [`--bare`](/docs/de/headless#start-faster-with-bare-mode), oder [deaktivieren Sie Hooks für diesen Durchlauf](#disable-or-remove-hooks) mit `--settings '{"disableAllHooks": true}'`. Frontmatter-Hooks in einem Projekt-Subagent folgen einer strengeren Regel als Einstellungsdatei-Hooks. [Was vor dem Vertrauen eines Ordners ausgeführt wird](/docs/de/permissions#what-runs-before-you-trust-a-folder) listet jede Art von Repository-Inhalt nach Sitzungstyp auf.

<h3 id="security-best-practices">
  Best Practices für Sicherheit
</h3>

Beachten Sie diese Praktiken beim Schreiben von Hooks:

* **Validieren und bereinigen Sie Eingaben**: Vertrauen Sie niemals blind auf Eingabedaten
* **Zitieren Sie immer Shell-Variablen**: Verwenden Sie `"$VAR"` nicht `$VAR`
* **Blockieren Sie Pfad-Traversal**: Prüfen Sie auf `..` in Dateipfaden
* **Verwenden Sie absolute Pfade**: Geben Sie vollständige Pfade für Skripte an. In der Exec-Form verwenden Sie `${CLAUDE_PROJECT_DIR}` und der Pfad benötigt keine Anführungszeichen. In der Shell-Form wickeln Sie ihn in doppelte Anführungszeichen ein
* **Überspringen Sie sensible Dateien**: Vermeiden Sie `.env`, `.git/`, Schlüssel, etc.

<h2 id="windows-powershell-tool">
  Windows PowerShell-Tool
</h2>

Unter Windows können Sie einzelne Hooks in PowerShell ausführen, indem Sie `"shell": "powershell"` auf einem Command-Hook setzen. Claude Code erkennt automatisch `pwsh.exe`, die PowerShell 7 und später ausführbare Datei, und fällt auf `powershell.exe` für Windows PowerShell 5.1 zurück.

```json theme={null}
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write",
        "hooks": [
          {
            "type": "command",
            "shell": "powershell",
            "command": "Write-Host 'File written'"
          }
        ]
      }
    ]
  }
}
```

Um auf das Projektverzeichnis aus einem PowerShell-Shell-Form-Befehl zu verweisen, schreiben Sie `${CLAUDE_PROJECT_DIR}` oder `$env:CLAUDE_PROJECT_DIR`. Claude Code schreibt die Platzhalter `${CLAUDE_PROJECT_DIR}`, `${CLAUDE_PLUGIN_ROOT}` und `${CLAUDE_PLUGIN_DATA}` in einem PowerShell-Shell-Form-Befehl in die PowerShell-Form `${env:NAME}` um, unabhängig davon, ob der Hook in `settings.json`, einem Plugin oder einem Skill definiert ist. PowerShell löst dann den Wert aus der exportierten Umgebung nach dem Parsing auf, daher funktioniert der Platzhalter in doppelt angeführten Zeichenketten, aber nicht in einfach angeführten Zeichenketten, wo PowerShell niemals Variablen erweitert.

Schreiben Sie nicht die bloße Schreibweise `$CLAUDE_PROJECT_DIR` in einem PowerShell-Hook. PowerShell analysiert sie als undefinierte lokale Variable und löst sie zu `$null` auf, was den Skriptpfad ohne sein Projektverzeichnis-Präfix hinterlässt. Claude Code schreibt diese Form nicht um; stattdessen protokolliert es eine Warnung im [Debug-Log](#debug-hooks).

Das folgende Beispiel zeigt einen `settings.json`-Hook, der ein Projektskript mit der Form `$env:` ausführt:

```json theme={null}
{
  "type": "command",
  "shell": "powershell",
  "command": "& \"$env:CLAUDE_PROJECT_DIR\\.claude\\hooks\\check.ps1\""
}
```

<h2 id="debug-hooks">
  Debug-Hooks
</h2>

Hook-Ausführungsdetails werden in die Debug-Log-Datei geschrieben. Starten Sie Claude Code mit `claude --debug-file <path>`, um das Log in einen bekannten Speicherort zu schreiben, oder führen Sie `claude --debug` aus und lesen Sie das Log unter `~/.claude/debug/<session-id>.txt`. Das Flag `--debug` gibt nicht auf dem Terminal aus.

Beispielsweise erzeugt ein `PostToolUse`-Hook auf `Write`, dessen Befehl `hook-ran` ausgibt, Einträge wie:

```text theme={null}
2026-07-19T02:03:24.382Z [DEBUG] Hook output does not start with {, treating as plain text
2026-07-19T02:03:24.382Z [DEBUG] "Hook PostToolUse:Write (PostToolUse) success:\nhook-ran"
```

Für granularere Hook-Matching-Details setzen Sie `CLAUDE_CODE_DEBUG_LOG_LEVEL=verbose`, um zusätzliche Log-Zeilen wie Hook-Matcher-Zählungen und Query-Matching zu sehen.

Zur Fehlerbehebung häufiger Probleme wie Hooks, die nicht ausgelöst werden, Stop-Hooks, die weiterhin blockieren, oder Konfigurationsfehler, siehe [Einschränkungen und Fehlerbehebung](/docs/de/hooks-guide#limitations-and-troubleshooting) in der Anleitung. Für eine umfassendere diagnostische Anleitung, die `/context`, `/doctor` und Einstellungspriorität abdeckt, siehe [Debug your config](/docs/de/debug-your-config).
