/something은 모두 커맨드 — 3가지 실행 전략, 등록 파이프라인, 가용성 게이팅.
사용자가 /로 시작하는 입력을 하면 커맨드 시스템이 활성화됩니다. Claude Code의 커맨드 시스템은 단순한 디스패치 테이블이 아닙니다 — 3가지 실행 전략, 동적 등록, 가용성 게이팅, 캐시 관리를 포함하는 완전한 프레임워크입니다.
commands/registry.ts → commands/base.ts → commands/executor.ts → commands/availability.ts
커맨드 시스템의 핵심 구성요소:
local, local-jsx, promptlocal 커맨드는 순수 TypeScript 함수로 실행됩니다. REPL 상태를 직접 변경하거나, 설정을 수정하거나, 즉각적인 부수 효과를 발생시킵니다. AI 모델 호출이 필요 없는 작업에 사용됩니다.
// local 커맨드: 즉시 실행, 모델 호출 없음
const clearCommand: LocalCommand = {
type: 'local',
name: 'clear',
description: '대화 기록을 초기화합니다',
execute(context) {
context.clearConversation()
return { success: true }
}
}
local-jsx 커맨드는 React 컴포넌트를 반환합니다. 대화상자, 설정 화면, 인터랙티브 위자드 등 UI가 필요한 커맨드에 사용됩니다. 반환된 JSX는 Ink 렌더링 엔진을 통해 터미널에 표시됩니다.
// local-jsx 커맨드: React 컴포넌트 반환
const settingsCommand: LocalJsxCommand = {
type: 'local-jsx',
name: 'settings',
description: '설정 화면을 표시합니다',
render(context) {
return <SettingsDialog onClose={context.dismiss} />
}
}
prompt 커맨드는 사용자 입력을 AI 모델에 전달하기 전에 프롬프트를 변환합니다. 사용자가 입력한 내용에 시스템 프롬프트를 추가하거나, 특정 컨텍스트를 주입하거나, 모델의 동작을 조정합니다.
// prompt 커맨드: 사용자 입력을 프롬프트로 변환
const reviewCommand: PromptCommand = {
type: 'prompt',
name: 'review',
description: '코드 리뷰를 수행합니다',
buildPrompt(userInput, context) {
return `다음 코드를 리뷰해주세요:\n${context.selectedCode}\n\n사용자 요청: ${userInput}`
}
}
모든 커맨드는 CommandBase 인터페이스를 구현해야 합니다. 이 계약은 커맨드의 정체성, 실행 방식, 가용성 조건을 정의합니다.
interface CommandBase {
name: string // 고유 식별자 (/name으로 호출)
type: CommandType // 'local' | 'local-jsx' | 'prompt'
description: string // 사용자에게 표시되는 설명
aliases: string[] // 대체 이름 목록
isAvailable: AvailFn // 현재 컨텍스트에서 사용 가능 여부
isHidden: boolean // 자동완성에서 숨길지 여부
argDescription: string // 인수 설명
userFacingName: string // UI에 표시되는 이름
category: string // 그룹화 카테고리
requiredFeatures: Feature[] // 필요한 기능 플래그
priority: number // 자동완성 정렬 우선순위
}
isAvailable은 런타임 조건을 체크합니다 — 예를 들어 현재 대화에 코드가 선택되어 있는지, 특정 모드가 활성화되어 있는지. requiredFeatures는 빌드 타임 기능 플래그입니다 — 특정 기능이 빌드에 포함되지 않으면 커맨드 자체가 등록되지 않습니다. 이 이중 게이팅은 커맨드가 사용 불가능할 때 명확한 이유를 제공합니다.
빌드 타임에 알려진 커맨드들이 정적으로 등록됩니다. commands/ 디렉토리의 각 파일이 하나의 커맨드를 export하며, 레지스트리에 자동으로 수집됩니다.
런타임에 추가되는 커맨드입니다. 프로젝트의 .claude/commands/ 디렉토리에서 커스텀 커맨드를 로드하거나, MCP 서버에서 제공하는 커맨드를 등록합니다. 동적 커맨드는 정적 커맨드와 동일한 CommandBase 계약을 따릅니다.
등록된 모든 커맨드에 대해 isAvailable()과 requiredFeatures를 체크하여 현재 컨텍스트에서 사용 가능한 커맨드만 남깁니다.
// 등록 파이프라인 흐름
function getAvailableCommands(context: CommandContext): Command[] {
const staticCmds = getStaticCommands()
const dynamicCmds = getDynamicCommands(context.projectRoot)
const allCmds = [...staticCmds, ...dynamicCmds]
return allCmds
.filter(cmd => cmd.requiredFeatures.every(f => feature(f)))
.filter(cmd => cmd.isAvailable(context))
.sort((a, b) => b.priority - a.priority)
}
사용자가 /를 입력하면 REPL은 일반 텍스트 모드에서 커맨드 모드로 전환됩니다. 자동완성이 활성화되고, 사용 가능한 커맨드 목록이 표시됩니다.
// REPL 입력 처리 — 커맨드 디스패치
function handleInput(input: string): void {
if (input.startsWith('/')) {
const [name, ...args] = input.slice(1).split(' ')
const cmd = registry.resolve(name) // 이름 + 별칭으로 조회
if (!cmd) { showUnknownCommand(name); return }
switch (cmd.type) {
case 'local': cmd.execute(context); break
case 'local-jsx': mountDialog(cmd.render(context)); break
case 'prompt': sendToModel(cmd.buildPrompt(args, context)); break
}
}
}
동적 커맨드의 로드 결과는 캐시됩니다. 프로젝트 루트가 변경되거나 .claude/commands/ 디렉토리의 파일이 변경되면 캐시가 무효화됩니다. 이를 통해 매 입력마다 파일시스템을 읽지 않으면서도 최신 커맨드 목록을 유지합니다.
브릿지 모드에서는 커맨드가 원격 프로세스로 전달됩니다. local과 local-jsx 커맨드는 로컬에서 실행되지만, prompt 커맨드는 원격 세션의 모델에 전달됩니다. 원격 모드에서는 일부 로컬 커맨드가 비활성화됩니다.
동적 커맨드의 이름이 정적 커맨드와 충돌하면 정적 커맨드가 우선합니다. 사용자는 이름 충돌을 인지하지 못할 수 있으므로, 커스텀 커맨드에는 프로젝트별 접두사를 사용하는 것이 좋습니다.
local(즉시 실행), local-jsx(React UI 반환), prompt(모델 프롬프트 변환)CommandBase는 11개 필드의 계약으로, 모든 커맨드가 일관된 인터페이스를 제공합니다isAvailable)과 기능 게이팅(requiredFeatures)이 이중으로 커맨드 접근을 제어합니다prompt 커맨드는 원격으로, local/local-jsx는 로컬에서 실행됩니다Q1. local-jsx 커맨드가 local 커맨드와 다른 점은 무엇인가요?
local-jsx 커맨드는 render() 메서드를 통해 React 컴포넌트를 반환합니다. 반환된 JSX는 Ink 렌더링 엔진을 통해 터미널에 대화상자나 설정 화면으로 표시됩니다. local 커맨드는 UI 없이 즉시 실행됩니다.Q2. 동적 커맨드와 정적 커맨드의 이름이 충돌하면 어떻게 되나요?
Q3. prompt 커맨드의 buildPrompt()는 무엇을 하나요?
buildPrompt()는 사용자가 입력한 인수와 현재 컨텍스트(선택된 코드, 파일 경로 등)를 결합하여 AI 모델에 전송할 완성된 프롬프트를 생성합니다. 이를 통해 특정 작업에 최적화된 프롬프트를 자동으로 구성할 수 있습니다.Q4. requiredFeatures와 isAvailable의 차이는 무엇인가요?
requiredFeatures는 빌드 타임에 특정 기능이 포함되어 있는지 확인합니다. 기능이 빌드에서 제외되면 커맨드 자체가 등록되지 않습니다. isAvailable은 런타임에 현재 대화 상태, 모드, 선택 영역 등을 체크하여 커맨드의 일시적 사용 가능 여부를 결정합니다.Q5. 브릿지 모드에서 커맨드 실행은 어떻게 달라지나요?
local과 local-jsx 커맨드는 UI 관련이므로 로컬에서 실행됩니다. prompt 커맨드는 AI 모델 호출이 필요하므로 원격 세션으로 전달됩니다. 이 분리를 통해 로컬 UI 응답성을 유지하면서 원격 모델과 통신합니다.