SpyBara
Go Premium

plugins/mods/api.md 2026-10-08 22:58 UTC to 2026-10-09 21:01 UTC

This page contains 106 additions and 7 deletions.

2026
Thu 1 23:59 Fri 2 22:59 Thu 8 22:58 Fri 9 22:01

Die Mods-API verwenden

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

Die Mods-API ist die Menge der Methoden, die ein Mod aufruft, um zu handeln: Befehle und Tools hinzufügen, ein Modell aufrufen, Arbeit zwischen Events ausführen und auf das Dateisystem, Prozesse und das Netzwerk zugreifen. Jeder Hook erhält sie als erstes Argument, $, wobei die Methoden in Namespaces wie $.ui und $.fs gruppiert sind. Events entscheiden, wann ein Hook ausgeführt wird, und die Mods-API ist das, was der Hook aufruft, sobald er ausgeführt wird.

Erstellen Sie Ihren ersten Mod, bevor Sie hier beginnen. Informationen zu allen Methoden finden Sie unter Methoden der Mods-API, oder lesen Sie die Typen für Ihren Build.

Einen Befehl oder ein Tool hinzufügen

Ein Mod kann einen Befehl hinzufügen, den der Benutzer ausführt, und ein Tool, das Claude aufruft. Registrieren Sie beides in einem session.start-Hook. Claude Code wartet vor dem ersten Prompt auf diesen Hook, sodass das, was Sie registrieren, ab dem ersten Turn verfügbar ist.

Einen Befehl hinzufügen

Ein Befehl ist für den Benutzer gedacht. Registrieren Sie ihn und behandeln Sie dann command.run für seinen Namen. Dieses Beispiel fügt einen Befehl /standup hinzu, der eine optionale Anzahl von Tagen entgegennimmt:

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 im Eingabefeld angezeigt, nachdem Sie den Befehl und ein Leerzeichen eingegeben haben, etwa /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 an. Der Hook ruft next nie auf, da der Befehl kein anderes Verhalten als Ihres hat.

Der von Ihnen zurückgegebene text wird im Transkript ausgegeben, und Claude liest ihn. Um nichts auszugeben, wie bei einem Befehl, der nur ein Pane öffnet, geben Sie {} zurück. Damit der Befehl ausgeführt werden kann, während Claude arbeitet, fügen Sie der Registrierung immediate: true hinzu.

Wählen Sie einen Namen, den kein integrierter Befehl verwendet. Geben Sie in einer Sitzung / ein, um diese zu sehen. $.command.register löst bei einem bereits vergebenen Namen einen Fehler aus, mit einer Meldung wie "/focus" refused: it is the built-in /focus. Ein Hook, der einen Fehler auslöst, wird übersprungen, sodass auch der Rest Ihres session.start-Hooks nicht ausgeführt wird. Registrieren Sie Befehle zuletzt in diesem Hook, oder umschließen Sie den Aufruf mit try und catch.

Ein Tool hinzufügen

Ein Tool ist für Claude gedacht. 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 sich aus mcp__, dem Namen Ihres Plugins, zwei Unterstrichen und dem registrierten Namen zusammensetzt. Seine Aufrufe behandeln Sie in einem tool.call-Hook, der auf diesen vollständigen Namen gefiltert ist. Dieses Beispiel aus einem Plugin namens my-mod registriert ticket, der vollständige Name lautet also mcp__my-mod__ticket. Es gibt Claude ein Tool, das ein Ticket in einem Issue-Tracker nachschlägt:

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 dessen ID aufrufen. Der zweite Hook ruft das Ticket ab und gibt den Response-Body 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.

Ein Modell aufrufen

Ein Mod kann eigene Anfragen an ein Modell senden, um eine kleine Aufgabe wie das Klassifizieren oder Zusammenfassen eines Textes zu erledigen. $.model.complete sendet Ihren Prompt für sich allein, und $.model.fork({ prompt }) sendet die aktuelle Konversation mit Ihrem Prompt am Ende.

Diese Tabelle vergleicht, was jede Anfrage enthält:

In der Anfrage $.model.complete $.model.fork
Modell Das model, das Sie übergeben Das Modell der Sitzung
System-Prompt Ein kurzer Attributionsblock, danach Ihr system, falls Sie eines übergeben Der System-Prompt der Sitzung
Nachrichten Eine Benutzernachricht, Ihr prompt Die bisherige Konversation, danach Ihr prompt als Benutzernachricht
CLAUDE.md und anderer Projektkontext Nicht enthalten Enthalten, wie in der letzten Anfrage der Konversation
Tools Keine Die Tools von Claude, die das Modell nicht aufrufen kann

Ein Fork wiederholt die letzte Anfrage der Konversation, sodass die Claude API den Großteil davon aus dem Prompt-Cache bedient, solange die Konversation noch im Cache liegt.

Beide Aufrufe nutzen die Anmeldedaten der Sitzung, sodass sie über den Plan, den API-Schlüssel oder den Cloud-Anbieter des Benutzers abgerechnet werden. Die Typen für Ihren Build dokumentieren jede $.model-Methode.

Einen einzelnen Prompt senden

Übergeben Sie model und prompt an $.model.complete. prompt wird zur Benutzernachricht. Um dem Modell Anweisungen zu geben, etwa eine Rolle oder ein Ausgabeformat, übergeben Sie zusätzlich system, das zum System-Prompt wird.

Dieser Hook beantwortet einen /triage-Befehl, der als Befehl registriert ist, indem er ein kleines Modell bittet, den danach eingegebenen Text zu kennzeichnen:

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 gibt dessen Antwort aus, etwa Label: bug. Wenn das Modell nicht antwortet, lautet die Kennzeichnung unknown.

Ein Fehler der Claude API führt nicht zur Ablehnung des Aufrufs. Prüfen Sie daher r.isAnswered und lesen Sie r.reason, wenn der Wert false ist. Der Aufruf wird bei einer Anfrage abgelehnt, die Claude Code nicht sendet, etwa bei einem Modell, das Ihre Organisation blockiert.

Die Typen für Ihren Build listen die weiteren Optionen auf, etwa effort, und die Limits nennen den Standardwert für maxTokens.

Prompt-Caching verwenden

$.model.complete unterstützt das Prompt-Caching der Claude API. Die API speichert den Anfang einer Anfrage, das sogenannte Präfix, bis zu einem von Ihnen gesetzten Cache-Breakpoint im Cache. Wenn jeder Aufruf mit demselben langen statischen Inhalt beginnt, etwa Anweisungen oder Referenzmaterial, setzen Sie einen Breakpoint am Ende dieses Inhalts. Spätere Aufrufe lesen ihn dann aus dem Cache, statt dafür den vollen Eingabepreis zu zahlen.

Um einen Breakpoint zu setzen, übergeben Sie prompt als Array von { text }-Blöcken statt als String und fügen dem letzten Block des statischen Inhalts cache: true hinzu. Claude Code sendet diesen Block mit dem Feld cache_control der API. system akzeptiert dieselbe Array-Form. Wie Sie sich zwischen beiden entscheiden, erfahren Sie unter Zwischen prompt und system wählen.

Diese Version des /triage-Hooks sendet vor dem zu kennzeichnenden Text einen langen Satz von Kennzeichnungsregeln, mit einem Breakpoint nach den Regeln. RULES ist ein eigener String:

on('command.run', { command: 'triage' }, async ($, e) => {
  const r = await $.model.complete({
    model: 'haiku',
    prompt: [
      // Identical on every call, so it forms the cached prefix
      { text: RULES, cache: true },
      // Changes on every call, so it goes after the breakpoint
      { text: e.args },
    ],
  })
  return { text: 'Label: ' + (r.isAnswered ? r.text.trim() : 'unknown') }
})

Für die TTL und die Anzahl der Breakpoints gelten diese Limits:

  • TTL: Ein Cache-Eintrag bleibt nach seiner letzten Verwendung fünf Minuten lang bestehen. Die TTL stammt aus den Claude Code-Einstellungen des Benutzers, nicht aus dem Aufruf. Für eine Stunde setzen Sie subagentPromptCacheTtl auf 1h.
  • Breakpoints pro Anfrage: Die API akzeptiert bis zu vier, und ein weiterer kommt als api-error in r.reason zurück

Zwischen `prompt` und `system` wählen

Platzieren Sie den statischen Inhalt, den Ihre Aufrufe gemeinsam haben, am Anfang von prompt, es sei denn, Sie wissen, dass Ihre Anfragen direkt an die Claude API gehen:

  • Direkt an die Claude API, mit einem API-Schlüssel oder einem Claude-Abonnement: Beide Felder funktionieren
  • Über Amazon Bedrock, Claude Platform on AWS, Google Cloud's Agent Platform, Microsoft Foundry oder ein LLM-Gateway: Verwenden Sie prompt. Claude Code beginnt den System-Prompt mit einem Attributionsblock, dessen Fingerabdruck aus dem Anfang der Benutzernachricht stammt. Der Endpunkt api.anthropic.com entfernt diesen Block vor dem Caching. Andere Endpunkte erhalten ihn als Teil des Prompts, sodass ein Breakpoint in system den Cache verfehlen kann, wenn prompt anders beginnt.
  • In einem Mod, den andere Personen ausführen: Verwenden Sie prompt, da Sie deren Anbieter nicht auswählen

system steht im Präfix vor prompt, sodass ein Breakpoint in prompt auch system abdeckt und ein Aufruf mit einem anderen system den Cache verfehlt.

Auf Cache-Treffer prüfen

Das Ergebnis von $.model.complete enthält ein usage-Objekt mit den Cache-Feldern der API. usage.cache_creation_input_tokens zählt die Token, die der Aufruf in den Cache geschrieben hat, und usage.cache_read_input_tokens zählt die Token, die er aus dem Cache gelesen hat. Erwarten Sie beim ersten Aufruf einen Schreibvorgang und bei späteren Aufrufen innerhalb der TTL Lesevorgänge.

Wenn jeder Aufruf schreibt und keiner liest, unterscheidet sich das Präfix zwischen den Aufrufen oder die Aufrufe liegen weiter auseinander als die TTL. Für ein abweichendes Präfix siehe Zwischen prompt und system wählen.

Wenn beide Felder bei Aufrufen, die das Modell beantwortet hat, auf null bleiben, wurde nichts zwischengespeichert. Prüfen Sie jede dieser Ursachen:

Was ein `model.complete`-Hook erhält

Wenn Sie sich in das Event model.complete einklinken, um die Anfragen anderer Mods zu prüfen oder zu ändern, lesen Sie den Text aus diesen Feldern:

  • e.prompt: immer ein String. Wenn der Aufrufer ein Array übergeben hat, ist es der Text der Blöcke, in Reihenfolge aneinandergehängt.
  • e.system: ein auf dieselbe Weise gebildeter String oder nicht vorhanden, wenn der Aufrufer kein system übergeben hat
  • e.promptBlocks und e.systemBlocks: die Arrays des Aufrufers, jeweils vorhanden, wenn der Aufrufer für dieses Feld ein Array übergeben hat

Claude Code sendet die Strings, die Ihr Hook an next übergibt, und verwendet die Arrays, die Sie mit ihnen übergeben, um Cache-Breakpoints zu platzieren. Es behält die führenden Blöcke, die noch mit dem Anfang des Strings übereinstimmen, samt ihren Breakpoints bei und sendet den Rest des Strings ohne Breakpoint. Beispielsweise behält next({ ...e, prompt: e.prompt + NOTE }) die Breakpoints des Aufrufers bei, während ein Hook, der den Anfang von prompt ändert, sie entfernt.

Arbeit im Hintergrund ausführen

Arbeit, die länger als ein einzelnes Event dauert, etwa eine Prüfung einmal pro Minute, läuft über einen Timer, den Sie in session.start starten. Ein Hook selbst läuft für ein Event und hat ein Zeitlimit für seine eigene Ausführungszeit. Zeit, die mit dem Warten auf next oder auf einen Aufruf der Mods-API verbracht wird, zählt nicht, mit Ausnahme von $.clock.sleep. $.clock.every und $.clock.after ersetzen setInterval und setTimeout, wobei die Verzögerung in Millisekunden zuerst angegeben wird: $.clock.after(5000, fn) ruft fn einmal auf, fünf Sekunden ab jetzt. Beide geben einen Timer mit einer cancel()-Methode zurück, und await $.clock.now() liefert die Zeit in Millisekunden.

Dieser Hook fragt einmal pro Minute die Checks eines Pull Requests ab und zeigt das Ergebnis unter dem Eingabefeld an. summarize ist eine eigene Funktion, die die JSON-Ausgabe des Befehls in wenige Worte umwandelt:

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 unter dem Eingabefeld eine Zeile mit einem ⚠, dem Namen des Mods und anschließend checks: sowie Ihrer Zusammenfassung. Danach wird sie einmal pro Minute ersetzt. Der Callback des Timers läuft außerhalb jedes Events, daher läuft er zwischen Turns weiter und startet selbst keinen. Wenn der Callback einen Fehler auslöst, wird der Fehler in das Debug-Log geschrieben, und der Timer läuft beim nächsten Intervall erneut.

Etwas anzeigen, ohne einen Turn zu starten

Ein Hintergrundjob kann dem Benutzer etwas anzeigen, ohne einen Turn zu starten. Jeder dieser Aufrufe platziert Text an einer anderen Stelle:

Aufruf Was der Benutzer sieht
$.ui.status(text) Eine Zeile unter dem Eingabefeld, die bestehen bleibt, bis Sie sie ändern. Sie beginnt mit ⚠ und dem Namen des Mods, wie in ⚠ my-mod: checks: 3 passing.
$.ui.toast(text) Eine Toast-Benachrichtigung mit dem Namen des Mods, die nach einigen Sekunden verschwindet. Im Vollbild-Rendering ist sie ein Feld oben rechts, im klassischen Renderer eine Zeile rechts unter dem Eingabefeld.
$.ui.log(text) Eine abgeblendete Zeile im Transkript, die Claude nicht liest. Sie beginnt mit ● und dem Namen des Mods, wie in ● my-mod: build finished.

Einen Turn aus einem Hintergrundjob starten

Wenn ein Hintergrundjob etwas findet, das Claudes Aufmerksamkeit erfordert, kann er einen Turn starten, indem er mit $.prompt.submit({ text }) einen Prompt übermittelt. Claude liest den Text nach einem Satz, der Ihren Mod als Absender nennt. Um ihn ohne diesen Satz als eigene Worte des Benutzers zu senden, fügen Sie asUser: true hinzu. Der Aufruf wartet, bis die Sitzung inaktiv ist, und startet dann einen neuen Turn. Er wird aufgelöst, wenn dieser Turn beginnt, verwenden Sie ihn daher nicht mit await in einem Handler, der läuft, während Claude arbeitet.

Hintergrundarbeit beenden

Timer werden beendet, wenn das Modul neu geladen wird. Für lang laufende Arbeit innerhalb eines Hooks ist next.signal ein AbortSignal, das abbricht, wenn das Event, das Ihr Hook verarbeitet, verworfen wird, zum Beispiel wenn der Benutzer unterbricht. Übergeben Sie es daher an alles, was lange läuft.

Nachrichten zwischen Sitzungen senden und empfangen

Ein Mod kann eine Nachricht im Klartext an eine andere Ihrer Sitzungen, an einen der Subagenten dieser Sitzung oder an ein Teammitglied in seinem Agent-Team senden. Er kann außerdem die eingehenden und ausgehenden Nachrichten beobachten.

Um eine Nachricht zu senden, rufen Sie $.session.send({ to, text }) auf. Dies nutzt dieselbe Zustellung wie das SendMessage-Tool. Legen Sie to danach fest, wer die Nachricht empfängt:

  • Eine andere Ihrer Sitzungen: { sessionId }
  • Ein Subagent oder Teammitglied: { agentId }, mit einer ID aus $.agent.list()
  • Der Absender einer Nachricht, die Sie empfangen haben: die String-Adresse, von der diese Nachricht stammt

Der Aufruf wird aufgelöst, sobald die Nachricht in die Warteschlange gestellt wurde, mit { isDelivered: true }. Wenn nichts zugestellt wurde, wird er mit { isDelivered: false, reason } aufgelöst, und reason gibt den Grund an.

Dieser Hook beantwortet einen /ping-Befehl, als Befehl registriert, indem er die Sitzung, deren ID Sie danach eingeben, nach einem Status fragt:

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 gestellt wurde, erscheint nichts in Ihrer Sitzung, und Claude in der anderen Sitzung liest Status? One line. Wenn nichts zugestellt wurde, nennt eine Toast-Benachrichtigung den Grund.

Mit session.receive und session.send kann ein Mod die Nachrichten beobachten. Geben Sie bei beiden next(e) zurück, um jede Nachricht unverändert weiterzuleiten:

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

Eine Sitzung, die so eingestellt ist, dass sie eingehende Nachrichten ablehnt, lehnt eine Nachricht ab, bevor session.receive ausgelöst wird, sodass ein Hook sie nie sieht. Eine Nachricht, die auf Ihre Genehmigung wartet, erreicht den Hook zuerst, sodass ein Mod eine Nachricht lesen kann, die Sie noch nicht genehmigt haben. Das next(e) des Hooks wird abgelehnt, wenn die Nachricht nicht zugestellt wird.

Der Absendername einer empfangenen Nachricht ist das, was der Absender angegeben hat. Stützen Sie daher keine Entscheidung darauf.

Auf Dateien, Prozesse und das Netzwerk zugreifen

Ein Mod greift über die Mods-API auf das Dateisystem, Prozesse und das Netzwerk zu, und zwar mit denselben Berechtigungen wie der Benutzer, der Claude Code ausführt. Das Hooks-Modul selbst verfügt über keine Node.js-APIs, keine Timer-Globals wie setTimeout und keinen eigenen Netzwerk- oder Dateizugriff. Standard-JavaScript- und Web-APIs wie URL, TextEncoder, AbortController und crypto.subtle sind verfügbar. Jeder der folgenden Namespaces deckt eine Art von Zugriff ab:

Namespace Funktion
$.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 dieser beendet ist. spawn streamt die Ausgabe eines lang laufenden Befehls.
$.http fetch(url, init) über http oder https. Wird zu { status, ok, headers, text } aufgelöst, sobald der Body gelesen wurde.
$.store Ein eigener JSON-Key-Value-Speicher Ihres Plugins, der zwischen Sitzungen erhalten bleibt
$.env Umgebungsvariablen mit get lesen und mit set setzen. Geben Sie den Namen als String-Literal an.
$.settings Mit read auslesen, was die Einstellungsdateien und die verwaltete Richtlinie enthalten
$.session messages() gibt das Transkript als Liste von { role, text, toolUses } zurück. Außerdem das Arbeitsverzeichnis, das Modell und mehr. usage() gibt die Nutzung des Kontextfensters und die Limits des Plans zurück.
$.mcp Mit call ein Tool auf einem verbundenen MCP-Server aufrufen

Für Dateien und Prozesse gelten einige eigene Regeln:

  • Pfade: Ein relativer Pfad wird relativ zum Arbeitsverzeichnis der Sitzung aufgelöst
  • $.fs.list: Gibt die Einträge eines einzelnen Verzeichnisses als { name, kind, size, isLink } zurück und arbeitet nicht rekursiv
  • $.process.run: Nimmt eine Argumentliste entgegen und verwendet keine Shell. Wird unabhängig vom Exit-Code zu { exitCode, stdout, stderr } aufgelöst. Wird abgelehnt, wenn das Programm nicht starten kann oder beim Timeout, standardmäßig 30 Sekunden, noch läuft. Umschließen Sie den Aufruf daher mit try und catch.

Jeder dieser Aufrufe ist selbst ein Event, benannt nach seinem Namespace und seiner Methode ohne das $., etwa fs.read für $.fs.read. Ein Mod, der früher in der Kette steht, kann Ihren Aufruf beobachten, umschreiben oder ablehnen. Auf diese Weise schränkt eine Organisation ein, worauf Mods zugreifen können.

Ein Mod kann Ihren $.process.spawn-Aufruf ablehnen, nachdem der Befehl bereits Ausgabe erzeugt hat oder beendet wurde, und nichts von dem, was der Befehl getan hat, wird rückgängig gemacht. Der Aufruf wird dann mit einer Meldung abgelehnt, die mit einer der folgenden Zeichenfolgen und der Begründung des ablehnenden Mods endet:

  • $.process.spawn started, and a plugin withheld its result:: Der ablehnende Mod hatte die Ausgabe des Befehls nicht bis zum Ende gelesen. Claude Code beendet den Befehl, falls er noch läuft.
  • $.process.spawn ran, and a plugin withheld its result:: Der ablehnende Mod hatte die Ausgabe des Befehls bis zum Ende gelesen, der Befehl war also bereits beendet

Nächste Schritte