Architecture

Technical overview of youtube-music-cli’s architecture.

Overview

youtube-music-cli is built with:

Project Structure

youtube-music-cli/
β”œβ”€β”€ source/
β”‚   β”œβ”€β”€ cli.tsx              # CLI entry point
β”‚   β”œβ”€β”€ app.tsx              # App setup
β”‚   β”œβ”€β”€ main.tsx             # Root component with providers
β”‚   β”‚
β”œβ”€β”€ components/          # UI Components
β”‚   β”œβ”€β”€ layouts/         # Main view layouts
β”‚   β”œβ”€β”€ player/          # Player components
β”‚   β”œβ”€β”€ favorites/       # Favorites view
β”‚   β”œβ”€β”€ search/          # Search components
β”‚   β”œβ”€β”€ plugins/         # Plugin management UI
β”‚   β”‚   β”œβ”€β”€ settings/        # Settings UI
β”‚   β”‚   └── common/          # Shared components
β”‚   β”‚
β”‚   β”œβ”€β”€ services/            # Business logic
β”‚   β”‚   β”œβ”€β”€ player/          # Audio playback
β”‚   β”‚   β”œβ”€β”€ youtube-music/   # YouTube Music API
β”‚   β”‚   β”œβ”€β”€ plugin/          # Plugin system
β”‚   β”‚   β”œβ”€β”€ config/          # Configuration
β”‚   β”‚   └── logger/          # Logging
β”‚   β”‚
β”‚   β”œβ”€β”€ stores/              # State management
β”‚   β”‚   β”œβ”€β”€ player.store.tsx
β”‚   β”‚   β”œβ”€β”€ navigation.store.tsx
β”‚   β”‚   └── plugins.store.tsx
β”‚   β”‚
β”‚   β”œβ”€β”€ hooks/               # Custom React hooks
β”‚   β”œβ”€β”€ types/               # TypeScript definitions
β”‚   β”œβ”€β”€ contexts/            # React contexts
β”‚   β”œβ”€β”€ immersive/           # Immersive Windows TUI
β”‚   β”‚   β”œβ”€β”€ renderer/        # Frame buffer, braille canvas, ANSI codes
β”‚   β”‚   β”œβ”€β”€ visualizer/      # Audio collector, disco engine
β”‚   β”‚   β”œβ”€β”€ effects/         # Particle system, color extractor
β”‚   β”‚   β”œβ”€β”€ native/          # Console, tray, notifications, hotkeys
β”‚   β”‚   └── components/      # Immersive player component
β”‚   └── utils/               # Utilities
β”‚
β”œβ”€β”€ plugins/                 # Plugin submodule
β”œβ”€β”€ templates/               # Plugin templates
β”œβ”€β”€ docs/                    # Documentation
└── dist/                    # Compiled output

State Management

Uses React Context + useReducer pattern:

                    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                    β”‚   Providers     β”‚
                    β”‚                 β”‚
                    β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
                    β”‚ β”‚ThemeProviderβ”‚ β”‚
                    β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
                    β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
                    β”‚ β”‚PlayerProviderβ”‚ β”‚
                    β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
                    β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
                    β”‚ β”‚FavProvider  β”‚ β”‚
                    β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
                    β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
                    β”‚ β”‚NavProvider  β”‚ β”‚
                    β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
                    β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
                    β”‚ β”‚PluginsProviderβ”‚ β”‚
                    β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
                    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                            β”‚
                            β–Ό
                    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                    β”‚   MainLayout    β”‚
                    β”‚   (Router)      β”‚
                    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Player Store

Manages playback state:

Favorites Store

Manages favorite tracks:

Manages view navigation:

Plugins Store

Manages plugin state:

Service Layer

Services encapsulate external dependencies:

PlayerService

Wraps mpv/yt-dlp for audio playback.

const player = getPlayerService();
await player.play(track);
player.pause();
player.setVolume(80);

MusicService

Wraps YouTube Music API (Innertube).

const music = getMusicService();
const results = await music.search('query');
const suggestions = await music.getSuggestions(videoId);

FavoritesService

Wraps favorites persistence.

const favs = getFavoritesService();
await favs.saveFavorites(tracks);
const data = await favs.loadFavorites();

PluginRegistryService

Manages plugin lifecycle.

const registry = getPluginRegistryService();
await registry.loadAllPlugins();
await registry.enablePlugin('adblock');

Plugin System

Plugin Lifecycle

Install β†’ Load β†’ Init β†’ Enable β†’ (Running) β†’ Disable β†’ Destroy β†’ Uninstall

Plugin Context

Plugins receive a context object with APIs:

{
  player,      // Playback control
  navigation,  // View navigation
  config,      // Configuration storage
  logger,      // Logging
  filesystem,  // File operations
  audio,       // Audio stream hooks
  on/off/emit, // Event system
}

Event Flow

User Action β†’ Store Dispatch β†’ State Update β†’ Plugin Hook β†’ UI Re-render
                                    β”‚
                                    β–Ό
                            Plugin Event Emitted

Immersive Mode (Windows)

A fullscreen Windows-only TUI experience wired to the real player stack (PlayerService, YouTube Music API). It renders ANSI graphics directly to the terminal using an alternate screen buffer.

Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  cli.tsx --win32 / immersive-entry  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
               β”‚
               β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚       immersive-app.ts (bridge)     β”‚
β”‚  queue state + mpv IPC + search     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
               β”‚
       β”Œβ”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
       β–Ό               β–Ό          β–Ό          β–Ό
  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”
  β”‚Renderer β”‚   β”‚Visualizer β”‚ β”‚Effects β”‚ β”‚ Native β”‚
  β”‚         β”‚   β”‚           β”‚ β”‚        β”‚ β”‚        β”‚
  β”‚-FrameBufβ”‚   β”‚-HybridAud β”‚ β”‚-Particleβ”‚ β”‚-Tray  β”‚
  β”‚-Braille β”‚   β”‚-DiscoEng  β”‚ β”‚-ColorExβ”‚ β”‚-Hotkey β”‚
  β”‚-ANSI    β”‚   β”‚           β”‚ β”‚        β”‚ β”‚-DPI   β”‚
  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Components

Entry Points

# Development
bun run dev:win32

# From main CLI
youtube-music-cli --win32 --search "query"

# Production build
bun run build:win32
# Output: dist/ymc-win32.exe

# Build all (bun + node + win32 + web)
bun run build:all

Build

Uses bun build --compile --target bun-windows-x64 to produce a standalone Windows executable with the immersive bridge entry point.

Component Architecture

Layouts

Each view has a dedicated layout component:

Ink Primitives

Components use Ink’s Box and Text:

<Box flexDirection="column" padding={1}>
	<Text color="green">Now Playing</Text>
	<Text>{track.title}</Text>
</Box>

Data Flow

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Input   │───▢│  Store   │───▢│   UI     β”‚
β”‚(Keyboard)β”‚    β”‚(Reducer) β”‚    β”‚(React)   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                     β”‚
                     β–Ό
               β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
               β”‚ Services β”‚
               β”‚(Side FX) β”‚
               β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Build Process

  1. TypeScript Compilation (tsc)
  2. Output to dist/
  3. Entry: dist/source/cli.js
bun run build  # Runs format β†’ lint β†’ typecheck β†’ tsc

Testing

bun run test