import * as vscode from 'vscode'; import { registerSlashCommand, chunk, type Webview } from '../datacollect/slashRouter'; /** * /claude — 로컬에 설치된 Claude Code CLI 를 VS Code 통합 터미널에서 실행. * * 배경 (v2.2.303): 벤치마킹→개발 파이프라인의 마지막 구간. 로컬 소형 모델은 * 분석·명세(핸드오프 문서)까지 담당하고, 실제 코드 생성은 클라우드 모델에 * 위임한다. Anthropic 구독(Pro/Max) 인증은 API 키가 아니라 Claude Code 로그인 * 방식이므로, Astra 가 API 를 직접 호출하는 대신 **사용자가 이미 로그인해 둔 * `claude` CLI 를 실행**한다 — 추가 과금 없이 구독 한도 안에서 동작. * * 설계 (bridgeLauncher 의 터미널 패턴 재사용): * - 통합 터미널("Claude Code (Astra)")에서 실행 → 셸/OS 차이를 VS Code 가 흡수, * Claude Code 의 권한 승인·진행 상황을 사용자가 눈으로 보며 제어. * - cwd = 첫 워크스페이스 폴더 (Claude Code 가 그 프로젝트 컨텍스트로 동작). * - 지시문은 첫 인자로 전달 — 따옴표는 셸 호환을 위해 정규화. */ const TERMINAL_NAME = 'Claude Code (Astra)'; /** 셸(zsh/bash/PowerShell) 공통으로 안전한 한 줄 인자로 정규화 (순수 — 테스트 대상). */ export function buildClaudeCommand(instruction: string): string { const t = (instruction || '').trim(); if (!t) return 'claude'; // 큰따옴표로 감싸므로 내부의 "는 ', POSIX 확장 문자와 PowerShell 백틱은 공백으로 완화. // 지시문은 터미널에서 사용자가 이어서 수정할 수 있으니 완벽 이스케이프보다 안전 우선. const safe = t.replace(/"/g, "'").replace(/[`$\\]/g, ' ').replace(/\s+/g, ' ').trim(); return `claude "${safe}"`; } async function runClaude(arg: string, view: Webview | undefined): Promise { const instruction = (arg || '').trim(); const ws = vscode.workspace.workspaceFolders?.find(f => f.uri.scheme === 'file'); const cwd = ws?.uri.fsPath; // 기존 우리 터미널이 있으면 재사용하지 않고 정리 후 새로 연다 (죽은 셸 방지 — bridgeLauncher 동일). vscode.window.terminals.find(t => t.name === TERMINAL_NAME)?.dispose(); const terminal = vscode.window.createTerminal({ name: TERMINAL_NAME, cwd }); terminal.show(true); terminal.sendText(buildClaudeCommand(instruction)); chunk(view, [ `🚀 **Claude Code 실행** — "${TERMINAL_NAME}" 터미널에서 진행됩니다.`, instruction ? `- 전달한 지시: ${instruction.slice(0, 200)}${instruction.length > 200 ? '…' : ''}` : '- 지시 없이 대화형으로 시작했습니다.', cwd ? `- 작업 폴더: \`${cwd}\`` : '- ⚠️ 열린 워크스페이스가 없어 홈 폴더에서 시작합니다.', '- 파일 수정·명령 실행 승인은 터미널에서 직접 하시면 됩니다 (구독 인증 그대로 사용).', '', '💡 `command not found: claude` 가 뜨면: 터미널에서 `npm install -g @anthropic-ai/claude-code` 설치 후 `claude` 를 실행해 로그인하세요.', '', ].join('\n')); return true; } registerSlashCommand({ name: '/claude', description: 'Claude Code(클라우드·구독 인증)를 터미널로 실행 — 핸드오프 문서 기반 개발 위임. 예: /claude <파일경로> 읽고 명세대로 개발해줘', handler: runClaude, });