SDK 권한

Claude Code SDK는 애플리케이션에서 Claude가 도구를 사용하는 방법을 관리할 수 있는 강력한 권한 제어 기능을 제공합니다. 이 가이드는 canUseTool 콜백, 훅, 그리고 settings.json 권한 규칙을 사용하여 권한 시스템을 구현하는 방법을 다룹니다. 완전한 API 문서는 TypeScript SDK 참조를 참조하세요.

개요

Claude Code SDK는 도구 사용을 제어하는 네 가지 보완적인 방법을 제공합니다:
  1. 권한 모드 - 모든 도구에 영향을 미치는 전역 권한 동작 설정
  2. canUseTool 콜백 - 다른 규칙으로 다루어지지 않는 경우를 위한 런타임 권한 핸들러
  3. - 사용자 정의 로직으로 모든 도구 실행에 대한 세밀한 제어
  4. 권한 규칙 (settings.json) - 통합된 bash 명령 파싱을 포함한 선언적 허용/거부 규칙
각 접근 방식의 사용 사례:
  • 권한 모드 - 전반적인 권한 동작 설정 (계획, 편집 자동 승인, 검사 우회)
  • canUseTool - 다루어지지 않은 경우에 대한 동적 승인, 사용자에게 권한 요청
  • 훅 - 모든 도구 실행에 대한 프로그래밍적 제어
  • 권한 규칙 - 지능적인 bash 명령 파싱을 포함한 정적 정책

권한 흐름 다이어그램

처리 순서: PreToolUse 훅 → Ask 규칙 → Deny 규칙 → 권한 모드 확인 → Allow 규칙 → canUseTool 콜백 → PostToolUse 훅

권한 모드

권한 모드는 Claude가 도구를 사용하는 방법에 대한 전역 제어를 제공합니다. query()를 호출할 때 권한 모드를 설정하거나 스트리밍 세션 중에 동적으로 변경할 수 있습니다.

사용 가능한 모드

SDK는 각각 다른 동작을 가진 네 가지 권한 모드를 지원합니다:
모드설명도구 동작
default표준 권한 동작일반적인 권한 검사가 적용됨
plan계획 모드 - 실행 없음Claude는 읽기 전용 도구만 사용 가능; 실행 전에 계획을 제시 (현재 SDK에서 지원되지 않음)
acceptEdits파일 편집 자동 승인파일 편집 및 파일시스템 작업이 자동으로 승인됨
bypassPermissions모든 권한 검사 우회모든 도구가 권한 프롬프트 없이 실행됨 (주의해서 사용)

권한 모드 설정

권한 모드는 두 가지 방법으로 설정할 수 있습니다:

1. 초기 구성

쿼리를 생성할 때 모드를 설정합니다:
import { query } from "@anthropic-ai/claude-code";

const result = await query({
  prompt: "이 코드를 리팩토링하는 데 도움을 주세요",
  options: {
    permissionMode: 'default'  // 표준 권한 모드
  }
});

2. 동적 모드 변경 (스트리밍만)

스트리밍 세션 중에 모드를 변경합니다:
import { query } from "@anthropic-ai/claude-code";

// 스트리밍 입력을 위한 비동기 제너레이터 생성
async function* streamInput() {
  yield { 
    type: 'user',
    message: { 
      role: 'user', 
      content: "기본 권한으로 시작해봅시다" 
    }
  };
  
  // 대화 중 나중에...
  yield {
    type: 'user',
    message: {
      role: 'user',
      content: "이제 개발 속도를 높여봅시다"
    }
  };
}

const q = query({
  prompt: streamInput(),
  options: {
    permissionMode: 'default'  // 기본 모드로 시작
  }
});

// 동적으로 모드 변경
await q.setPermissionMode('acceptEdits');

// 메시지 처리
for await (const message of q) {
  console.log(message);
}

모드별 동작

편집 승인 모드 (acceptEdits)

편집 승인 모드에서:
  • 모든 파일 편집이 자동으로 승인됨
  • 파일시스템 작업 (mkdir, touch, rm 등)이 자동 승인됨
  • 다른 도구들은 여전히 일반적인 권한이 필요함
  • Claude의 편집을 신뢰할 때 개발 속도를 높임
  • 빠른 프로토타이핑과 반복에 유용함
자동 승인되는 작업:
  • 파일 편집 (Edit, MultiEdit, Write 도구)
  • Bash 파일시스템 명령 (mkdir, touch, rm, mv, cp)
  • 파일 생성 및 삭제

권한 우회 모드 (bypassPermissions)

권한 우회 모드에서:
  • 모든 도구 사용이 자동으로 승인됨
  • 권한 프롬프트가 나타나지 않음
  • 훅은 여전히 실행됨 (여전히 작업을 차단할 수 있음)
  • 극도로 주의해서 사용 - Claude가 전체 시스템 접근 권한을 가짐
  • 제어된 환경에서만 권장됨

권한 흐름에서의 모드 우선순위

권한 모드는 권한 흐름의 특정 지점에서 평가됩니다:
  1. 훅이 먼저 실행됨 - 모든 모드를 재정의할 수 있음
  2. 거부 규칙이 확인됨 - 모드에 관계없이 도구를 차단함
  3. bypassPermissions 모드 - 활성화되면 나머지 모든 도구를 허용함
  4. 허용 규칙이 확인됨
  5. 기타 모드가 특정 도구 동작에 영향을 미침
  6. canUseTool 콜백 - 나머지 경우를 처리함
이는 다음을 의미합니다:
  • 훅은 bypassPermissions 모드에서도 항상 도구 사용을 차단할 수 있음
  • 명시적 거부 규칙은 모든 권한 모드를 재정의함
  • bypassPermissions 모드는 허용 규칙과 canUseTool을 재정의함

모범 사례

  1. 기본 모드 사용 - 일반적인 권한 검사를 통한 제어된 실행
  2. acceptEdits 모드 사용 - 격리된 파일이나 디렉토리에서 작업할 때
  3. bypassPermissions 피하기 - 프로덕션이나 민감한 데이터가 있는 시스템에서
  4. 모드와 훅 결합 - 세밀한 제어를 위해
  5. 동적으로 모드 전환 - 작업 진행 상황과 신뢰도에 따라
모드 진행 예시:
// 제어된 실행을 위해 기본 모드로 시작
permissionMode: 'default'

// 빠른 반복을 위해 acceptEdits로 전환
await q.setPermissionMode('acceptEdits')

canUseTool

canUseTool 콜백은 query 함수를 호출할 때 옵션으로 전달됩니다. 도구 이름과 입력 매개변수를 받아서 허용 또는 거부 결정을 반환해야 합니다. canUseTool은 Claude Code가 사용자에게 권한 프롬프트를 표시할 때마다 실행됩니다. 예를 들어 훅과 권한 규칙이 이를 다루지 않고 자동 승인 모드가 아닐 때입니다. 다음은 대화형 도구 승인을 구현하는 방법을 보여주는 완전한 예시입니다:
import { query } from "@anthropic-ai/claude-code";

async function promptForToolApproval(toolName: string, input: any) {
  console.log("\n🔧 도구 요청:");
  console.log(`   도구: ${toolName}`);
  
  // 도구 매개변수 표시
  if (input && Object.keys(input).length > 0) {
    console.log("   매개변수:");
    for (const [key, value] of Object.entries(input)) {
      let displayValue = value;
      if (typeof value === 'string' && value.length > 100) {
        displayValue = value.substring(0, 100) + "...";
      } else if (typeof value === 'object') {
        displayValue = JSON.stringify(value, null, 2);
      }
      console.log(`     ${key}: ${displayValue}`);
    }
  }
  
  // 사용자 승인 받기 (UI 로직으로 교체)
  const approved = await getUserApproval();
  
  if (approved) {
    console.log("   ✅ 승인됨\n");
    return {
      behavior: "allow",
      updatedInput: input
    };
  } else {
    console.log("   ❌ 거부됨\n");
    return {
      behavior: "deny",
      message: "사용자가 이 도구에 대한 권한을 거부했습니다"
    };
  }
}

// 권한 콜백 사용
const result = await query({
  prompt: "이 코드베이스를 분석하는 데 도움을 주세요",
  options: {
    canUseTool: async (toolName, input) => {
      return promptForToolApproval(toolName, input);
    }
  }
});

도구 제어를 위한 훅 사용

훅은 다양한 단계에서 도구 실행에 대한 프로그래밍적 제어를 제공합니다. 훅은 모든 도구 사용에 대해 호출되어 권한 파이프라인에 대한 완전한 제어를 제공합니다.

훅 구현

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

const result = await query({
  prompt: "이 코드를 리팩토링하는 데 도움을 주세요",
  options: {
    hooks: {
      PreToolUse: [{
        hooks: [async (input, toolUseId, { signal }) => {
          console.log(`도구 요청: ${input.tool_name}`);
          
          // 도구 입력을 직접 파싱하고 검증
          if (input.tool_name === "Bash") {
            const command = input.tool_input.command;
            if (command.startsWith("rm -rf")) {
              return {
                decision: "block",
                reason: "위험한 명령이 차단되었습니다"
              };
            }
          }
          
          return { continue: true };
        }]
      }],
      PostToolUse: [{
        hooks: [async (input, toolUseId, { signal }) => {
          console.log(`도구 완료: ${input.tool_name}`);
          // 도구 결과 로그 또는 감사
          return { continue: true };
        }]
      }]
    }
  }
});

canUseTool과의 주요 차이점

  • 범위: 훅은 모든 도구 사용에 대해 호출됨; canUseTool은 권한 규칙으로 다루어지지 않는 경우를 처리함
  • 제어: 훅은 입력을 직접 파싱하고 검증해야 함
  • 이벤트: 훅은 다양한 단계를 위한 여러 이벤트 (PreToolUse, PostToolUse 등)를 지원함

권한 규칙 사용 (settings.json)

settings.json의 권한 규칙은 내장된 bash 명령 파싱을 통한 선언적 제어를 제공합니다. 이러한 규칙은 canUseTool이 호출되기 전에 평가됩니다. 설정 구성에 대한 자세한 내용은 Claude Code 설정 문서를 참조하세요.

구성 구조

{
  "permissions": {
    "allow": [
      "Bash(npm run lint)",
      "Bash(npm run test:*)",
      "Read(~/.zshrc)"
    ],
    "deny": [
      "Bash(curl:*)",
      "Read(./.env)",
      "Read(./secrets/**)",
      "WebFetch"
    ],
    "ask": [
      "Bash(git push:*)",
      "Write(./production/**)"
    ]
  }
}

규칙 구문

권한 규칙은 ToolName(pattern) 패턴을 따릅니다:
  • Bash 규칙: 접두사 매칭 사용 (정규식 아님). 예: Bash(npm:*)는 “npm”으로 시작하는 모든 명령과 일치
  • 파일 규칙: glob 패턴 지원. 예: Read(./src/**/*.ts)는 src의 TypeScript 파일과 일치
  • 도구 전용 규칙: 전체 도구를 제어하려면 괄호 생략. 예: WebFetch는 모든 웹 페치를 차단

SDK와 함께 사용

SDK에서는 아직 규칙을 프로그래밍적으로 설정할 수 없지만, SDK가 로드된 경로의 settings.json 파일에서 읽어집니다.

권한 평가 순서

  1. 거부 규칙이 먼저 확인됨 - 일치하면 도구 사용이 차단됨
  2. 허용 규칙이 다음에 확인됨 - 일치하면 도구 사용이 허용됨
  3. 요청 규칙이 확인됨 - 일치하면 사용자에게 프롬프트가 표시됨
  4. canUseTool 콜백이 나머지 경우에 대해 호출됨

Bash 명령 파싱

SDK는 명령 구조를 이해하는 통합된 bash 파서를 포함합니다:
  • 파이프, 리디렉션, 명령 치환을 처리함
  • rm -rf 또는 curl | sh와 같은 위험한 패턴을 인식함
  • 와일드카드 및 접두사 매칭을 지원함
bash 패턴이 작동하는 방식의 예:
  • Bash(git:*) - 모든 git 명령과 일치
  • Bash(npm run test) - 정확한 명령과 일치
  • Bash(npm run test:*) - npm run test:unit, test:integration 등과 일치

모범 사례

  1. 기본 모드로 시작 - 표준 권한 검사를 위해
  2. 권한 규칙 사용 - 정적 정책, 특히 bash 명령을 위해 (권한 설정 참조)
  3. 훅 사용 - 모든 도구 사용을 로그, 감사 또는 변환하기 위해 (훅 타입 참조)
  4. canUseTool 사용 - 다루어지지 않은 경우에 대한 동적 결정을 위해 (CanUseTool 타입 참조)
  5. 방어 계층화 - 중요한 애플리케이션을 위해 모드, 규칙, 훅, 콜백을 결합하여 사용