Prérequis

  • Node.js 18+

Installation

Installez @anthropic-ai/claude-code depuis NPM :

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

Pour voir le code source du SDK TypeScript, visitez la page @anthropic-ai/claude-code sur NPM.

Utilisation de base

L’interface principale via le SDK TypeScript est la fonction query, qui retourne un itérateur asynchrone qui diffuse les messages au fur et à mesure qu’ils arrivent :

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

for await (const message of query({
  prompt: "Analyser les performances du système",
  options: {
    maxTurns: 5,
    appendSystemPrompt: "Vous êtes un ingénieur en performance",
    allowedTools: ["Bash", "Read", "WebSearch"],
    abortController: new AbortController(),
  }
})) {
  if (message.type === "result" && message.subtype === "success") {
    console.log(message.result);
  }
}

Options de configuration

ArgumentTypeDescriptionDéfaut
abortControllerAbortControllerContrôleur d’abandon pour annuler les opérationsnew AbortController()
additionalDirectoriesstring[]Répertoires supplémentaires à inclure dans la sessionundefined
allowedToolsstring[]Liste des outils que Claude est autorisé à utiliserTous les outils activés par défaut
appendSystemPromptstringTexte à ajouter à l’invite système par défautundefined
canUseTool(toolName: string, input: any) => Promise<ToolPermissionResult>Fonction de permission personnalisée pour l’utilisation d’outilsundefined
continuebooleanContinuer la session la plus récentefalse
customSystemPromptstringRemplacer entièrement l’invite système par défautundefined
cwdstringRépertoire de travail actuelprocess.cwd()
disallowedToolsstring[]Liste des outils que Claude n’est pas autorisé à utiliserundefined
envDict<string>Variables d’environnement à définirundefined
executable'bun' | 'deno' | 'node'Quel runtime JavaScript utilisernode lors de l’exécution avec Node.js, bun lors de l’exécution avec Bun
executableArgsstring[]Arguments à passer à l’exécutable[]
fallbackModelstringModèle à utiliser si le modèle principal échoueundefined
hooksPartial<Record<HookEvent, HookCallbackMatcher[]>>Hooks de cycle de vie pour la personnalisationundefined
includePartialMessagesbooleanInclure les événements de diffusion partielle dans le flux de messagesfalse
maxThinkingTokensnumberJetons maximum pour le processus de réflexion de Claudeundefined
maxTurnsnumberNombre maximum de tours de conversationundefined
mcpServersRecord<string, McpServerConfig>Configurations de serveur MCPundefined
modelstringModèle Claude à utiliserUtilise la valeur par défaut de la configuration CLI
pathToClaudeCodeExecutablestringChemin vers l’exécutable Claude CodeExécutable fourni avec @anthropic-ai/claude-code
permissionModePermissionModeMode de permission pour la session"default" (options : "default", "acceptEdits", "bypassPermissions", "plan")
resumestringID de session à reprendreundefined
stderr(data: string) => voidCallback pour la sortie stderrundefined
strictMcpConfigbooleanAppliquer une validation stricte de la configuration MCPundefined

Diffusion de messages partiels

Lorsque includePartialMessages est activé, le SDK émettra des messages stream_event qui contiennent des événements de diffusion bruts de l’API Claude. Cela vous permet d’accéder au contenu partiel au fur et à mesure qu’il est généré, utile pour implémenter des mises à jour d’interface utilisateur en temps réel ou des indicateurs de progression.

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

for await (const message of query({
  prompt: "Écrivez un long essai sur l'intelligence artificielle",
  options: {
    includePartialMessages: true,
    maxTurns: 1
  }
})) {
  // Gérer les événements de diffusion partielle
  if (message.type === "stream_event") {
    const event = message.event;
    
    // Accéder au texte partiel au fur et à mesure qu'il est diffusé
    if (event.type === "content_block_delta" && event.delta.type === "text_delta") {
      process.stdout.write(event.delta.text);
    }
    
    // Suivre le progrès de la réflexion
    if (event.type === "content_block_start" && event.content_block.type === "thinking") {
      console.log("\n[Claude réfléchit...]");
    }
  }
  
  // Obtenir toujours le résultat final
  if (message.type === "result" && message.subtype === "success") {
    console.log("\nRésultat final :", message.result);
  }
}

Chaque message stream_event inclut :

  • event : L’événement de diffusion brut de l’API
  • session_id : L’identifiant de session actuel
  • parent_tool_use_id : L’ID de l’outil en cours d’exécution (le cas échéant)
  • uuid : Un identifiant unique pour cet événement

La diffusion de messages partiels est principalement utile pour les cas d’utilisation avancés où vous avez besoin d’un contrôle granulaire sur la réponse en streaming. Pour la plupart des applications, le comportement par défaut (attendre les messages complets) est suffisant.

Conversations multi-tours

Pour les conversations multi-tours, vous avez deux options.

Vous pouvez générer des réponses et les reprendre, ou vous pouvez utiliser le mode d’entrée en streaming qui accepte un async/générateur pour un tableau de messages. Pour l’instant, le mode d’entrée en streaming est le seul moyen d’attacher des images via des messages.

Reprendre avec la gestion de session

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

// Continuer la conversation la plus récente
for await (const message of query({
  prompt: "Maintenant refactorisez ceci pour de meilleures performances",
  options: { continue: true }
})) { 
  if (message.type === "result" && message.subtype === "success") console.log(message.result);
}

// Reprendre une session spécifique
for await (const message of query({
  prompt: "Mettre à jour les tests",
  options: {
    resume: "550e8400-e29b-41d4-a716-446655440000",
    maxTurns: 3
  }
})) {
  if (message.type === "result" && message.subtype === "success") console.log(message.result);
}

Mode d’entrée en streaming

Le mode d’entrée en streaming vous permet de fournir des messages comme un itérable asynchrone au lieu d’une seule chaîne. Cela permet les conversations multi-tours, les pièces jointes d’images et la génération de messages dynamiques :

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

// Créer un générateur asynchrone pour les messages en streaming
async function* generateMessages() {
  yield {
    type: "user" as const,
    message: {
      role: "user" as const,
      content: "Commencer l'analyse de cette base de code"
    }
  };
  
  // Attendre une condition ou une entrée utilisateur
  await new Promise(resolve => setTimeout(resolve, 1000));
  
  yield {
    type: "user" as const,
    message: {
      role: "user" as const,
      content: "Maintenant concentrez-vous sur le module d'authentification"
    }
  };
}

// Utiliser l'entrée en streaming
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);
  }
}

Entrée en streaming avec images

Le mode d’entrée en streaming est le seul moyen d’attacher des images via des messages :

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

async function* messagesWithImage() {
  // Envoyer une image avec du texte
  yield {
    type: "user" as const,
    message: {
      role: "user" as const,
      content: [
        {
          type: "text",
          text: "Analysez cette capture d'écran et suggérez des améliorations"
        },
        {
          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);
}

Invites système personnalisées

Les invites système définissent le rôle, l’expertise et le comportement de votre agent :

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

// Agent de réponse aux incidents SRE
for await (const message of query({
  prompt: "L'API est en panne, enquêter",
  options: {
    customSystemPrompt: "Vous êtes un expert SRE. Diagnostiquez les problèmes de manière systématique et fournissez des solutions exploitables.",
    maxTurns: 3
  }
})) {
  if (message.type === "result" && message.subtype === "success") console.log(message.result);
}

// Ajouter à l'invite système par défaut
for await (const message of query({
  prompt: "Refactoriser cette fonction",
  options: {
    appendSystemPrompt: "Incluez toujours une gestion d'erreur complète et des tests unitaires.",
    maxTurns: 2
  }
})) {
  if (message.type === "result" && message.subtype === "success") console.log(message.result);
}

Intégration de serveur MCP

Le Model Context Protocol (MCP) vous permet de donner à vos agents des outils et capacités personnalisés :

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

// Agent SRE avec outils de surveillance
for await (const message of query({
  prompt: "Enquêter sur la panne du service de paiement",
  options: {
    mcpConfig: "sre-tools.json",
    allowedTools: ["mcp__datadog", "mcp__pagerduty", "mcp__kubernetes"],
    appendSystemPrompt: "Vous êtes un SRE. Utilisez les données de surveillance pour diagnostiquer les problèmes.",
    maxTurns: 4
  }
})) {
  if (message.type === "result" && message.subtype === "success") console.log(message.result);
}

Outils personnalisés avec serveurs MCP en processus

Les serveurs MCP SDK vous permettent de créer des outils personnalisés qui s’exécutent directement dans le processus de votre application, fournissant une exécution d’outils type-safe sans la surcharge de processus séparés ou de communication réseau.

Créer des outils personnalisés

Utilisez les fonctions d’aide createSdkMcpServer et tool pour définir des outils personnalisés type-safe :

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

// Créer un serveur MCP SDK avec des outils personnalisés
const customServer = createSdkMcpServer({
  name: "my-custom-tools",
  version: "1.0.0",
  tools: [
    tool(
      "calculate_compound_interest",
      "Calculer les intérêts composés pour un investissement",
      {
        principal: z.number().describe("Montant d'investissement initial"),
        rate: z.number().describe("Taux d'intérêt annuel (en décimal, par ex. 0.05 pour 5%)"),
        time: z.number().describe("Période d'investissement en années"),
        n: z.number().default(12).describe("Fréquence de composition par an")
      },
      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: `Montant final : ${amount.toFixed(2)}$\nIntérêts gagnés : ${interest.toFixed(2)}$`
          }]
        };
      }
    ),
    tool(
      "fetch_user_data",
      "Récupérer les données utilisateur de votre base de données d'application",
      {
        userId: z.string().describe("L'ID utilisateur à récupérer"),
        fields: z.array(z.string()).optional().describe("Champs spécifiques à retourner")
      },
      async (args) => {
        // Accès direct à la couche de données de votre application
        const userData = await myDatabase.getUser(args.userId, args.fields);
        
        return {
          content: [{
            type: "text",
            text: JSON.stringify(userData, null, 2)
          }]
        };
      }
    )
  ]
});

// Utiliser les outils personnalisés dans votre requête
for await (const message of query({
  prompt: "Calculer les intérêts composés pour 10 000$ à 5% pendant 10 ans",
  options: {
    mcpServers: {
      "my-custom-tools": customServer
    },
    maxTurns: 3
  }
})) {
  if (message.type === "result") {
    console.log(message.result);
  }
}

Sécurité de type avec Zod

L’aide tool fournit une inférence de type TypeScript complète à partir de vos schémas Zod :

tool(
  "process_data",
  "Traiter des données structurées avec sécurité de type",
  {
    // Le schéma Zod définit à la fois la validation d'exécution et les types TypeScript
    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 est entièrement typé basé sur le schéma
    // TypeScript sait : args.data.name est string, args.data.age est number, etc.
    console.log(`Traitement des données de ${args.data.name} en ${args.format}`);
    
    // Votre logique de traitement ici
    return {
      content: [{
        type: "text",
        text: `Données traitées pour ${args.data.name}`
      }]
    };
  }
)

Hooks

Les hooks vous permettent de personnaliser et d’étendre le comportement de Claude Code en exécutant des callbacks personnalisés à divers points du cycle de vie de l’agent. Contrairement aux hooks CLI qui exécutent des commandes bash, les hooks SDK sont des fonctions JavaScript/TypeScript qui s’exécutent en processus.

Définir des hooks

Les hooks sont organisés par type d’événement, avec des matchers optionnels pour filtrer quand ils s’exécutent :

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

for await (const message of query({
  prompt: "Analyser la base de code",
  options: {
    hooks: {
      PreToolUse: [
        {
          matcher: "Write",
          hooks: [
            async (input, toolUseId, { signal }) => {
              console.log(`Sur le point d'écrire le fichier : ${input.tool_input.file_path}`);
              
              // Valider l'opération
              if (input.tool_input.file_path.includes('.env')) {
                return {
                  decision: 'block',
                  stopReason: 'Impossible d\'écrire dans les fichiers d\'environnement'
                };
              }
              
              // Autoriser l'opération
              return { continue: true };
            }
          ]
        }
      ],
      PostToolUse: [
        {
          matcher: "Write|Edit",
          hooks: [
            async (input, toolUseId, { signal }) => {
              console.log(`Fichier modifié : ${input.tool_response.filePath}`);
              // Exécuter votre formatage ou validation personnalisé
              return { continue: true };
            }
          ]
        }
      ]
    }
  }
})) {
  if (message.type === "result") console.log(message.result);
}

Événements de hook disponibles

  • PreToolUse : S’exécute avant l’exécution de l’outil. Peut bloquer les outils ou fournir des commentaires.
  • PostToolUse : S’exécute après l’exécution réussie de l’outil.
  • UserPromptSubmit : S’exécute quand l’utilisateur soumet une invite.
  • SessionStart : S’exécute quand une session démarre.
  • SessionEnd : S’exécute quand une session se termine.
  • Stop : S’exécute quand Claude est sur le point d’arrêter de répondre.
  • SubagentStop : S’exécute quand un sous-agent est sur le point de s’arrêter.
  • PreCompact : S’exécute avant la compaction de conversation.
  • Notification : S’exécute quand des notifications sont envoyées.

Types d’entrée de hook

Chaque hook reçoit une entrée typée basée sur l’événement :

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

// Entrée PostToolUse
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;
}

Sortie de hook

Les hooks retournent une sortie qui contrôle le flux d’exécution :

interface HookJSONOutput {
  // Continuer l'exécution (défaut : true)
  continue?: boolean;
  
  // Supprimer la sortie à l'utilisateur
  suppressOutput?: boolean;
  
  // Raison d'arrêt (montrée au modèle)
  stopReason?: string;
  
  // Décision pour les hooks PreToolUse
  decision?: 'approve' | 'block';
  
  // Message système à afficher
  systemMessage?: string;
  
  // Sortie spécifique au hook
  hookSpecificOutput?: {
    // Pour PreToolUse
    permissionDecision?: 'allow' | 'deny' | 'ask';
    permissionDecisionReason?: string;
    
    // Pour UserPromptSubmit ou PostToolUse
    additionalContext?: string;
  };
}

Exemples pratiques

Journalisation et surveillance

const hooks = {
  PreToolUse: [
    {
      hooks: [
        async (input) => {
          // Journaliser toute utilisation d'outil
          await logToMonitoring({
            event: 'tool_use',
            tool: input.tool_name,
            input: input.tool_input,
            session: input.session_id
          });
          
          return { continue: true };
        }
      ]
    }
  ]
};

Validation des opérations de fichier

const hooks = {
  PreToolUse: [
    {
      matcher: "Write|Edit",
      hooks: [
        async (input) => {
          const filePath = input.tool_input.file_path;
          
          // Bloquer les fichiers sensibles
          const sensitivePatterns = ['.env', '.git/', 'secrets/', '*.key'];
          
          for (const pattern of sensitivePatterns) {
            if (filePath.includes(pattern)) {
              return {
                decision: 'block',
                stopReason: `Impossible de modifier le fichier sensible correspondant à ${pattern}`
              };
            }
          }
          
          return { continue: true };
        }
      ]
    }
  ]
};

Formatage automatique du code

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;
          
          // Formatage automatique basé sur le type de fichier
          if (filePath.endsWith('.ts') || filePath.endsWith('.tsx')) {
            await execAsync(`prettier --write "${filePath}"`);
          } else if (filePath.endsWith('.py')) {
            await execAsync(`black "${filePath}"`);
          }
          
          return { continue: true };
        }
      ]
    }
  ]
};

Amélioration d’invite

const hooks = {
  UserPromptSubmit: [
    {
      hooks: [
        async (input) => {
          // Ajouter du contexte aux invites
          const projectContext = await loadProjectContext();
          
          return {
            continue: true,
            hookSpecificOutput: {
              hookEventName: 'UserPromptSubmit',
              additionalContext: `Contexte du projet : ${projectContext}`
            }
          };
        }
      ]
    }
  ]
};

Instructions de compaction personnalisées

const hooks = {
  PreCompact: [
    {
      hooks: [
        async (input) => {
          const trigger = input.trigger; // 'manual' ou 'auto'
          
          return {
            continue: true,
            systemMessage: 'Concentrez-vous sur la préservation des détails d\'implémentation et des résolutions d\'erreur'
          };
        }
      ]
    }
  ]
};

Comportement d’exécution des hooks

  • Parallélisation : Tous les hooks correspondants s’exécutent en parallèle
  • Timeout : Les hooks respectent le signal d’abandon des options
  • Gestion d’erreur : Les erreurs de hook sont journalisées mais n’arrêtent pas l’exécution
  • Matchers : Supportent les motifs regex (par ex. "Write|Edit")

Combiner les hooks avec canUseTool

Alors que canUseTool fournit un contrôle de permission, les hooks offrent une intégration de cycle de vie plus large :

for await (const message of query({
  prompt: "Construire la fonctionnalité",
  options: {
    // Contrôle de permission fin
    canUseTool: async (toolName, input) => {
      // Modifier les entrées ou refuser basé sur les conditions d'exécution
      return { behavior: "allow", updatedInput: input };
    },
    
    // Hooks de cycle de vie pour la surveillance et l'automatisation
    hooks: {
      PreToolUse: [
        {
          hooks: [
            async (input) => {
              // Journaliser, valider ou préparer
              return { continue: true };
            }
          ]
        }
      ]
    }
  }
})) {
  // Traiter les messages
}

Contrôle de permission avec canUseTool

Le callback canUseTool fournit un contrôle fin sur l’exécution des outils. Il est appelé avant chaque utilisation d’outil et peut autoriser, refuser ou modifier les entrées d’outil :

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

for await (const message of query({
  prompt: "Analyser le comportement utilisateur et calculer les métriques",
  options: {
    mcpServers: {
      "analytics": analyticsServer
    },
    canUseTool: async (toolName: string, input: any) => {
      // Contrôler quels outils peuvent être utilisés
      if (toolName.startsWith("mcp__analytics__")) {
        // Vérifier les permissions pour les outils d'analyse
        const hasPermission = await checkUserPermissions(toolName);
        
        return hasPermission
          ? { behavior: "allow", updatedInput: input }
          : { behavior: "deny", message: "Permissions insuffisantes" };
      }
      
      // Modifier les entrées pour certains outils
      if (toolName === "Bash") {
        // Ajouter des vérifications de sécurité ou modifier les commandes
        const safeInput = sanitizeBashCommand(input);
        return { behavior: "allow", updatedInput: safeInput };
      }
      
      // Autoriser les autres outils par défaut
      return { behavior: "allow", updatedInput: input };
    }
  }
})) {
  if (message.type === "result") console.log(message.result);
}

Cas d’utilisation pour canUseTool

  • Gestion de permissions : Vérifier les permissions utilisateur avant d’autoriser l’exécution d’outil
  • Validation d’entrée : Valider ou assainir les entrées d’outil avant l’exécution
  • Limitation de taux : Implémenter des limites de taux pour les opérations coûteuses
  • Journalisation d’audit : Journaliser l’utilisation d’outil pour la conformité ou le débogage
  • Permissions dynamiques : Activer/désactiver les outils basé sur les conditions d’exécution
// Exemple : Limiteur de taux de scraping web
const rateLimits = new Map<string, { count: number; resetTime: number }>();

const canUseTool = async (toolName: string, input: any) => {
  // Limiter le taux de scraping web pour éviter les bannissements d'IP et les problèmes de quota d'API
  if (toolName === "WebFetch" || toolName === "WebSearch") {
    const now = Date.now();
    const limit = rateLimits.get(toolName) || { count: 0, resetTime: now + 60000 };
    
    // Réinitialiser le compteur chaque minute
    if (now > limit.resetTime) {
      limit.count = 0;
      limit.resetTime = now + 60000;
    }
    
    // Autoriser max 10 requêtes par minute
    if (limit.count >= 10) {
      return { 
        behavior: "deny", 
        message: `Limite de taux dépassée : max 10 requêtes ${toolName} par minute. Réinitialise dans ${Math.ceil((limit.resetTime - now) / 1000)}s` 
      };
    }
    
    limit.count++;
    rateLimits.set(toolName, limit);
    
    // Journaliser l'activité de scraping pour la surveillance
    console.log(`Requête ${toolName} ${limit.count}/10 vers : ${input.url || input.query}`);
  }
  
  // Empêcher les boucles infinies accidentelles dans les scripts bash
  if (toolName === "Bash" && input.command?.includes("while true")) {
    return { 
      behavior: "deny", 
      message: "Les boucles infinies ne sont pas autorisées" 
    };
  }
  
  return { behavior: "allow", updatedInput: input };
};

Formats de sortie

Sortie texte (par défaut)

// Sortie texte par défaut
for await (const message of query({
  prompt: "Expliquer le fichier src/components/Header.tsx"
})) {
  if (message.type === "result" && message.subtype === "success") {
    console.log(message.result);
    // Sortie : Ceci est un composant React montrant...
  }
}

Sortie JSON

// Collecter tous les messages pour un accès de type JSON
const messages = [];
for await (const message of query({
  prompt: "Comment fonctionne la couche de données ?"
})) {
  messages.push(message);
}

// Accéder au message de résultat avec métadonnées
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
});

Formats d’entrée

// Invite directe
for await (const message of query({
  prompt: "Expliquer ce code"
})) {
  if (message.type === "result" && message.subtype === "success") console.log(message.result);
}

// Depuis une variable
const userInput = "Expliquer ce code";
for await (const message of query({ prompt: userInput })) {
  if (message.type === "result" && message.subtype === "success") console.log(message.result);
}

Exemples d’intégration d’agent

Agent de réponse aux incidents SRE

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

// Agent de réponse aux incidents automatisé
async function investigateIncident(
  incidentDescription: string,
  severity = "medium"
) {
  const messages = [];

  for await (const message of query({
    prompt: `Incident : ${incidentDescription} (Gravité : ${severity})`,
    options: {
      appendSystemPrompt: "Vous êtes un expert SRE. Diagnostiquez le problème, évaluez l'impact et fournissez des éléments d'action immédiats.",
      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");
}

// Utilisation
const result = await investigateIncident("L'API de paiement retourne des erreurs 500", "high");
console.log(result.result);

Révision de sécurité automatisée

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

async function auditPR(prNumber: number) {
  // Obtenir le diff de la PR
  const prDiff = execSync(`gh pr diff ${prNumber}`, { encoding: 'utf8' });

  const messages = [];
  for await (const message of query({
    prompt: prDiff,
    options: {
      appendSystemPrompt: "Vous êtes un ingénieur en sécurité. Révisez cette PR pour les vulnérabilités, les motifs non sécurisés et les problèmes de conformité.",
      maxTurns: 3,
      allowedTools: ["Read", "Grep", "WebSearch"]
    }
  })) {
    messages.push(message);
  }

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

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

Assistant juridique multi-tours

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

async function legalReview() {
  // Démarrer la session de révision juridique
  let sessionId: string;

  for await (const message of query({
    prompt: "Démarrer la session de révision juridique",
    options: { maxTurns: 1 }
  })) {
    if (message.type === "system" && message.subtype === "init") {
      sessionId = message.session_id;
    }
  }

  // Révision multi-étapes utilisant la même session
  const steps = [
    "Réviser contract.pdf pour les clauses de responsabilité",
    "Vérifier la conformité avec les exigences RGPD",
    "Générer un résumé exécutif des risques"
  ];

  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(`Étape : ${step}`);
        console.log(message.result);
      }
    }
  }
}

Schéma de message

Les messages retournés par l’API JSON sont strictement typés selon le schéma suivant :

type SDKMessage =
  // Un message d'assistant
  | {
      type: "assistant";
      uuid: string;
      session_id: string;
      message: Message; // du SDK Anthropic
      parent_tool_use_id: string | null;
    }

  // Un message utilisateur (entrée)
  | {
      type: "user";
      uuid?: string;
      session_id: string;
      message: MessageParam; // du SDK Anthropic
      parent_tool_use_id: string | null;
    }

  // Un message utilisateur (sortie/replay avec UUID requis)
  | {
      type: "user";
      uuid: string;
      session_id: string;
      message: MessageParam; // du SDK Anthropic
      parent_tool_use_id: string | null;
    }

  // Émis comme dernier message en cas de succès
  | {
      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[];
    }

  // Émis comme dernier message en cas d'erreur ou de tours maximum
  | {
      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[];
    }

  // Émis comme premier message au début d'une conversation
  | {
      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>;
  }

Types de support supplémentaires :

Les types Message, MessageParam et Usage sont disponibles dans le SDK TypeScript Anthropic.

Ressources connexes