Skip to content

Latest commit

 

History

History
134 lines (104 loc) · 6.01 KB

File metadata and controls

134 lines (104 loc) · 6.01 KB

CLAUDE.md — Strudel Console

프로젝트 개요

Strudel 기반 TUI 음악 작곡 도구 + MCP 서버. 터미널에서 라이브 코딩하거나, Claude Code 같은 AI 에이전트를 통해 음악을 만들 수 있다.

빌드 & 실행

npm run build          # tsc → dist/
npm run dev            # tsc --watch
npm start              # TUI 모드 (기본)
npm run tui            # TUI 모드
npm run mcp            # MCP 서버 (stdio)
npm run test:sound     # 오디오 테스트

모든 실행 커맨드에 --experimental-specifier-resolution=node 플래그 필요.

프로젝트 구조

src/
├── cli.ts                    # 진입점: tui(기본) / serve / mcp 서브커맨드 라우팅
├── engine/                   # 오디오 엔진 (순수 로직, UI 무관)
│   ├── audio.ts              # node-web-audio-api → globalThis 폴리필 (반드시 먼저 import)
│   ├── player.ts             # webaudioRepl 래퍼 — evaluate/start/stop/getVisualState
│   ├── tracks.ts             # 멀티트랙 상태관리 — stack() 결합, 뮤트/솔로/게인
│   ├── mixer.ts              # 마스터 게인 + 이펙트 프리셋 (clean/lofi/ambient/dark/bright/tape)
│   ├── samples.ts            # 샘플 로드 — GitHub/로컬/URL, fetch 폴리필
│   ├── patterns.ts           # 패턴 저장/불러오기 — ~/.strudel-console/patterns/*.strudel
│   ├── render.ts             # WAV 렌더링 — OfflineAudioContext, 오실레이터 직접 스케줄링
│   ├── theory.ts             # 음악 이론 분석 + 장르 프리셋 6종
│   └── index.ts              # 배럴 export (모든 엔진 API)
├── mcp/
│   └── server.ts             # MCP 서버 — 20개 도구 + 2개 리소스
├── tui/
│   ├── App.tsx               # 루트 컴포넌트 — 키보드 라우팅, 모드 관리
│   ├── highlight.ts          # Strudel 구문 강조 토크나이저
│   ├── components/
│   │   ├── Editor.tsx         # 구문 강조 에디터 + 인라인 에러
│   │   ├── Visualizer.tsx     # 피아노 롤 + Braille 웨이브폼 + 사이클 표시
│   │   ├── TrackList.tsx      # 트랙 목록 (M/S/게인 표시)
│   │   ├── StatusBar.tsx      # BPM, CPS, 사이클 위치
│   │   ├── HelpBar.tsx        # 단축키 안내
│   │   └── Prompt.tsx         # 인라인 입력 프롬프트 (저장/이름변경)
│   └── hooks/
│       ├── usePlayer.ts       # 엔진 상태 폴링 + 트랙 조작
│       ├── useEditor.ts       # 에디터 상태 (줄, 커서)
│       └── useHistory.ts      # 명령어 히스토리
└── types/
    └── strudel.d.ts           # @strudel/* 타입 스텁

아키텍처

핵심 규칙

  1. audio.ts를 반드시 먼저 import — superdough가 globalThis.AudioContext를 사용하므로 player.ts보다 먼저 폴리필해야 함
  2. 모듈 레벨 상태repl, tracks[], masterGainValue 등 엔진 상태는 모듈 스코프에 저장
  3. 콜백 기반 재컴파일setRecompileCallback()으로 tracks → player 연결. 트랙 변경 시 자동으로 evaluate() 호출
  4. 100ms 폴링 — TUI의 usePlayer가 100ms 간격으로 엔진 상태를 폴링해서 Visualizer 업데이트

데이터 흐름

[TUI 입력 / MCP 호출]
    ↓
tracks.ts — 트랙 코드 업데이트
    ↓
compileTracksCode() — solo/mute 반영, stack() 결합
    ↓
applyMasterGain() — 마스터 게인 적용
    ↓
player.evaluate(compiledCode) — REPL에서 평가
    ↓
superdough → node-web-audio-api → 소리 출력

MCP vs TUI

  • MCP (mcp/server.ts): stdio 트랜스포트, 도구마다 ensureInitialized() 호출, 상태 없는 요청/응답
  • TUI (tui/App.tsx): Ink/React 컴포넌트, Tab 프리픽스 단축키, 폴링 기반 렌더링

둘 다 같은 engine/ 모듈을 공유하지만 동시에 실행되지는 않음.

코딩 컨벤션

임포트

  • ESM .js 확장자 필수: import "./audio.js", from "../engine/index.js"
  • 타입 전용 임포트: import type { Track } from "./tracks.js"
  • 동적 임포트로 지연 로딩: const { evaluateToPattern } = await import("../engine/index.js")

네이밍

  • 파일: camelCase (usePlayer.ts) / PascalCase 컴포넌트 (Editor.tsx)
  • 함수: camelCase (initPlayer, compileTracksCode)
  • 타입/인터페이스: PascalCase (Track, TracksSnapshot, PlayerState)
  • 컴포넌트: PascalCase (Editor, Visualizer, TrackList)

에러 처리

  • MCP 도구: try-catch → { content: [...], isError: true } 반환
  • TUI: 훅에서 catch → 에디터 하단에 인라인 에러 표시
  • 엔진: 초기화 안 됐으면 !repl 체크 후 early throw

상태 관리

  • 엔진: 모듈 스코프 변수 (싱글톤 패턴)
  • TUI: React hooks (useState, useCallback, useRef)
  • 트랙 ID: t1, t2, ... 순차 생성

주의 사항

  • @strudel v1.1.0 고정 — 1.2.x는 @kabelsalat ESM 호환 문제 있음
  • superdough initAudio()typeof window === 'undefined'이면 early return하므로 Node.js에서는 수동 ac.resume() 필요
  • WAV 렌더링 — superdough 우회, OfflineAudioContext에 오실레이터 직접 스케줄링. 퍼커시브 사운드는 시뮬레이션 (bd=사인 피치다운, sd=트라이앵글, hh=고주파 사각파)
  • 샘플 fetchfile:// URL 지원을 위해 samples.ts에서 fetch 패치. 실제 WAV/MP3는 재생 시 lazy fetch (superdough 캐시)
  • 테스트 프레임워크 없음test-sound.ts, test-raw-audio.ts로 수동 검증

데이터 디렉토리

경로 용도
~/.strudel-console/patterns/ 저장된 패턴 (.strudel JSON)
~/.strudel-console/renders/ 렌더링된 WAV 파일

유용한 참조

  • Strudel 문서: https://strudel.cc
  • MCP 스펙: README.md의 "MCP 서버 스펙" 섹션
  • 음악 이론 가이드: engine/theory.ts 하단 MUSIC_THEORY_GUIDE