Architecture
Technical overview of youtube-music-cliβs architecture.
Overview
youtube-music-cli is built with:
- React + Ink - Terminal UI framework
- TypeScript - Type-safe development
- Bun - Fast JavaScript runtime
- mpv + yt-dlp - Audio playback
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
β β βββ 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
β βββ utils/ # Utilities
β
βββ plugins/ # Plugin submodule
βββ templates/ # Plugin templates
βββ docs/ # Documentation
βββ dist/ # Compiled output
State Management
Uses React Context + useReducer pattern:
βββββββββββββββββββ
β Providers β
β β
β βββββββββββββββ β
β βThemeProviderβ β
β βββββββββββββββ β
β βββββββββββββββ β
β βPlayerProviderβ β
β βββββββββββββββ β
β βββββββββββββββ β
β βNavProvider β β
β βββββββββββββββ β
β βββββββββββββββ β
β βPluginsProviderβ β
β βββββββββββββββ β
βββββββββββββββββββ
β
βΌ
βββββββββββββββββββ
β MainLayout β
β (Router) β
βββββββββββββββββββ
Player Store
Manages playback state:
- Current track
- Queue
- Playback status
- Volume, shuffle, repeat
Navigation Store
Manages view navigation:
- Current view
- View history
- Navigation actions
Plugins Store
Manages plugin state:
- Installed plugins
- Plugin status (enabled/disabled)
- Installation operations
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);
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
Component Architecture
Layouts
Each view has a dedicated layout component:
PlayerLayout- Main player viewSearchLayout- Search interfacePluginsLayout- Plugin managementConfigLayout- Settings
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
- TypeScript Compilation (
tsc) - Output to
dist/ - Entry:
dist/source/cli.js
bun run build # Runs format β lint β typecheck β tsc
Testing
- AVA - Test runner
- ink-testing-library - Component testing
bun run test