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

# Verwenden Sie die mods API

> Rufen Sie die mods API aus einem Claude Code Mod auf, um Befehle und Tools hinzuzufügen, ein Modell aufzurufen, Arbeiten auf einem Timer auszuführen, Nachrichten an andere Sitzungen zu senden und auf Dateien und das Netzwerk zuzugreifen.

Die mods API ist die Menge von Methoden, die ein Mod aufruft, um zu handeln: Befehle und Tools hinzufügen, ein Modell aufrufen, Arbeiten zwischen Ereignissen ausführen und auf das Dateisystem, Prozesse und das Netzwerk zugreifen. Jeder Hook erhält sie als sein erstes Argument, `$`, mit den Methoden in Namespaces wie `$.ui` und `$.fs` gruppiert. [Ereignisse](/docs/de/plugins/mods/events) entscheiden, wann ein Hook ausgeführt wird, und die mods API ist das, was der Hook aufruft, sobald er dies tut.

Erstellen Sie Ihren [ersten Mod](/docs/de/plugins/mods/create), bevor Sie hier beginnen. Für jede Methode siehe [mods API Methoden](/docs/de/plugins/mods/reference#mods-api-methods) oder lesen Sie [die Typen für Ihren Build](/docs/de/plugins/mods/create#get-the-types-for-your-build).

<h2 id="add-a-command-or-a-tool">
  Fügen Sie einen Befehl oder ein Tool hinzu
</h2>

Ein Mod kann einen Befehl hinzufügen, den der Benutzer ausführen kann, und ein Tool, das Claude aufrufen kann. Registrieren Sie beide in einem [`session.start`](/docs/de/plugins/mods/reference#session) Hook. Claude Code wartet auf diesen Hook vor der ersten Eingabeaufforderung, sodass das, was Sie registrieren, ab der ersten Runde verfügbar ist.

<h3 id="add-a-command">
  Fügen Sie einen Befehl hinzu
</h3>

Ein Befehl ist für den Benutzer. Registrieren Sie ihn und behandeln Sie dann [`command.run`](/docs/de/plugins/mods/reference#commands-and-configuration) für seinen Namen. Dieses Beispiel fügt einen `/standup` Befehl hinzu, der eine optionale Anzahl von Tagen akzeptiert:

```javascript theme={null}
on('session.start', async ($, e, next) => {
  // Add /standup to the command list, with the description the user sees there
  await $.command.register({ name: 'standup', description: 'Summarize what changed today', argumentHint: '[days]' })
  return next(e)
})

// The matcher limits the hook to /standup, so other commands don't reach it
on('command.run', { command: 'standup' }, async ($, e) => {
  // e.args is the text typed after the command name, or an empty string
  return { text: 'Summary for the last ' + (e.args || '1') + ' day(s): ...' }
})
```

Nach dem Start der Sitzung erscheint `/standup` mit seiner Beschreibung in der Liste, die Sie sehen, wenn Sie `/` eingeben. Der `argumentHint` wird in der Eingabeaufforderung angezeigt, nachdem Sie den Befehl und ein Leerzeichen eingeben, wie in `/standup [days]`. Wenn Sie `/standup 3` ausführen, gibt der zweite Hook `Summary for the last 3 day(s): ...` zurück, und das Transkript zeigt diesen Text nach dem Namen des Plugins. Der Hook ruft niemals `next` auf, da der Befehl kein anderes Verhalten als Ihres hat.

Der `text`, den Sie zurückgeben, wird im Transkript gedruckt und Claude liest ihn. Um nichts zu drucken, wie ein Befehl, der nur einen [Bereich](/docs/de/plugins/mods/interface#pick-where-to-draw) öffnet, geben Sie `{}` zurück. Um den Befehl auszuführen, während Claude arbeitet, fügen Sie `immediate: true` zur Registrierung hinzu.

Wählen Sie einen Namen, den kein integrierter Befehl verwendet. Geben Sie `/` in einer Sitzung ein, um sie zu sehen. `$.command.register` wirft einen Fehler für einen verwendeten Namen mit einer Nachricht wie `"/focus" refused: it is the built-in /focus"`. Ein Hook, der einen Fehler wirft, wird übersprungen, sodass der Rest Ihres `session.start` Hooks auch nicht ausgeführt wird. Registrieren Sie Befehle zuletzt in diesem Hook oder wickeln Sie den Aufruf in `try` und `catch`.

<h3 id="add-a-tool">
  Fügen Sie ein Tool hinzu
</h3>

Ein Tool ist für Claude. Registrieren Sie es mit einem Namen, einer Beschreibung, die Claude liest, und einem JSON Schema für seine Eingabe. Claude sieht es unter einem längeren Namen, der aus `mcp__`, dem Namen Ihres Plugins, zwei Unterstrichen und dem Namen besteht, den Sie registriert haben. Sie behandeln seine Aufrufe in einem [`tool.call`](/docs/de/plugins/mods/events#guard-or-change-a-tool-call) Hook, der auf diesen vollständigen Namen gefiltert ist. Dieses Beispiel aus einem Plugin namens `my-mod` registriert `ticket`, sodass der vollständige Name `mcp__my-mod__ticket` ist. Es gibt Claude ein Tool, das ein Ticket in einem Issue-Tracker nachschlägt:

```javascript theme={null}
on('session.start', async ($, e, next) => {
  await $.tool.register({
    name: 'ticket',
    // Claude decides when to call the tool from this description
    description: 'Look up a ticket by its id and return its title and status',
    // The arguments Claude has to send: one required string named id
    inputSchema: { type: 'object', properties: { id: { type: 'string' } }, required: ['id'] },
  })
  return next(e)
})

// The full tool name is mcp__, the plugin's name, and the registered name
on('tool.call', { tool: 'mcp__my-mod__ticket' }, async ($, e) => {
  // The tool's arguments are fields of e, so the id is e.id
  const response = await $.http.fetch('https://tickets.example.com/api/' + encodeURIComponent(e.id))
  // Return a result either way, so Claude learns when the lookup failed
  return { result: response.ok ? response.text : 'Lookup failed with status ' + response.status }
})
```

Wenn Sie nach einem Ticket fragen, kann Claude `mcp__my-mod__ticket` mit seiner ID aufrufen. Der zweite Hook ruft das Ticket ab und gibt den Antwortkörper zurück, den Claude als Ergebnis des Tools liest. Wenn der Server mit einem Fehlerstatus antwortet, liest Claude `Lookup failed with status` und die Nummer.

<h2 id="call-a-model">
  Rufen Sie ein Modell auf
</h2>

Ein Mod kann ein Modell eine Frage stellen, außerhalb des Gesprächs, für eine kleine Aufgabe wie das Sortieren oder Zusammenfassen eines Textstücks. `$.model.complete` sendet eine Eingabeaufforderung an ein Modell mit den Anmeldedaten Ihrer Sitzung und wird in die Antwort aufgelöst. Es hat keine Gesprächsverlauf.

Dieser Hook beantwortet einen `/triage` Befehl, [registriert als Befehl](#add-a-command), indem er ein kleines Modell fragt, den nach dem Befehl eingegebenen Text zu kennzeichnen:

```javascript theme={null}
on('command.run', { command: 'triage' }, async ($, e) => {
  const r = await $.model.complete({
    model: 'haiku',
    // The system prompt sets the job, and the prompt carries the text to label
    system: 'Reply with one word: bug, feature, or question.',
    prompt: e.args,
    // One word needs few tokens, and the call gives up after 15 seconds
    maxTokens: 20,
    timeoutMs: 15000,
  })
  // r.text exists only when the model answered, so check r.isAnswered first
  const label = r.isAnswered ? r.text.trim() : 'unknown'
  return { text: 'Label: ' + label }
})
```

Wenn Sie `/triage the export button does nothing` ausführen, sendet der Mod diesen Text an das Modell und druckt seine Antwort, wie `Label: bug`. Claudes Gespräch ist nicht Teil der Anfrage. Wenn das Modell nicht antwortet, ist die Bezeichnung `unknown`.

Ein Claude API Fehler lehnt den Aufruf nicht ab, daher überprüfen Sie `r.isAnswered` und lesen Sie `r.reason`, wenn es `false` ist. Der Aufruf lehnt nur für eine Anfrage ab, die Claude Code nicht sendet, wie ein Modell, das Ihre Organisation blockiert. [Die Typen für Ihren Build](/docs/de/plugins/mods/create#get-the-types-for-your-build) listen die anderen Optionen auf, wie `effort`, und die [Limits](/docs/de/plugins/mods/reference#limits) geben den `maxTokens` Standard an.

`$.model.fork({ prompt })` stellt stattdessen eine Frage über das aktuelle Gespräch, mit demselben Modell und Systemaufforderung, sodass die Claude API die meisten davon aus dem Prompt Cache bedient.

Diese Aufrufe verwenden den Plan oder API-Schlüssel des Benutzers.

<h2 id="run-work-in-the-background">
  Führen Sie Arbeiten im Hintergrund aus
</h2>

Arbeiten, die ein Ereignis überdauern, wie das Überprüfen von etwas einmal pro Minute, laufen auf einem Timer, den Sie von `session.start` starten. Ein Hook selbst läuft für ein Ereignis und hat ein Zeitlimit von 10 Sekunden seiner eigenen Laufzeit. Die Zeit, die auf `next` oder auf einen mods API Aufruf wartet, zählt nicht, außer einem `$.clock.sleep`. `$.clock.every` und `$.clock.after` ersetzen `setInterval` und `setTimeout`, mit der Verzögerung in Millisekunden zuerst: `$.clock.after(5000, fn)` ruft `fn` einmal auf, fünf Sekunden von jetzt an. Jeder gibt einen Timer mit einer `cancel()` Methode zurück, und `await $.clock.now()` gibt die Zeit in Millisekunden an.

Dieser Hook schlägt die Überprüfungen eines Pull Requests einmal pro Minute nach und zeigt das Ergebnis unter der Eingabeaufforderung an. `summarize` ist eine Funktion Ihres eigenen, die die JSON-Ausgabe des Befehls in ein paar Wörter umwandelt:

```javascript theme={null}
on('session.start', async ($, e, next) => {
  // Call the function every 60,000 milliseconds, starting one minute from now
  $.clock.every(60_000, async () => {
    const status = await $.process.run(['gh', 'pr', 'checks', '--json', 'state'])
    // Replace the line under the prompt with the latest summary
    $.ui.status('checks: ' + summarize(status.stdout))
  })
  // Return without waiting for the timer, so the session starts right away
  return next(e)
})
```

Die Sitzung startet wie gewohnt. Eine Minute später erscheint eine Zeile unter der Eingabeaufforderung mit einem `⚠`, dem Namen des Mods und dann `checks:` und Ihrer Zusammenfassung. Sie wird einmal pro Minute danach ersetzt. Der Callback des Timers läuft außerhalb eines Ereignisses, sodass er zwischen Runden weiterläuft und keinen startet. Wenn der Callback einen Fehler wirft, geht der Fehler zum [Debug-Protokoll](/docs/de/plugins/mods/troubleshoot#read-the-debug-log) und der Timer läuft beim nächsten Intervall erneut.

<h3 id="show-something-without-starting-a-turn">
  Zeigen Sie etwas an, ohne eine Runde zu starten
</h3>

Ein Hintergrund-Job kann dem Benutzer etwas anzeigen, ohne eine Runde zu starten. Jeder dieser Aufrufe setzt Text an einen anderen Ort:

| Aufruf | Was der Benutzer sieht |
| :- | :- |
| `$.ui.status(text)` | Eine Zeile unter der Eingabeaufforderung, die bleibt, bis Sie sie ändern. Sie beginnt mit `⚠` und dem Namen des Mods, wie in `⚠ my-mod: checks: 3 passing`. |
| `$.ui.toast(text)` | Ein kleines Feld oben rechts, mit dem Namen des Mods über dem Text, das nach ein paar Sekunden verschwindet |
| `$.ui.log(text)` | Eine schwache Zeile im Transkript, die Claude nicht liest. Sie beginnt mit `●` und dem Namen des Mods, wie in `● my-mod: build finished`. |

<h3 id="start-a-turn-from-a-background-job">
  Starten Sie eine Runde aus einem Hintergrund-Job
</h3>

Wenn ein Hintergrund-Job etwas findet, das Claudes Aufmerksamkeit benötigt, kann er eine Runde starten, indem er eine Eingabeaufforderung mit `$.prompt.submit({ text })` einreicht. Claude liest den Text nach einem Satz, der Ihren Mod als Absender benennt. Um ihn als die eigenen Worte des Benutzers zu senden, ohne diesen Satz, fügen Sie `asUser: true` hinzu. Der Aufruf wartet, bis die Sitzung untätig ist, und startet dann eine neue Runde. Er wird aufgelöst, wenn diese Runde startet, daher `await` ihn nicht in einem Handler, der läuft, während Claude arbeitet.

<h3 id="stop-background-work">
  Beenden Sie Hintergrund-Arbeiten
</h3>

Hintergrund-Arbeiten enden auf zwei Arten. Timer enden, wenn das Modul neu geladen wird. Für lang laufende Arbeiten in einem Hook ist [`next.signal`](/docs/de/plugins/mods/reference#the-hook-function) ein `AbortSignal`, das abbricht, wenn das Ereignis, das Ihr Hook behandelt, aufgegeben wird, zum Beispiel wenn der Benutzer unterbricht, daher übergeben Sie es an alles, das lang läuft.

<h2 id="send-and-receive-messages-between-sessions">
  Senden und empfangen Sie Nachrichten zwischen Sitzungen
</h2>

Ein Mod kann eine Klartextnachricht an eine andere Ihrer Sitzungen oder an einen der Subagenten dieser Sitzung senden und die Nachrichten beobachten, die ankommen und gehen. `$.session.send({ to, text })` sendet eine, die gleiche Lieferung, die das SendMessage Tool macht. `to` ist `{ sessionId }` für eine Sitzung, `{ agentId }` für einen Subagenten von `$.agent.list()` oder die Zeichenkettenadresse, von der eine empfangene Nachricht kam. Der Aufruf wird aufgelöst, sobald die Nachricht in die Warteschlange eingereiht ist, mit `{ isDelivered: true }`. Wenn nichts geliefert wurde, wird es mit `{ isDelivered: false, reason }` aufgelöst, und `reason` sagt, warum.

Dieser Hook beantwortet einen `/ping` Befehl, [registriert als Befehl](#add-a-command), indem er die Sitzung fragt, deren ID Sie nach ihm eingeben, um einen Status zu erhalten:

```javascript theme={null}
on('command.run', { command: 'ping' }, async ($, e) => {
  // e.args is the session id typed after /ping
  const sent = await $.session.send({ to: { sessionId: e.args }, text: 'Status? One line.' })
  // The call resolves either way, so check isDelivered to learn what happened
  if (!sent.isDelivered) $.ui.toast('Not delivered: ' + sent.reason)
  // An empty result prints nothing in this session's transcript
  return {}
})
```

Wenn die Nachricht in die Warteschlange eingereiht wird, erscheint nichts in Ihrer Sitzung, und Claudes andere Sitzung liest `Status? One line.` Wenn nichts geliefert wurde, gibt ein kleines Feld oben rechts den Grund an und verschwindet nach ein paar Sekunden.

Zwei Ereignisse lassen einen Mod die Nachrichten beobachten. Geben Sie `next(e)` von beiden zurück, um jede Nachricht unverändert durchzuleiten:

| Ereignis | Wird ausgelöst, wenn | Nützliche Felder |
| :- | :- | :- |
| `session.receive` | Eine Nachricht kommt für diese Sitzung an, bevor Claude sie liest | `e.text` und `e.origin.kind`, wie `peer` oder `peer-send-message` für eine andere Sitzung oder einen Agenten, `task-notification` oder `scheduled-trigger`. Geben Sie `{ consumed: reason }` zurück, um sie von Claude fernzuhalten. |
| `session.send` | Eine Nachricht ist dabei zu gehen, vom SendMessage Tool oder einem Mod | `e.to`, `e.text` und `e.origin.kind`, das `model` oder `plugin` ist |

Eine Sitzung, die auf [eingehende Nachrichten ablehnen](/docs/de/cross-session-messaging#control-inbound-messages) eingestellt ist, lehnt eine Nachricht ab, bevor `session.receive` ausgelöst wird, daher sieht ein Hook sie nie. Eine Nachricht, die für Ihre Genehmigung gehalten wird, erreicht zuerst den Hook, daher kann ein Mod eine Nachricht lesen, die Sie noch nicht genehmigt haben. Der `next(e)` des Hooks lehnt ab, wenn die Nachricht nicht geliefert wird.

Der Name des Absenders auf einer empfangenen Nachricht ist das, was der Absender geschrieben hat, daher treffen Sie keine Entscheidung darauf.

<h2 id="reach-files-processes-and-the-network">
  Erreichen Sie Dateien, Prozesse und das Netzwerk
</h2>

Ein Mod erreicht das Dateisystem, Prozesse und das Netzwerk durch die mods API, mit den gleichen Berechtigungen wie der Benutzer, der Claude Code ausführt. Das Hooks-Modul selbst hat keine Node.js APIs, keine Timer-Globale wie `setTimeout` und keinen Netzwerk- oder Dateizugriff. Standard-JavaScript und Web-APIs wie `URL`, `TextEncoder`, `AbortController` und `crypto.subtle` sind verfügbar. Jeder Namespace unten behandelt eine Art von Zugriff:

| Namespace | Was es tut |
| :- | :- |
| `$.fs` | `read(path)`, `write(path, text)`, `exists(path)`, `stat(path)` und `list(path)` arbeiten mit Dateien und Verzeichnissen |
| `$.process` | `run(['git', 'status'])` startet einen Befehl und wird aufgelöst, wenn er beendet wird. `spawn` streamt die Ausgabe eines lang laufenden Befehls. |
| `$.http` | `fetch(url, init)` über `http` oder `https`. Es wird aufgelöst zu `{ status, ok, headers, text }`, sobald der Körper gelesen wird. |
| `$.store` | Ein JSON-Schlüssel-Wert-Speicher Ihres eigenen Plugins, der zwischen Sitzungen beibehalten wird |
| `$.env` | `get` und `set` Umgebungsvariablen. Schreiben Sie den Namen als Literalzeichenkette. |
| `$.settings` | `read` was die Einstellungsdateien und verwaltete Richtlinie halten |
| `$.session` | `messages()` gibt das Transkript als eine Liste von `{ role, text, toolUses }` zurück. Auch das Arbeitsverzeichnis, Modell und mehr. [`usage()`](/docs/de/plugins/mods/reference#mods-api-methods) gibt die Nutzung des Kontextfensters und Planlimits zurück. |
| `$.mcp` | `call` ein Tool auf einem verbundenen MCP Server |

Dateien und Prozesse haben ein paar Regeln ihrer eigenen:

* **Pfade**: ein relativer Pfad ist unter dem Arbeitsverzeichnis der Sitzung
* **`$.fs.list`**: gibt die Einträge eines Verzeichnisses als `{ name, kind, size, isLink }` zurück und steigt nicht in Unterverzeichnisse ab
* **`$.process.run`**: nimmt eine Argumentliste und verwendet keine Shell. Es wird aufgelöst zu `{ exitCode, stdout, stderr }` unabhängig vom Exit-Code. Es lehnt ab, wenn das Programm nicht starten kann oder beim Timeout noch läuft, das standardmäßig 30 Sekunden beträgt, daher wickeln Sie es in `try` und `catch`.

Jeder dieser Aufrufe ist selbst ein Ereignis, benannt nach seinem Namespace und seiner Methode ohne das `$.`, wie `fs.read` für `$.fs.read`. Ein Mod [früher in der Kette](/docs/de/plugins/mods/events#the-order-mods-run-in) kann Ihren Aufruf beobachten, umschreiben oder ablehnen, was ist, wie eine Organisation einschränkt, was Mods erreichen.

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

* [Reagieren Sie auf Ereignisse](/docs/de/plugins/mods/events): Hook Tool-Aufrufe, Eingabeaufforderungen und Runden
* [Zeichnen Sie in der Benutzeroberfläche](/docs/de/plugins/mods/interface): zeigen Sie, was Ihr Mod sammelt, in einem Bereich oder über der Eingabeaufforderung
* [Testen Sie einen Mod](/docs/de/plugins/mods/test): stub jeden dieser Aufrufe in einem Test
* [Mods Referenz](/docs/de/plugins/mods/reference): jedes Ereignis, jede mods API Methode und die Limits
