DEV Community

김이더
김이더

Posted on

Claude Code 소스코드를 뜯어봤다

더 많은 글은 radarlog.kr에서.


Claude Code의 소스코드가 유출됐다. TypeScript 파일 1,884개, 총 31MB.

누군가 이미 Mintlify로 깔끔한 문서 사이트를 만들어서 공개했는데, 거기에 정리된 환경변수는 30개다. 소스코드에는 195개 있다. 문서화된 슬래시 커맨드는 20개 남짓이다. 소스코드에는 80개 이상 있다.

문서에 없는 나머지는 뭘까. 직접 뜯어봤다.

소스코드의 전체 구조

압축을 풀면 src/ 하나에 모든 게 들어 있다. 게임 프로젝트처럼 폴더 구조가 역할별로 깔끔하게 나뉘어 있다.

src/
├── tools/          (2.8MB) — 40개의 도구 정의
├── components/     (9.5MB) — Ink 기반 터미널 UI
├── commands/       (2.8MB) — 80+ 슬래시 커맨드
├── services/       (1.9MB) — API, MCP, 분석, 컴팩트
├── hooks/          (1.3MB) — React 훅 (터미널 UI용)
├── utils/          (6.7MB) — 유틸리티 모음
├── constants/      (122KB) — 시스템 프롬프트, 상수
├── coordinator/    (23KB)  — 코디네이터 모드
├── buddy/          (79KB)  — 가상 펫 시스템 (!?)
└── voice/          (6.5KB) — 음성 모드
Enter fullscreen mode Exit fullscreen mode

UE5 프로젝트의 Source/ 폴더를 보는 것 같다. 모듈 간 의존성이 깔끔하고, 각 도구가 독립적으로 분리되어 있다. tools/ 안에 40개 디렉토리가 각각 하나의 도구를 담당한다. 언리얼의 모듈 시스템이랑 느낌이 비슷하다.

런타임은 Bun이다. Node가 아니다. feature() 함수로 빌드 타임에 기능을 켜고 끄는 구조가 있는데, 이게 UE5의 WITH_EDITOR 같은 컴파일 플래그랑 정확히 같은 패턴이다.

const buddy = feature('BUDDY')
  ? require('./commands/buddy/index.js').default
  : null
Enter fullscreen mode Exit fullscreen mode

feature('BUDDY')가 빌드 타임에 false로 평가되면 해당 코드가 번들에서 통째로 빠진다. Dead code elimination. UE5에서 #if WITH_EDITOR로 에디터 전용 코드를 빼는 것과 같다.

문서에 없는 슬래시 커맨드들

공식 문서에 나오는 커맨드는 /help, /compact, /config, /mcp 정도다. 소스코드에서 발견한 커맨드는 훨씬 많다. 그중 실제로 쓸 수 있는 것들을 추려봤다.

/btw — 사이드 질문. 메인 대화를 끊지 않고 빠른 질문을 던진다. immediate: true로 설정되어 있어서 대화 맥락을 오염시키지 않는다. 작업 중에 "btw 이 함수 뭐하는 거야?" 같은 질문을 던지기에 딱이다.

const btw = {
  type: 'local-jsx',
  name: 'btw',
  description: 'Ask a quick side question without interrupting the main conversation',
  immediate: true,
  argumentHint: '<question>',
}
Enter fullscreen mode Exit fullscreen mode

/rewind — 코드 되돌리기. 대화와 코드를 이전 시점으로 되돌린다. alias가 /checkpoint다. Git의 특정 시점으로 돌아가는 게 아니라, Claude Code가 자체적으로 관리하는 체크포인트 시스템이다. 잘못된 방향으로 갈 때 "처음부터 다시"가 아니라 "여기서부터 다시"가 가능하다.

/compact — 컨텍스트 요약. 이건 문서에 나오지만, 인자를 받는다는 건 안 나온다. /compact 코드 변경사항 위주로 요약해줘처럼 요약 방향을 지정할 수 있다. 소스코드를 보면 customInstructions로 사용자 인자를 그대로 요약 프롬프트에 넘긴다.

/review — PR 코드 리뷰. gh CLI를 써서 PR diff를 가져온 다음 코드 리뷰를 해준다. PR 번호 없이 치면 열린 PR 목록을 보여준다.

const LOCAL_REVIEW_PROMPT = (args: string) => `
  You are an expert code reviewer. Follow these steps:
  1. If no PR number is provided, run \`gh pr list\`
  2. If provided, run \`gh pr view <number>\`
  3. Run \`gh pr diff <number>\` to get the diff
  4. Analyze the changes...
`
Enter fullscreen mode Exit fullscreen mode

/advisor — 보조 모델 설정. 메인 모델 외에 "어드바이저" 모델을 따로 붙일 수 있다. /advisor opus로 설정하면 메인 모델이 작업할 때 Opus가 조언을 한다. 해제는 /advisor unset.

/stickers — 스티커 주문. 진짜로 Claude Code 스티커를 주문하는 페이지(stickermule.com/claudecode)를 브라우저에서 연다. 이스터에그인데, 소스코드에 떡하니 있다.

/sandbox — 샌드박스 토글. Bash 명령을 격리된 환경에서 실행하는 샌드박스 모드를 제어한다. macOS에서 사용 가능하고, 자동 허용 모드와 결합하면 안전하게 "다 허용"을 할 수 있다.

/fast — 빠른 모드. 더 빠른 모델로 전환한다. Claude AI 구독자와 API 사용자만 쓸 수 있고, isFastModeEnabled()로 게이트된다.

/effort — 노력 수준 조절. low, medium, high, max, auto 5단계. 간단한 질문에는 low, 복잡한 리팩토링에는 max. API 비용을 직접 제어할 수 있다.

/stats — 사용 통계. Claude Code 사용 패턴과 활동 통계를 보여준다.

/passes — 친구 초대. 무료 1주일 이용권을 친구에게 공유하고, 자신은 추가 사용량을 받는 레퍼럴 시스템이다. checkCachedPassesEligibility()로 자격을 확인한다.

/mobile — 모바일 앱 QR. alias가 /ios, /android다. QR 코드를 터미널에 표시해서 모바일 앱 다운로드를 안내한다.

/chrome — 크롬 확장 설정. Claude in Chrome 베타 기능을 설정한다. Claude AI 구독자만 사용 가능.

195개 환경변수 — 숨겨진 설정 표면

Mintlify 분석에서 문서화한 환경변수는 약 30개다. 소스코드에서 grep으로 찾은 CLAUDE_CODE_ 접두어 환경변수는 195개다.

전부 나열하진 않겠지만, 실전에서 유용한 것들이 있다.

CLAUDE_CODE_AUTO_COMPACT_WINDOW — 자동 컴팩트가 트리거되는 컨텍스트 윈도우 비율을 조절한다. 기본값보다 일찍 또는 늦게 컴팩트가 돌도록 할 수 있다.

CLAUDE_CODE_DISABLE_MOUSE — 마우스 입력을 완전히 끈다. tmux 안에서 Claude Code를 쓸 때 마우스 이벤트가 충돌하는 경우에 유용하다.

CLAUDE_CODE_SCROLL_SPEED — 스크롤 속도 조절. 터미널 환경에 따라 스크롤이 너무 빠르거나 느릴 때.

CLAUDE_CODE_TMUX_PREFIX — tmux 프리픽스 키 충돌을 해결한다. tmux 안에서 Claude Code의 키바인딩이 먹히지 않을 때 이걸로 조정한다.

CLAUDE_CODE_DISABLE_FILE_CHECKPOINTING — 파일 체크포인팅을 끈다. /rewind에 쓰이는 체크포인트 시스템인데, 디스크 I/O가 부담될 때 끌 수 있다.

CLAUDE_CODE_COORDINATOR_MODE — 코디네이터 모드를 활성화한다. Claude가 직접 코드를 안 쓰고, 워커 에이전트를 지휘하는 오케스트레이터 역할만 한다. 이건 2편에서 자세히 다룬다.

CLAUDE_CODE_STREAMLINED_OUTPUT — 출력을 간소화한다. 도구 호출 과정 같은 중간 과정을 숨기고 결과만 보여준다.

CLAUDE_CODE_SYNTAX_HIGHLIGHT — 구문 강조를 제어한다. 터미널에서 색상이 깨질 때 끄면 된다.

CLAUDE_CODE_DISABLE_CRON — 크론 스케줄링을 끈다. Claude Code에 크론이 있다는 것 자체가 놀라운데, 이건 3편에서 다룬다.

# 실전 조합 예시 — tmux 안에서 가볍게 쓰기
export CLAUDE_CODE_DISABLE_MOUSE=1
export CLAUDE_CODE_STREAMLINED_OUTPUT=1
export DISABLE_AUTO_COMPACT=1
Enter fullscreen mode Exit fullscreen mode

환경변수 중에는 CLAUDE_CODE_UNDERCOVER처럼 Anthropic 내부용으로 보이는 것도 있다. 이건 3편에서 다룬다.

키바인딩 — 커스터마이징이 된다

Claude Code의 키바인딩이 전부 커스터마이징 가능하다는 건 거의 알려지지 않았다. 소스코드에 defaultBindings.ts가 있고, 사용자 오버라이드를 keybindings.json에서 읽는다.

기본 키바인딩 중 쓸만한 것들이 많다.

// 글로벌
'ctrl+t': 'app:toggleTodos',     // 투두 리스트 토글
'ctrl+o': 'app:toggleTranscript', // 대화 전문 보기
'ctrl+r': 'history:search',       // 히스토리 검색

// 채팅
'shift+tab': 'chat:cycleMode',    // 모드 전환 (plan/code)
'meta+p': 'chat:modelPicker',     // 모델 선택
'meta+o': 'chat:fastMode',        // 빠른 모드 토글
'meta+t': 'chat:thinkingToggle',  // 사고 과정 표시 토글
'ctrl+s': 'chat:stash',           // 입력 스태시
'ctrl+g': 'chat:externalEditor',  // 외부 에디터로 열기

// 작업 중
'ctrl+b': 'task:background',      // 작업을 백그라운드로
Enter fullscreen mode Exit fullscreen mode

ctrl+b로 현재 실행 중인 작업을 백그라운드로 보낼 수 있다. 에이전트가 긴 작업을 하고 있을 때, 끝날 때까지 기다리지 않고 다른 입력을 할 수 있다는 뜻이다. tmux에서는 ctrl+b를 두 번 눌러야 한다(tmux prefix와 겹치므로).

ctrl+s는 스태시다. git stash처럼, 지금 입력 중인 내용을 임시 저장하고 나중에 꺼낼 수 있다.

shift+up을 치면 메시지 액션 모드로 들어간다. 이전 메시지를 선택해서 복사하거나 다시 보낼 수 있다.

Windows에서는 VT 모드 지원 여부에 따라 shift+tab 대신 meta+m이 기본으로 바뀐다. 소스코드에서 Bun과 Node의 버전별 VT 모드 지원을 직접 체크하고 있다.

const SUPPORTS_TERMINAL_VT_MODE =
  getPlatform() !== 'windows' ||
  (isRunningWithBun()
    ? satisfies(process.versions.bun, '>=1.2.23')
    : satisfies(process.versions.node, '>=22.17.0 <23.0.0 || >=24.2.0'))
Enter fullscreen mode Exit fullscreen mode

이런 수준의 플랫폼별 호환성 처리는 UE5에서 iOS/Android 크로스플랫폼 입력 처리할 때 보던 패턴과 똑같다.

macOS에서 잠들지 않는 이유

Claude Code가 작업 중일 때 맥이 잠들지 않는다. 운이 좋아서가 아니다. 소스코드에 caffeinate를 직접 호출하는 코드가 있다.

const CAFFEINATE_TIMEOUT_SECONDS = 300 // 5분
const RESTART_INTERVAL_MS = 4 * 60 * 1000 // 4분마다 재시작

// refCount 기반 — 작업이 0개가 되면 caffeinate를 끈다
export function startPreventSleep(): void {
  refCount++
  if (refCount === 1) {
    spawnCaffeinate()
  }
}
Enter fullscreen mode Exit fullscreen mode

레퍼런스 카운팅 방식이다. 작업이 시작되면 카운트가 올라가고, 끝나면 내려간다. 카운트가 0이 되면 caffeinate 프로세스를 죽인다. 5분 타임아웃을 걸고 4분마다 재시작하는 이유는, Node 프로세스가 SIGKILL로 죽으면 cleanup 핸들러가 안 돌기 때문이다. orphan caffeinate가 5분 뒤 자동으로 죽는다.

게임 서버에서 keepalive 체크하는 것과 같은 패턴이다. 부모가 죽어도 자식이 무한히 살아남지 않도록, 자체 타임아웃을 건다.

다음 편 — 시스템 프롬프트와 코디네이터 모드

1편에서는 표면에 드러나는 숨겨진 기능들을 다뤘다. 2편에서는 더 깊이 들어간다. Claude Code의 시스템 프롬프트가 어떻게 조립되는지, 프롬프트 캐시를 깨지 않기 위해 어떤 구조를 쓰는지, 코디네이터 모드에서 워커 에이전트를 어떻게 지휘하는지. "AI가 AI를 관리하는" 아키텍처의 내부 구조다.

"Mintlify 문서에는 환경변수가 30개다. 소스코드에는 195개 있다."

Top comments (0)