전제 조건

  • Node.js 18+

설치

NPM에서 @anthropic-ai/claude-code를 설치하세요:
npm install -g @anthropic-ai/claude-code
TypeScript SDK 소스 코드를 보려면 NPM의 @anthropic-ai/claude-code 페이지를 방문하세요.

기본 사용법

TypeScript SDK를 통한 주요 인터페이스는 query 함수로, 메시지가 도착하는 대로 스트리밍하는 비동기 이터레이터를 반환합니다:
import { query } from "@anthropic-ai/claude-code";

for await (const message of query({
  prompt: "시스템 성능 분석",
  options: {
    maxTurns: 5,
    appendSystemPrompt: "당신은 성능 엔지니어입니다",
    allowedTools: ["Bash", "Read", "WebSearch"],
    abortController: new AbortController(),
  }
})) {
  if (message.type === "result" && message.subtype === "success") {
    console.log(message.result);
  }
}

구성 옵션

인수타입설명기본값
abortControllerAbortController작업 취소를 위한 중단 컨트롤러new AbortController()
additionalDirectoriesstring[]세션에 포함할 추가 디렉토리undefined
allowedToolsstring[]Claude가 사용할 수 있는 도구 목록기본적으로 모든 도구 활성화
appendSystemPromptstring기본 시스템 프롬프트에 추가할 텍스트undefined
canUseTool(toolName: string, input: any) => Promise<ToolPermissionResult>도구 사용을 위한 맞춤형 권한 함수undefined
continueboolean가장 최근 세션 계속하기false
customSystemPromptstring기본 시스템 프롬프트를 완전히 교체undefined
cwdstring현재 작업 디렉토리process.cwd()
disallowedToolsstring[]Claude가 사용할 수 없는 도구 목록undefined
envDict<string>설정할 환경 변수undefined
executable'bun' | 'deno' | 'node'사용할 JavaScript 런타임Node.js로 실행할 때 node, Bun으로 실행할 때 bun
executableArgsstring[]실행 파일에 전달할 인수[]
fallbackModelstring기본 모델이 실패할 때 사용할 모델undefined
hooksPartial<Record<HookEvent, HookCallbackMatcher[]>>맞춤화를 위한 라이프사이클 훅undefined
includePartialMessagesboolean메시지 스트림에 부분 스트리밍 이벤트 포함false
maxThinkingTokensnumberClaude의 사고 과정을 위한 최대 토큰undefined
maxTurnsnumber대화 턴의 최대 수undefined
mcpServersRecord<string, McpServerConfig>MCP 서버 구성undefined
modelstring사용할 Claude 모델CLI 구성의 기본값 사용
pathToClaudeCodeExecutablestringClaude Code 실행 파일 경로@anthropic-ai/claude-code와 함께 제공되는 실행 파일
permissionModePermissionMode세션의 권한 모드"default" (옵션: "default", "acceptEdits", "bypassPermissions", "plan")
resumestring재개할 세션 IDundefined
stderr(data: string) => voidstderr 출력을 위한 콜백undefined
strictMcpConfigboolean엄격한 MCP 구성 검증 강제undefined

부분 메시지 스트리밍

includePartialMessages가 활성화되면, SDK는 Claude API의 원시 스트리밍 이벤트를 포함하는 stream_event 메시지를 방출합니다. 이를 통해 생성되는 동안 부분 콘텐츠에 액세스할 수 있어 실시간 UI 업데이트나 진행률 표시기를 구현하는 데 유용합니다.
import { query } from "@anthropic-ai/claude-code";

for await (const message of query({
  prompt: "인공지능에 대한 긴 에세이 작성",
  options: {
    includePartialMessages: true,
    maxTurns: 1
  }
})) {
  // 부분 스트리밍 이벤트 처리
  if (message.type === "stream_event") {
    const event = message.event;
    
    // 스트리밍되는 부분 텍스트에 액세스
    if (event.type === "content_block_delta" && event.delta.type === "text_delta") {
      process.stdout.write(event.delta.text);
    }
    
    // 사고 진행률 추적
    if (event.type === "content_block_start" && event.content_block.type === "thinking") {
      console.log("\n[Claude가 생각하고 있습니다...]");
    }
  }
  
  // 최종 결과도 여전히 받음
  if (message.type === "result" && message.subtype === "success") {
    console.log("\n최종 결과:", message.result);
  }
}
stream_event 메시지에는 다음이 포함됩니다:
  • event: API의 원시 스트리밍 이벤트
  • session_id: 현재 세션 식별자
  • parent_tool_use_id: 실행 중인 도구의 ID (해당하는 경우)
  • uuid: 이 이벤트의 고유 식별자
부분 메시지 스트리밍은 주로 스트리밍 응답에 대한 세밀한 제어가 필요한 고급 사용 사례에 유용합니다. 대부분의 애플리케이션에서는 기본 동작(완전한 메시지 대기)으로 충분합니다.

다중 턴 대화

다중 턴 대화의 경우 두 가지 옵션이 있습니다. 응답을 생성하고 재개하거나, 메시지 배열에 대한 비동기/제너레이터를 허용하는 스트리밍 입력 모드를 사용할 수 있습니다. 현재 스트리밍 입력 모드는 메시지를 통해 이미지를 첨부하는 유일한 방법입니다.

세션 관리로 재개

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

// 가장 최근 대화 계속하기
for await (const message of query({
  prompt: "이제 더 나은 성능을 위해 리팩토링하세요",
  options: { continue: true }
})) { 
  if (message.type === "result" && message.subtype === "success") console.log(message.result);
}

// 특정 세션 재개
for await (const message of query({
  prompt: "테스트 업데이트",
  options: {
    resume: "550e8400-e29b-41d4-a716-446655440000",
    maxTurns: 3
  }
})) {
  if (message.type === "result" && message.subtype === "success") console.log(message.result);
}

스트리밍 입력 모드

스트리밍 입력 모드를 사용하면 단일 문자열 대신 비동기 이터러블로 메시지를 제공할 수 있습니다. 이를 통해 다중 턴 대화, 이미지 첨부 및 동적 메시지 생성이 가능합니다:
import { query } from "@anthropic-ai/claude-code";

// 스트리밍 메시지를 위한 비동기 제너레이터 생성
async function* generateMessages() {
  yield {
    type: "user" as const,
    message: {
      role: "user" as const,
      content: "이 코드베이스 분석 시작"
    }
  };
  
  // 어떤 조건이나 사용자 입력 대기
  await new Promise(resolve => setTimeout(resolve, 1000));
  
  yield {
    type: "user" as const,
    message: {
      role: "user" as const,
      content: "이제 인증 모듈에 집중하세요"
    }
  };
}

// 스트리밍 입력 사용
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);
  }
}

이미지가 포함된 스트리밍 입력

스트리밍 입력 모드는 메시지를 통해 이미지를 첨부하는 유일한 방법입니다:
import { query } from "@anthropic-ai/claude-code";
import { readFileSync } from "fs";

async function* messagesWithImage() {
  // 텍스트와 함께 이미지 전송
  yield {
    type: "user" as const,
    message: {
      role: "user" as const,
      content: [
        {
          type: "text",
          text: "이 스크린샷을 분석하고 개선 사항을 제안하세요"
        },
        {
          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);
}

맞춤형 시스템 프롬프트

시스템 프롬프트는 에이전트의 역할, 전문성 및 동작을 정의합니다:
import { query } from "@anthropic-ai/claude-code";

// SRE 인시던트 대응 에이전트
for await (const message of query({
  prompt: "API가 다운되었습니다. 조사하세요",
  options: {
    customSystemPrompt: "당신은 SRE 전문가입니다. 문제를 체계적으로 진단하고 실행 가능한 솔루션을 제공하세요.",
    maxTurns: 3
  }
})) {
  if (message.type === "result" && message.subtype === "success") console.log(message.result);
}

// 기본 시스템 프롬프트에 추가
for await (const message of query({
  prompt: "이 함수를 리팩토링하세요",
  options: {
    appendSystemPrompt: "항상 포괄적인 오류 처리와 단위 테스트를 포함하세요.",
    maxTurns: 2
  }
})) {
  if (message.type === "result" && message.subtype === "success") console.log(message.result);
}

MCP 서버 통합

모델 컨텍스트 프로토콜(MCP)을 통해 에이전트에게 맞춤형 도구와 기능을 제공할 수 있습니다:
import { query } from "@anthropic-ai/claude-code";

// 모니터링 도구가 있는 SRE 에이전트
for await (const message of query({
  prompt: "결제 서비스 장애를 조사하세요",
  options: {
    mcpConfig: "sre-tools.json",
    allowedTools: ["mcp__datadog", "mcp__pagerduty", "mcp__kubernetes"],
    appendSystemPrompt: "당신은 SRE입니다. 모니터링 데이터를 사용하여 문제를 진단하세요.",
    maxTurns: 4
  }
})) {
  if (message.type === "result" && message.subtype === "success") console.log(message.result);
}

인프로세스 MCP 서버를 사용한 맞춤형 도구

SDK MCP 서버를 사용하면 별도의 프로세스나 네트워크 통신의 오버헤드 없이 애플리케이션 프로세스에서 직접 실행되는 맞춤형 도구를 만들 수 있으며, 타입 안전한 도구 실행을 제공합니다.

맞춤형 도구 생성

createSdkMcpServertool 헬퍼 함수를 사용하여 타입 안전한 맞춤형 도구를 정의하세요:
import { query, tool, createSdkMcpServer } from "@anthropic-ai/claude-code";
import { z } from "zod";

// 맞춤형 도구가 있는 SDK MCP 서버 생성
const customServer = createSdkMcpServer({
  name: "my-custom-tools",
  version: "1.0.0",
  tools: [
    tool(
      "calculate_compound_interest",
      "투자에 대한 복리 이자 계산",
      {
        principal: z.number().describe("초기 투자 금액"),
        rate: z.number().describe("연간 이자율 (소수점으로, 예: 5%의 경우 0.05)"),
        time: z.number().describe("투자 기간(년)"),
        n: z.number().default(12).describe("연간 복리 빈도")
      },
      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: `최종 금액: $${amount.toFixed(2)}\n획득한 이자: $${interest.toFixed(2)}`
          }]
        };
      }
    ),
    tool(
      "fetch_user_data",
      "애플리케이션 데이터베이스에서 사용자 데이터 가져오기",
      {
        userId: z.string().describe("가져올 사용자 ID"),
        fields: z.array(z.string()).optional().describe("반환할 특정 필드")
      },
      async (args) => {
        // 애플리케이션의 데이터 레이어에 직접 액세스
        const userData = await myDatabase.getUser(args.userId, args.fields);
        
        return {
          content: [{
            type: "text",
            text: JSON.stringify(userData, null, 2)
          }]
        };
      }
    )
  ]
});

// 쿼리에서 맞춤형 도구 사용
for await (const message of query({
  prompt: "$10,000을 5%로 10년간 복리 이자 계산",
  options: {
    mcpServers: {
      "my-custom-tools": customServer
    },
    maxTurns: 3
  }
})) {
  if (message.type === "result") {
    console.log(message.result);
  }
}

Zod를 사용한 타입 안전성

tool 헬퍼는 Zod 스키마에서 완전한 TypeScript 타입 추론을 제공합니다:
tool(
  "process_data",
  "타입 안전성을 갖춘 구조화된 데이터 처리",
  {
    // Zod 스키마는 런타임 검증과 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는 스키마를 기반으로 완전히 타입화됨
    // TypeScript는 다음을 알고 있음: args.data.name은 string, args.data.age는 number 등
    console.log(`${args.data.name}의 데이터를 ${args.format}으로 처리 중`);
    
    // 여기에 처리 로직
    return {
      content: [{
        type: "text",
        text: `${args.data.name}의 데이터 처리 완료`
      }]
    };
  }
)

훅을 사용하면 에이전트의 라이프사이클의 다양한 지점에서 맞춤형 콜백을 실행하여 Claude Code의 동작을 맞춤화하고 확장할 수 있습니다. bash 명령을 실행하는 CLI 훅과 달리 SDK 훅은 인프로세스에서 실행되는 JavaScript/TypeScript 함수입니다.

훅 정의

훅은 이벤트 타입별로 구성되며, 언제 실행될지 필터링하는 선택적 매처가 있습니다:
import { query } from "@anthropic-ai/claude-code";

for await (const message of query({
  prompt: "코드베이스 분석",
  options: {
    hooks: {
      PreToolUse: [
        {
          matcher: "Write",
          hooks: [
            async (input, toolUseId, { signal }) => {
              console.log(`파일 쓰기 예정: ${input.tool_input.file_path}`);
              
              // 작업 검증
              if (input.tool_input.file_path.includes('.env')) {
                return {
                  decision: 'block',
                  stopReason: '환경 파일에 쓸 수 없습니다'
                };
              }
              
              // 작업 허용
              return { continue: true };
            }
          ]
        }
      ],
      PostToolUse: [
        {
          matcher: "Write|Edit",
          hooks: [
            async (input, toolUseId, { signal }) => {
              console.log(`파일 수정됨: ${input.tool_response.filePath}`);
              // 맞춤형 포맷팅이나 검증 실행
              return { continue: true };
            }
          ]
        }
      ]
    }
  }
})) {
  if (message.type === "result") console.log(message.result);
}

사용 가능한 훅 이벤트

  • PreToolUse: 도구 실행 전에 실행됩니다. 도구를 차단하거나 피드백을 제공할 수 있습니다.
  • PostToolUse: 성공적인 도구 실행 후에 실행됩니다.
  • UserPromptSubmit: 사용자가 프롬프트를 제출할 때 실행됩니다.
  • SessionStart: 세션이 시작될 때 실행됩니다.
  • SessionEnd: 세션이 종료될 때 실행됩니다.
  • Stop: Claude가 응답을 중지하려고 할 때 실행됩니다.
  • SubagentStop: 서브에이전트가 중지하려고 할 때 실행됩니다.
  • PreCompact: 대화 압축 전에 실행됩니다.
  • Notification: 알림이 전송될 때 실행됩니다.

훅 입력 타입

각 훅은 이벤트를 기반으로 타입화된 입력을 받습니다:
// PreToolUse 입력
type PreToolUseHookInput = {
  hook_event_name: 'PreToolUse';
  session_id: string;
  transcript_path: string;
  cwd: string;
  permission_mode?: string;
  tool_name: string;
  tool_input: unknown;
}

// 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;
}

훅 출력

훅은 실행 흐름을 제어하는 출력을 반환합니다:
interface HookJSONOutput {
  // 실행 계속 (기본값: true)
  continue?: boolean;
  
  // 사용자에게 출력 억제
  suppressOutput?: boolean;
  
  // 중지 이유 (모델에 표시)
  stopReason?: string;
  
  // PreToolUse 훅의 결정
  decision?: 'approve' | 'block';
  
  // 표시할 시스템 메시지
  systemMessage?: string;
  
  // 훅별 출력
  hookSpecificOutput?: {
    // PreToolUse용
    permissionDecision?: 'allow' | 'deny' | 'ask';
    permissionDecisionReason?: string;
    
    // UserPromptSubmit 또는 PostToolUse용
    additionalContext?: string;
  };
}

실용적인 예제

로깅 및 모니터링

const hooks = {
  PreToolUse: [
    {
      hooks: [
        async (input) => {
          // 모든 도구 사용 로깅
          await logToMonitoring({
            event: 'tool_use',
            tool: input.tool_name,
            input: input.tool_input,
            session: input.session_id
          });
          
          return { continue: true };
        }
      ]
    }
  ]
};

파일 작업 검증

const hooks = {
  PreToolUse: [
    {
      matcher: "Write|Edit",
      hooks: [
        async (input) => {
          const filePath = input.tool_input.file_path;
          
          // 민감한 파일 차단
          const sensitivePatterns = ['.env', '.git/', 'secrets/', '*.key'];
          
          for (const pattern of sensitivePatterns) {
            if (filePath.includes(pattern)) {
              return {
                decision: 'block',
                stopReason: `${pattern}과 일치하는 민감한 파일을 수정할 수 없습니다`
              };
            }
          }
          
          return { continue: true };
        }
      ]
    }
  ]
};

코드 자동 포맷팅

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;
          
          // 파일 타입에 따른 자동 포맷팅
          if (filePath.endsWith('.ts') || filePath.endsWith('.tsx')) {
            await execAsync(`prettier --write "${filePath}"`);
          } else if (filePath.endsWith('.py')) {
            await execAsync(`black "${filePath}"`);
          }
          
          return { continue: true };
        }
      ]
    }
  ]
};

프롬프트 향상

const hooks = {
  UserPromptSubmit: [
    {
      hooks: [
        async (input) => {
          // 프롬프트에 컨텍스트 추가
          const projectContext = await loadProjectContext();
          
          return {
            continue: true,
            hookSpecificOutput: {
              hookEventName: 'UserPromptSubmit',
              additionalContext: `프로젝트 컨텍스트: ${projectContext}`
            }
          };
        }
      ]
    }
  ]
};

맞춤형 압축 지침

const hooks = {
  PreCompact: [
    {
      hooks: [
        async (input) => {
          const trigger = input.trigger; // 'manual' 또는 'auto'
          
          return {
            continue: true,
            systemMessage: '구현 세부사항과 오류 해결 방법 보존에 집중하세요'
          };
        }
      ]
    }
  ]
};

훅 실행 동작

  • 병렬화: 일치하는 모든 훅이 병렬로 실행됩니다
  • 타임아웃: 훅은 옵션의 중단 신호를 존중합니다
  • 오류 처리: 훅 오류는 로깅되지만 실행을 중지하지 않습니다
  • 매처: 정규식 패턴을 지원합니다 (예: "Write|Edit")

canUseTool과 훅 결합

canUseTool이 권한 제어를 제공하는 반면, 훅은 더 광범위한 라이프사이클 통합을 제공합니다:
for await (const message of query({
  prompt: "기능 구축",
  options: {
    // 세밀한 권한 제어
    canUseTool: async (toolName, input) => {
      // 런타임 조건에 따라 입력을 수정하거나 거부
      return { behavior: "allow", updatedInput: input };
    },
    
    // 모니터링 및 자동화를 위한 라이프사이클 훅
    hooks: {
      PreToolUse: [
        {
          hooks: [
            async (input) => {
              // 로깅, 검증 또는 준비
              return { continue: true };
            }
          ]
        }
      ]
    }
  }
})) {
  // 메시지 처리
}

canUseTool을 사용한 권한 제어

canUseTool 콜백은 도구 실행에 대한 세밀한 제어를 제공합니다. 각 도구 사용 전에 호출되며 도구 입력을 허용, 거부 또는 수정할 수 있습니다:
type ToolPermissionResult = 
  | { behavior: "allow"; updatedInput?: any }
  | { behavior: "deny"; message?: string };

for await (const message of query({
  prompt: "사용자 행동 분석 및 메트릭 계산",
  options: {
    mcpServers: {
      "analytics": analyticsServer
    },
    canUseTool: async (toolName: string, input: any) => {
      // 사용할 수 있는 도구 제어
      if (toolName.startsWith("mcp__analytics__")) {
        // 분석 도구에 대한 권한 확인
        const hasPermission = await checkUserPermissions(toolName);
        
        return hasPermission
          ? { behavior: "allow", updatedInput: input }
          : { behavior: "deny", message: "권한이 부족합니다" };
      }
      
      // 특정 도구의 입력 수정
      if (toolName === "Bash") {
        // 안전 검사 추가 또는 명령 수정
        const safeInput = sanitizeBashCommand(input);
        return { behavior: "allow", updatedInput: safeInput };
      }
      
      // 기본적으로 다른 도구 허용
      return { behavior: "allow", updatedInput: input };
    }
  }
})) {
  if (message.type === "result") console.log(message.result);
}

canUseTool 사용 사례

  • 권한 관리: 도구 실행을 허용하기 전에 사용자 권한 확인
  • 입력 검증: 실행 전에 도구 입력 검증 또는 정리
  • 속도 제한: 비용이 많이 드는 작업에 대한 속도 제한 구현
  • 감사 로깅: 규정 준수 또는 디버깅을 위한 도구 사용 로깅
  • 동적 권한: 런타임 조건에 따라 도구 활성화/비활성화
// 예제: 웹 스크래핑 속도 제한기
const rateLimits = new Map<string, { count: number; resetTime: number }>();

const canUseTool = async (toolName: string, input: any) => {
  // IP 차단 및 API 할당량 문제를 방지하기 위해 웹 스크래핑 속도 제한
  if (toolName === "WebFetch" || toolName === "WebSearch") {
    const now = Date.now();
    const limit = rateLimits.get(toolName) || { count: 0, resetTime: now + 60000 };
    
    // 매분마다 카운터 재설정
    if (now > limit.resetTime) {
      limit.count = 0;
      limit.resetTime = now + 60000;
    }
    
    // 분당 최대 10개 요청 허용
    if (limit.count >= 10) {
      return { 
        behavior: "deny", 
        message: `속도 제한 초과: 분당 최대 10개 ${toolName} 요청. ${Math.ceil((limit.resetTime - now) / 1000)}초 후 재설정` 
      };
    }
    
    limit.count++;
    rateLimits.set(toolName, limit);
    
    // 모니터링을 위한 스크래핑 활동 로깅
    console.log(`${toolName} 요청 ${limit.count}/10 대상: ${input.url || input.query}`);
  }
  
  // bash 스크립트에서 우발적인 무한 루프 방지
  if (toolName === "Bash" && input.command?.includes("while true")) {
    return { 
      behavior: "deny", 
      message: "무한 루프는 허용되지 않습니다" 
    };
  }
  
  return { behavior: "allow", updatedInput: input };
};

출력 형식

텍스트 출력 (기본값)

// 기본 텍스트 출력
for await (const message of query({
  prompt: "src/components/Header.tsx 파일 설명"
})) {
  if (message.type === "result" && message.subtype === "success") {
    console.log(message.result);
    // 출력: 이것은 다음을 보여주는 React 컴포넌트입니다...
  }
}

JSON 출력

// JSON과 같은 액세스를 위해 모든 메시지 수집
const messages = [];
for await (const message of query({
  prompt: "데이터 레이어는 어떻게 작동하나요?"
})) {
  messages.push(message);
}

// 메타데이터와 함께 결과 메시지에 액세스
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
});

입력 형식

// 직접 프롬프트
for await (const message of query({
  prompt: "이 코드 설명"
})) {
  if (message.type === "result" && message.subtype === "success") console.log(message.result);
}

// 변수에서
const userInput = "이 코드 설명";
for await (const message of query({ prompt: userInput })) {
  if (message.type === "result" && message.subtype === "success") console.log(message.result);
}

에이전트 통합 예제

SRE 인시던트 대응 에이전트

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

// 자동화된 인시던트 대응 에이전트
async function investigateIncident(
  incidentDescription: string,
  severity = "medium"
) {
  const messages = [];

  for await (const message of query({
    prompt: `인시던트: ${incidentDescription} (심각도: ${severity})`,
    options: {
      appendSystemPrompt: "당신은 SRE 전문가입니다. 문제를 진단하고 영향을 평가하며 즉각적인 행동 항목을 제공하세요.",
      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");
}

// 사용법
const result = await investigateIncident("결제 API가 500 오류 반환", "high");
console.log(result.result);

자동화된 보안 검토

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

async function auditPR(prNumber: number) {
  // PR diff 가져오기
  const prDiff = execSync(`gh pr diff ${prNumber}`, { encoding: 'utf8' });

  const messages = [];
  for await (const message of query({
    prompt: prDiff,
    options: {
      appendSystemPrompt: "당신은 보안 엔지니어입니다. 이 PR에서 취약점, 안전하지 않은 패턴 및 규정 준수 문제를 검토하세요.",
      maxTurns: 3,
      allowedTools: ["Read", "Grep", "WebSearch"]
    }
  })) {
    messages.push(message);
  }

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

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

다중 턴 법무 어시스턴트

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

async function legalReview() {
  // 법무 검토 세션 시작
  let sessionId: string;

  for await (const message of query({
    prompt: "법무 검토 세션 시작",
    options: { maxTurns: 1 }
  })) {
    if (message.type === "system" && message.subtype === "init") {
      sessionId = message.session_id;
    }
  }

  // 동일한 세션을 사용한 다단계 검토
  const steps = [
    "contract.pdf에서 책임 조항 검토",
    "GDPR 요구사항 준수 확인",
    "위험에 대한 경영진 요약 생성"
  ];

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

메시지 스키마

JSON API에서 반환되는 메시지는 다음 스키마에 따라 엄격하게 타입화됩니다:
type SDKMessage =
  // 어시스턴트 메시지
  | {
      type: "assistant";
      uuid: string;
      session_id: string;
      message: Message; // Anthropic SDK에서
      parent_tool_use_id: string | null;
    }

  // 사용자 메시지 (입력)
  | {
      type: "user";
      uuid?: string;
      session_id: string;
      message: MessageParam; // Anthropic SDK에서
      parent_tool_use_id: string | null;
    }

  // 사용자 메시지 (출력/재생, 필수 UUID 포함)
  | {
      type: "user";
      uuid: string;
      session_id: string;
      message: MessageParam; // Anthropic SDK에서
      parent_tool_use_id: string | null;
    }

  // 성공 시 마지막 메시지로 방출
  | {
      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[];
    }

  // 오류 또는 최대 턴 시 마지막 메시지로 방출
  | {
      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[];
    }

  // 대화 시작 시 첫 번째 메시지로 방출
  | {
      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>;
  }

추가 지원 타입: Message, MessageParam, Usage 타입은 Anthropic TypeScript SDK에서 사용할 수 있습니다.

관련 리소스