Voraussetzungen

  • Node.js 18+

Installation

Installieren Sie @anthropic-ai/claude-code von NPM:

npm install -g @anthropic-ai/claude-code

Um den TypeScript SDK-Quellcode anzuzeigen, besuchen Sie die @anthropic-ai/claude-code Seite auf NPM.

Grundlegende Verwendung

Die primäre Schnittstelle über das TypeScript SDK ist die query Funktion, die einen asynchronen Iterator zurückgibt, der Nachrichten streamt, sobald sie eintreffen:

import { query } from "@anthropic-ai/claude-code";

for await (const message of query({
  prompt: "Systemleistung analysieren",
  options: {
    maxTurns: 5,
    appendSystemPrompt: "Du bist ein Leistungsingenieur",
    allowedTools: ["Bash", "Read", "WebSearch"],
    abortController: new AbortController(),
  }
})) {
  if (message.type === "result" && message.subtype === "success") {
    console.log(message.result);
  }
}

Konfigurationsoptionen

ArgumentTypBeschreibungStandard
abortControllerAbortControllerAbort-Controller zum Abbrechen von Operationennew AbortController()
additionalDirectoriesstring[]Zusätzliche Verzeichnisse, die in die Sitzung einbezogen werden sollenundefined
allowedToolsstring[]Liste der Tools, die Claude verwenden darfAlle Tools standardmäßig aktiviert
appendSystemPromptstringText, der an den Standard-System-Prompt angehängt wirdundefined
canUseTool(toolName: string, input: any) => Promise<ToolPermissionResult>Benutzerdefinierte Berechtigungsfunktion für Tool-Verwendungundefined
continuebooleanDie neueste Sitzung fortsetzenfalse
customSystemPromptstringDen Standard-System-Prompt vollständig ersetzenundefined
cwdstringAktuelles Arbeitsverzeichnisprocess.cwd()
disallowedToolsstring[]Liste der Tools, die Claude nicht verwenden darfundefined
envDict<string>Umgebungsvariablen, die gesetzt werden sollenundefined
executable'bun' | 'deno' | 'node'Welche JavaScript-Laufzeit verwendet werden sollnode beim Ausführen mit Node.js, bun beim Ausführen mit Bun
executableArgsstring[]Argumente, die an die ausführbare Datei übergeben werden[]
fallbackModelstringModell, das verwendet wird, wenn das primäre Modell fehlschlägtundefined
hooksPartial<Record<HookEvent, HookCallbackMatcher[]>>Lebenszyklus-Hooks für Anpassungenundefined
includePartialMessagesbooleanPartielle Streaming-Ereignisse in den Nachrichtenstrom einbeziehenfalse
maxThinkingTokensnumberMaximale Token für Claudes Denkprozessundefined
maxTurnsnumberMaximale Anzahl von Gesprächsrundenundefined
mcpServersRecord<string, McpServerConfig>MCP-Server-Konfigurationenundefined
modelstringZu verwendendes Claude-ModellVerwendet Standard aus CLI-Konfiguration
pathToClaudeCodeExecutablestringPfad zur Claude Code ausführbaren DateiAusführbare Datei, die mit @anthropic-ai/claude-code geliefert wird
permissionModePermissionModeBerechtigungsmodus für die Sitzung"default" (Optionen: "default", "acceptEdits", "bypassPermissions", "plan")
resumestringSitzungs-ID zum Fortsetzenundefined
stderr(data: string) => voidCallback für stderr-Ausgabeundefined
strictMcpConfigbooleanStrikte MCP-Konfigurationsvalidierung durchsetzenundefined

Partielles Nachrichten-Streaming

Wenn includePartialMessages aktiviert ist, sendet das SDK stream_event Nachrichten, die rohe Streaming-Ereignisse von der Claude API enthalten. Dies ermöglicht es Ihnen, auf partielle Inhalte zuzugreifen, während sie generiert werden, was für die Implementierung von Echtzeit-UI-Updates oder Fortschrittsindikatoren nützlich ist.

import { query } from "@anthropic-ai/claude-code";

for await (const message of query({
  prompt: "Schreibe einen langen Aufsatz über künstliche Intelligenz",
  options: {
    includePartialMessages: true,
    maxTurns: 1
  }
})) {
  // Partielle Streaming-Ereignisse behandeln
  if (message.type === "stream_event") {
    const event = message.event;
    
    // Auf partiellen Text zugreifen, während er gestreamt wird
    if (event.type === "content_block_delta" && event.delta.type === "text_delta") {
      process.stdout.write(event.delta.text);
    }
    
    // Denkfortschritt verfolgen
    if (event.type === "content_block_start" && event.content_block.type === "thinking") {
      console.log("\n[Claude denkt nach...]");
    }
  }
  
  // Immer noch das endgültige Ergebnis erhalten
  if (message.type === "result" && message.subtype === "success") {
    console.log("\nEndgültiges Ergebnis:", message.result);
  }
}

Jede stream_event Nachricht enthält:

  • event: Das rohe Streaming-Ereignis von der API
  • session_id: Die aktuelle Sitzungskennung
  • parent_tool_use_id: Die ID des Tools, das ausgeführt wird (falls zutreffend)
  • uuid: Eine eindeutige Kennung für dieses Ereignis

Partielles Nachrichten-Streaming ist hauptsächlich für erweiterte Anwendungsfälle nützlich, bei denen Sie granulare Kontrolle über die Streaming-Antwort benötigen. Für die meisten Anwendungen ist das Standardverhalten (Warten auf vollständige Nachrichten) ausreichend.

Multi-Turn-Gespräche

Für Multi-Turn-Gespräche haben Sie zwei Optionen.

Sie können Antworten generieren und sie fortsetzen, oder Sie können den Streaming-Eingabemodus verwenden, der ein async/generator für ein Array von Nachrichten akzeptiert. Derzeit ist der Streaming-Eingabemodus die einzige Möglichkeit, Bilder über Nachrichten anzuhängen.

Fortsetzen mit Sitzungsverwaltung

import { query } from "@anthropic-ai/claude-code";

// Neueste Unterhaltung fortsetzen
for await (const message of query({
  prompt: "Jetzt refaktoriere das für bessere Leistung",
  options: { continue: true }
})) { 
  if (message.type === "result" && message.subtype === "success") console.log(message.result);
}

// Spezifische Sitzung fortsetzen
for await (const message of query({
  prompt: "Die Tests aktualisieren",
  options: {
    resume: "550e8400-e29b-41d4-a716-446655440000",
    maxTurns: 3
  }
})) {
  if (message.type === "result" && message.subtype === "success") console.log(message.result);
}

Streaming-Eingabemodus

Der Streaming-Eingabemodus ermöglicht es Ihnen, Nachrichten als asynchrones Iterable anstatt als einzelnen String bereitzustellen. Dies ermöglicht Multi-Turn-Gespräche, Bildanhänge und dynamische Nachrichtengenerierung:

import { query } from "@anthropic-ai/claude-code";

// Einen asynchronen Generator für Streaming-Nachrichten erstellen
async function* generateMessages() {
  yield {
    type: "user" as const,
    message: {
      role: "user" as const,
      content: "Beginne mit der Analyse dieser Codebasis"
    }
  };
  
  // Auf eine Bedingung oder Benutzereingabe warten
  await new Promise(resolve => setTimeout(resolve, 1000));
  
  yield {
    type: "user" as const,
    message: {
      role: "user" as const,
      content: "Konzentriere dich jetzt auf das Authentifizierungsmodul"
    }
  };
}

// Streaming-Eingabe verwenden
for await (const message of query({
  prompt: generateMessages(),
  options: {
    maxTurns: 5,
    allowedTools: ["Read", "Grep", "Bash"]
  }
})) {
  if (message.type === "result" && message.subtype === "success") {
    console.log(message.result);
  }
}

Streaming-Eingabe mit Bildern

Der Streaming-Eingabemodus ist die einzige Möglichkeit, Bilder über Nachrichten anzuhängen:

import { query } from "@anthropic-ai/claude-code";
import { readFileSync } from "fs";

async function* messagesWithImage() {
  // Ein Bild mit Text senden
  yield {
    type: "user" as const,
    message: {
      role: "user" as const,
      content: [
        {
          type: "text",
          text: "Analysiere diesen Screenshot und schlage Verbesserungen vor"
        },
        {
          type: "image",
          source: {
            type: "base64",
            media_type: "image/png",
            data: readFileSync("screenshot.png", "base64")
          }
        }
      ]
    }
  };
}

for await (const message of query({
  prompt: messagesWithImage()
})) {
  if (message.type === "result" && message.subtype === "success") console.log(message.result);
}

Benutzerdefinierte System-Prompts

System-Prompts definieren die Rolle, Expertise und das Verhalten Ihres Agenten:

import { query } from "@anthropic-ai/claude-code";

// SRE-Incident-Response-Agent
for await (const message of query({
  prompt: "API ist ausgefallen, untersuchen",
  options: {
    customSystemPrompt: "Du bist ein SRE-Experte. Diagnostiziere Probleme systematisch und biete umsetzbare Lösungen.",
    maxTurns: 3
  }
})) {
  if (message.type === "result" && message.subtype === "success") console.log(message.result);
}

// An Standard-System-Prompt anhängen
for await (const message of query({
  prompt: "Diese Funktion refaktorieren",
  options: {
    appendSystemPrompt: "Immer umfassende Fehlerbehandlung und Unit-Tests einschließen.",
    maxTurns: 2
  }
})) {
  if (message.type === "result" && message.subtype === "success") console.log(message.result);
}

MCP-Server-Integration

Das Model Context Protocol (MCP) ermöglicht es Ihnen, Ihren Agenten benutzerdefinierte Tools und Fähigkeiten zu geben:

import { query } from "@anthropic-ai/claude-code";

// SRE-Agent mit Monitoring-Tools
for await (const message of query({
  prompt: "Den Ausfall des Zahlungsdienstes untersuchen",
  options: {
    mcpConfig: "sre-tools.json",
    allowedTools: ["mcp__datadog", "mcp__pagerduty", "mcp__kubernetes"],
    appendSystemPrompt: "Du bist ein SRE. Verwende Monitoring-Daten zur Diagnose von Problemen.",
    maxTurns: 4
  }
})) {
  if (message.type === "result" && message.subtype === "success") console.log(message.result);
}

Benutzerdefinierte Tools mit In-Process-MCP-Servern

SDK-MCP-Server ermöglichen es Ihnen, benutzerdefinierte Tools zu erstellen, die direkt in Ihrem Anwendungsprozess laufen und typsichere Tool-Ausführung ohne den Overhead separater Prozesse oder Netzwerkkommunikation bieten.

Benutzerdefinierte Tools erstellen

Verwenden Sie die createSdkMcpServer und tool Hilfsfunktionen, um typsichere benutzerdefinierte Tools zu definieren:

import { query, tool, createSdkMcpServer } from "@anthropic-ai/claude-code";
import { z } from "zod";

// Einen SDK-MCP-Server mit benutzerdefinierten Tools erstellen
const customServer = createSdkMcpServer({
  name: "my-custom-tools",
  version: "1.0.0",
  tools: [
    tool(
      "calculate_compound_interest",
      "Zinseszins für eine Investition berechnen",
      {
        principal: z.number().describe("Anfänglicher Investitionsbetrag"),
        rate: z.number().describe("Jährlicher Zinssatz (als Dezimalzahl, z.B. 0,05 für 5%)"),
        time: z.number().describe("Investitionszeitraum in Jahren"),
        n: z.number().default(12).describe("Zinseszinsfrequenz pro Jahr")
      },
      async (args) => {
        const amount = args.principal * Math.pow(1 + args.rate / args.n, args.n * args.time);
        const interest = amount - args.principal;
        
        return {
          content: [{
            type: "text",
            text: `Endbetrag: $${amount.toFixed(2)}\nVerdiente Zinsen: $${interest.toFixed(2)}`
          }]
        };
      }
    ),
    tool(
      "fetch_user_data",
      "Benutzerdaten aus Ihrer Anwendungsdatenbank abrufen",
      {
        userId: z.string().describe("Die abzurufende Benutzer-ID"),
        fields: z.array(z.string()).optional().describe("Spezifische Felder, die zurückgegeben werden sollen")
      },
      async (args) => {
        // Direkter Zugriff auf die Datenschicht Ihrer Anwendung
        const userData = await myDatabase.getUser(args.userId, args.fields);
        
        return {
          content: [{
            type: "text",
            text: JSON.stringify(userData, null, 2)
          }]
        };
      }
    )
  ]
});

// Die benutzerdefinierten Tools in Ihrer Abfrage verwenden
for await (const message of query({
  prompt: "Zinseszins für $10.000 bei 5% für 10 Jahre berechnen",
  options: {
    mcpServers: {
      "my-custom-tools": customServer
    },
    maxTurns: 3
  }
})) {
  if (message.type === "result") {
    console.log(message.result);
  }
}

Typsicherheit mit Zod

Der tool Helfer bietet vollständige TypeScript-Typinferenz aus Ihren Zod-Schemas:

tool(
  "process_data",
  "Strukturierte Daten mit Typsicherheit verarbeiten",
  {
    // Zod-Schema definiert sowohl Laufzeitvalidierung als auch TypeScript-Typen
    data: z.object({
      name: z.string(),
      age: z.number().min(0).max(150),
      email: z.string().email(),
      preferences: z.array(z.string()).optional()
    }),
    format: z.enum(["json", "csv", "xml"]).default("json")
  },
  async (args) => {
    // args ist vollständig typisiert basierend auf dem Schema
    // TypeScript weiß: args.data.name ist string, args.data.age ist number, etc.
    console.log(`Verarbeite ${args.data.name}s Daten als ${args.format}`);
    
    // Ihre Verarbeitungslogik hier
    return {
      content: [{
        type: "text",
        text: `Daten für ${args.data.name} verarbeitet`
      }]
    };
  }
)

Hooks

Hooks ermöglichen es Ihnen, das Verhalten von Claude Code anzupassen und zu erweitern, indem Sie benutzerdefinierte Callbacks an verschiedenen Punkten im Lebenszyklus des Agenten ausführen. Im Gegensatz zu CLI-Hooks, die Bash-Befehle ausführen, sind SDK-Hooks JavaScript/TypeScript-Funktionen, die im Prozess laufen.

Hooks definieren

Hooks sind nach Ereignistyp organisiert, mit optionalen Matchern, um zu filtern, wann sie ausgeführt werden:

import { query } from "@anthropic-ai/claude-code";

for await (const message of query({
  prompt: "Die Codebasis analysieren",
  options: {
    hooks: {
      PreToolUse: [
        {
          matcher: "Write",
          hooks: [
            async (input, toolUseId, { signal }) => {
              console.log(`Datei wird geschrieben: ${input.tool_input.file_path}`);
              
              // Die Operation validieren
              if (input.tool_input.file_path.includes('.env')) {
                return {
                  decision: 'block',
                  stopReason: 'Kann nicht in Umgebungsdateien schreiben'
                };
              }
              
              // Die Operation erlauben
              return { continue: true };
            }
          ]
        }
      ],
      PostToolUse: [
        {
          matcher: "Write|Edit",
          hooks: [
            async (input, toolUseId, { signal }) => {
              console.log(`Datei geändert: ${input.tool_response.filePath}`);
              // Ihre benutzerdefinierte Formatierung oder Validierung ausführen
              return { continue: true };
            }
          ]
        }
      ]
    }
  }
})) {
  if (message.type === "result") console.log(message.result);
}

Verfügbare Hook-Ereignisse

  • PreToolUse: Läuft vor der Tool-Ausführung. Kann Tools blockieren oder Feedback geben.
  • PostToolUse: Läuft nach erfolgreicher Tool-Ausführung.
  • UserPromptSubmit: Läuft, wenn der Benutzer einen Prompt einreicht.
  • SessionStart: Läuft, wenn eine Sitzung startet.
  • SessionEnd: Läuft, wenn eine Sitzung endet.
  • Stop: Läuft, wenn Claude aufhören wird zu antworten.
  • SubagentStop: Läuft, wenn ein Subagent aufhören wird.
  • PreCompact: Läuft vor der Gesprächskompaktierung.
  • Notification: Läuft, wenn Benachrichtigungen gesendet werden.

Hook-Eingabetypen

Jeder Hook erhält typisierte Eingaben basierend auf dem Ereignis:

// PreToolUse-Eingabe
type PreToolUseHookInput = {
  hook_event_name: 'PreToolUse';
  session_id: string;
  transcript_path: string;
  cwd: string;
  permission_mode?: string;
  tool_name: string;
  tool_input: unknown;
}

// PostToolUse-Eingabe
type PostToolUseHookInput = {
  hook_event_name: 'PostToolUse';
  session_id: string;
  transcript_path: string;
  cwd: string;
  permission_mode?: string;
  tool_name: string;
  tool_input: unknown;
  tool_response: unknown;
}

Hook-Ausgabe

Hooks geben Ausgaben zurück, die den Ausführungsfluss steuern:

interface HookJSONOutput {
  // Ausführung fortsetzen (Standard: true)
  continue?: boolean;
  
  // Ausgabe an Benutzer unterdrücken
  suppressOutput?: boolean;
  
  // Stopp-Grund (dem Modell gezeigt)
  stopReason?: string;
  
  // Entscheidung für PreToolUse-Hooks
  decision?: 'approve' | 'block';
  
  // Systemnachricht zum Anzeigen
  systemMessage?: string;
  
  // Hook-spezifische Ausgabe
  hookSpecificOutput?: {
    // Für PreToolUse
    permissionDecision?: 'allow' | 'deny' | 'ask';
    permissionDecisionReason?: string;
    
    // Für UserPromptSubmit oder PostToolU
    additionalContext?: string;
  };
}

Praktische Beispiele

Protokollierung und Überwachung

const hooks = {
  PreToolUse: [
    {
      hooks: [
        async (input) => {
          // Alle Tool-Verwendung protokollieren
          await logToMonitoring({
            event: 'tool_use',
            tool: input.tool_name,
            input: input.tool_input,
            session: input.session_id
          });
          
          return { continue: true };
        }
      ]
    }
  ]
};

Dateioperations-Validierung

const hooks = {
  PreToolUse: [
    {
      matcher: "Write|Edit",
      hooks: [
        async (input) => {
          const filePath = input.tool_input.file_path;
          
          // Sensible Dateien blockieren
          const sensitivePatterns = ['.env', '.git/', 'secrets/', '*.key'];
          
          for (const pattern of sensitivePatterns) {
            if (filePath.includes(pattern)) {
              return {
                decision: 'block',
                stopReason: `Kann sensible Datei nicht ändern, die ${pattern} entspricht`
              };
            }
          }
          
          return { continue: true };
        }
      ]
    }
  ]
};

Automatische Code-Formatierung

import { exec } from 'child_process';
import { promisify } from 'util';

const execAsync = promisify(exec);

const hooks = {
  PostToolUse: [
    {
      matcher: "Write|Edit|MultiEdit",
      hooks: [
        async (input) => {
          const filePath = input.tool_response.filePath;
          
          // Automatische Formatierung basierend auf Dateityp
          if (filePath.endsWith('.ts') || filePath.endsWith('.tsx')) {
            await execAsync(`prettier --write "${filePath}"`);
          } else if (filePath.endsWith('.py')) {
            await execAsync(`black "${filePath}"`);
          }
          
          return { continue: true };
        }
      ]
    }
  ]
};

Prompt-Verbesserung

const hooks = {
  UserPromptSubmit: [
    {
      hooks: [
        async (input) => {
          // Kontext zu Prompts hinzufügen
          const projectContext = await loadProjectContext();
          
          return {
            continue: true,
            hookSpecificOutput: {
              hookEventName: 'UserPromptSubmit',
              additionalContext: `Projektkontext: ${projectContext}`
            }
          };
        }
      ]
    }
  ]
};

Benutzerdefinierte Kompaktierungsanweisungen

const hooks = {
  PreCompact: [
    {
      hooks: [
        async (input) => {
          const trigger = input.trigger; // 'manual' oder 'auto'
          
          return {
            continue: true,
            systemMessage: 'Konzentriere dich darauf, Implementierungsdetails und Fehlerlösungen zu bewahren'
          };
        }
      ]
    }
  ]
};

Hook-Ausführungsverhalten

  • Parallelisierung: Alle passenden Hooks laufen parallel
  • Timeout: Hooks respektieren das Abort-Signal aus den Optionen
  • Fehlerbehandlung: Hook-Fehler werden protokolliert, stoppen aber nicht die Ausführung
  • Matcher: Unterstützen Regex-Muster (z.B. "Write|Edit")

Hooks mit canUseTool kombinieren

Während canUseTool Berechtigungskontrolle bietet, bieten Hooks eine breitere Lebenszyklus-Integration:

for await (const message of query({
  prompt: "Das Feature erstellen",
  options: {
    // Feinkörnige Berechtigungskontrolle
    canUseTool: async (toolName, input) => {
      // Eingaben ändern oder basierend auf Laufzeitbedingungen verweigern
      return { behavior: "allow", updatedInput: input };
    },
    
    // Lebenszyklus-Hooks für Überwachung und Automatisierung
    hooks: {
      PreToolUse: [
        {
          hooks: [
            async (input) => {
              // Protokollieren, validieren oder vorbereiten
              return { continue: true };
            }
          ]
        }
      ]
    }
  }
})) {
  // Nachrichten verarbeiten
}

Berechtigungskontrolle mit canUseTool

Der canUseTool Callback bietet feinkörnige Kontrolle über die Tool-Ausführung. Er wird vor jeder Tool-Verwendung aufgerufen und kann Tools erlauben, verweigern oder Tool-Eingaben ändern:

type ToolPermissionResult = 
  | { behavior: "allow"; updatedInput?: any }
  | { behavior: "deny"; message?: string };

for await (const message of query({
  prompt: "Benutzerverhalten analysieren und Metriken berechnen",
  options: {
    mcpServers: {
      "analytics": analyticsServer
    },
    canUseTool: async (toolName: string, input: any) => {
      // Kontrollieren, welche Tools verwendet werden können
      if (toolName.startsWith("mcp__analytics__")) {
        // Berechtigungen für Analytics-Tools prüfen
        const hasPermission = await checkUserPermissions(toolName);
        
        return hasPermission
          ? { behavior: "allow", updatedInput: input }
          : { behavior: "deny", message: "Unzureichende Berechtigungen" };
      }
      
      // Eingaben für bestimmte Tools ändern
      if (toolName === "Bash") {
        // Sicherheitsprüfungen hinzufügen oder Befehle ändern
        const safeInput = sanitizeBashCommand(input);
        return { behavior: "allow", updatedInput: safeInput };
      }
      
      // Andere Tools standardmäßig erlauben
      return { behavior: "allow", updatedInput: input };
    }
  }
})) {
  if (message.type === "result") console.log(message.result);
}

Anwendungsfälle für canUseTool

  • Berechtigungsverwaltung: Benutzerberechtigungen vor der Tool-Ausführung prüfen
  • Eingabevalidierung: Tool-Eingaben vor der Ausführung validieren oder bereinigen
  • Rate-Limiting: Rate-Limits für teure Operationen implementieren
  • Audit-Protokollierung: Tool-Verwendung für Compliance oder Debugging protokollieren
  • Dynamische Berechtigungen: Tools basierend auf Laufzeitbedingungen aktivieren/deaktivieren
// Beispiel: Web-Scraping-Rate-Limiter
const rateLimits = new Map<string, { count: number; resetTime: number }>();

const canUseTool = async (toolName: string, input: any) => {
  // Web-Scraping rate-limitieren, um IP-Sperren und API-Quota-Probleme zu verhindern
  if (toolName === "WebFetch" || toolName === "WebSearch") {
    const now = Date.now();
    const limit = rateLimits.get(toolName) || { count: 0, resetTime: now + 60000 };
    
    // Zähler jede Minute zurücksetzen
    if (now > limit.resetTime) {
      limit.count = 0;
      limit.resetTime = now + 60000;
    }
    
    // Maximal 10 Anfragen pro Minute erlauben
    if (limit.count >= 10) {
      return { 
        behavior: "deny", 
        message: `Rate-Limit überschritten: max 10 ${toolName} Anfragen pro Minute. Zurücksetzung in ${Math.ceil((limit.resetTime - now) / 1000)}s` 
      };
    }
    
    limit.count++;
    rateLimits.set(toolName, limit);
    
    // Scraping-Aktivität zur Überwachung protokollieren
    console.log(`${toolName} Anfrage ${limit.count}/10 an: ${input.url || input.query}`);
  }
  
  // Versehentliche Endlosschleifen in Bash-Skripten verhindern
  if (toolName === "Bash" && input.command?.includes("while true")) {
    return { 
      behavior: "deny", 
      message: "Endlosschleifen sind nicht erlaubt" 
    };
  }
  
  return { behavior: "allow", updatedInput: input };
};

Ausgabeformate

Textausgabe (Standard)

// Standard-Textausgabe
for await (const message of query({
  prompt: "Erkläre Datei src/components/Header.tsx"
})) {
  if (message.type === "result" && message.subtype === "success") {
    console.log(message.result);
    // Ausgabe: Dies ist eine React-Komponente, die...
  }
}

JSON-Ausgabe

// Alle Nachrichten für JSON-ähnlichen Zugriff sammeln
const messages = [];
for await (const message of query({
  prompt: "Wie funktioniert die Datenschicht?"
})) {
  messages.push(message);
}

// Auf Ergebnisnachricht mit Metadaten zugreifen
const result = messages.find(m => m.type === "result" && message.subtype === "success");
console.log({
  result: result.result,
  cost: result.total_cost_usd,
  duration: result.duration_ms
});

Eingabeformate

// Direkter Prompt
for await (const message of query({
  prompt: "Erkläre diesen Code"
})) {
  if (message.type === "result" && message.subtype === "success") console.log(message.result);
}

// Aus Variable
const userInput = "Erkläre diesen Code";
for await (const message of query({ prompt: userInput })) {
  if (message.type === "result" && message.subtype === "success") console.log(message.result);
}

Agenten-Integrationsbeispiele

SRE-Incident-Response-Agent

import { query } from "@anthropic-ai/claude-code";

// Automatisierter Incident-Response-Agent
async function investigateIncident(
  incidentDescription: string,
  severity = "medium"
) {
  const messages = [];

  for await (const message of query({
    prompt: `Incident: ${incidentDescription} (Schweregrad: ${severity})`,
    options: {
      appendSystemPrompt: "Du bist ein SRE-Experte. Diagnostiziere das Problem, bewerte die Auswirkungen und biete sofortige Handlungsschritte.",
      maxTurns: 6,
      allowedTools: ["Bash", "Read", "WebSearch", "mcp__datadog"],
      mcpConfig: "monitoring-tools.json"
    }
  })) {
    messages.push(message);
  }

  return messages.find(m => m.type === "result" && message.subtype === "success");
}

// Verwendung
const result = await investigateIncident("Payment API gibt 500-Fehler zurück", "high");
console.log(result.result);

Automatisierte Sicherheitsüberprüfung

import { query } from "@anthropic-ai/claude-code";
import { execSync } from "child_process";

async function auditPR(prNumber: number) {
  // PR-Diff abrufen
  const prDiff = execSync(`gh pr diff ${prNumber}`, { encoding: 'utf8' });

  const messages = [];
  for await (const message of query({
    prompt: prDiff,
    options: {
      appendSystemPrompt: "Du bist ein Sicherheitsingenieur. Überprüfe diese PR auf Schwachstellen, unsichere Muster und Compliance-Probleme.",
      maxTurns: 3,
      allowedTools: ["Read", "Grep", "WebSearch"]
    }
  })) {
    messages.push(message);
  }

  return messages.find(m => m.type === "result" && message.subtype === "success");
}

// Verwendung
const report = await auditPR(123);
console.log(JSON.stringify(report, null, 2));

Multi-Turn-Rechtsassistent

import { query } from "@anthropic-ai/claude-code";

async function legalReview() {
  // Rechtsüberprüfungssitzung starten
  let sessionId: string;

  for await (const message of query({
    prompt: "Rechtsüberprüfungssitzung starten",
    options: { maxTurns: 1 }
  })) {
    if (message.type === "system" && message.subtype === "init") {
      sessionId = message.session_id;
    }
  }

  // Mehrstufige Überprüfung mit derselben Sitzung
  const steps = [
    "contract.pdf auf Haftungsklauseln überprüfen",
    "Compliance mit GDPR-Anforderungen prüfen",
    "Zusammenfassung der Risiken für Führungskräfte erstellen"
  ];

  for (const step of steps) {
    for await (const message of query({
      prompt: step,
      options: { resume: sessionId, maxTurns: 2 }
    })) {
      if (message.type === "result" && message.subtype === "success") {
        console.log(`Schritt: ${step}`);
        console.log(message.result);
      }
    }
  }
}

Nachrichtenschema

Nachrichten, die von der JSON-API zurückgegeben werden, sind streng typisiert gemäß dem folgenden Schema:

type SDKMessage =
  // Eine Assistentennachricht
  | {
      type: "assistant";
      uuid: string;
      session_id: string;
      message: Message; // aus Anthropic SDK
      parent_tool_use_id: string | null;
    }

  // Eine Benutzernachricht (Eingabe)
  | {
      type: "user";
      uuid?: string;
      session_id: string;
      message: MessageParam; // aus Anthropic SDK
      parent_tool_use_id: string | null;
    }

  // Eine Benutzernachricht (Ausgabe/Wiedergabe mit erforderlicher UUID)
  | {
      type: "user";
      uuid: string;
      session_id: string;
      message: MessageParam; // aus Anthropic SDK
      parent_tool_use_id: string | null;
    }

  // Als letzte Nachricht bei Erfolg ausgegeben
  | {
      type: "result";
      subtype: "success";
      uuid: UUID;
      session_id: string;
      duration_ms: number;
      duration_api_ms: number;
      is_error: boolean;
      num_turns: number;
      result: string;
      total_cost_usd: number;
      usage: Usage;
      permission_denials: SDKPermissionDenial[];
    }

  // Als letzte Nachricht bei Fehler oder maximalen Runden ausgegeben
  | {
      type: "result";
      subtype: "error_max_turns" | "error_during_execution";
      uuid: UUID;
      session_id: string;
      duration_ms: number;
      duration_api_ms: number;
      is_error: boolean;
      num_turns: number;
      total_cost_usd: number;
      usage: Usage;
      permission_denials: SDKPermissionDenial[];
    }

  // Als erste Nachricht zu Beginn einer Unterhaltung ausgegeben
  | {
      type: "system";
      subtype: "init";
      uuid: UUID;
      session_id: string;
      apiKeySource: "user" | "project" | "org" | "temporary";
      cwd: string;
      tools: string[];
      mcp_servers: {
        name: string;
        status: string;
      }[];
      model: string;
      permissionMode: "default" | "acceptEdits" | "bypassPermissions" | "plan";
      slash_commands: string[];
      output_style: string;
    };

  type SDKPermissionDenial = {
    tool_name: string;
    tool_use_id: string;
    tool_input: Record<string, unknown>;
  }

Zusätzliche unterstützende Typen:

Message, MessageParam und Usage Typen sind im Anthropic TypeScript SDK verfügbar.

Verwandte Ressourcen