@involvex/youtube-music-cli 0.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (136) hide show
  1. package/README.md +352 -0
  2. package/dist/eslint.config.d.ts +2 -0
  3. package/dist/eslint.config.js +55 -0
  4. package/dist/source/app.d.ts +4 -0
  5. package/dist/source/app.js +17 -0
  6. package/dist/source/cli.d.ts +2 -0
  7. package/dist/source/cli.js +241 -0
  8. package/dist/source/components/common/ErrorBoundary.d.ts +15 -0
  9. package/dist/source/components/common/ErrorBoundary.js +22 -0
  10. package/dist/source/components/common/Help.d.ts +1 -0
  11. package/dist/source/components/common/Help.js +10 -0
  12. package/dist/source/components/common/ShortcutsBar.d.ts +1 -0
  13. package/dist/source/components/common/ShortcutsBar.js +33 -0
  14. package/dist/source/components/config/ConfigLayout.d.ts +1 -0
  15. package/dist/source/components/config/ConfigLayout.js +84 -0
  16. package/dist/source/components/layouts/MainLayout.d.ts +4 -0
  17. package/dist/source/components/layouts/MainLayout.js +83 -0
  18. package/dist/source/components/layouts/PlayerLayout.d.ts +1 -0
  19. package/dist/source/components/layouts/PlayerLayout.js +10 -0
  20. package/dist/source/components/layouts/PluginsLayout.d.ts +1 -0
  21. package/dist/source/components/layouts/PluginsLayout.js +77 -0
  22. package/dist/source/components/layouts/SearchLayout.d.ts +4 -0
  23. package/dist/source/components/layouts/SearchLayout.js +81 -0
  24. package/dist/source/components/player/NowPlaying.d.ts +1 -0
  25. package/dist/source/components/player/NowPlaying.js +21 -0
  26. package/dist/source/components/player/PlayerControls.d.ts +1 -0
  27. package/dist/source/components/player/PlayerControls.js +41 -0
  28. package/dist/source/components/player/ProgressBar.d.ts +1 -0
  29. package/dist/source/components/player/ProgressBar.js +18 -0
  30. package/dist/source/components/player/QueueList.d.ts +4 -0
  31. package/dist/source/components/player/QueueList.js +30 -0
  32. package/dist/source/components/player/Suggestions.d.ts +1 -0
  33. package/dist/source/components/player/Suggestions.js +47 -0
  34. package/dist/source/components/playlist/PlaylistList.d.ts +1 -0
  35. package/dist/source/components/playlist/PlaylistList.js +11 -0
  36. package/dist/source/components/plugins/PluginInstallDialog.d.ts +5 -0
  37. package/dist/source/components/plugins/PluginInstallDialog.js +41 -0
  38. package/dist/source/components/plugins/PluginsAvailable.d.ts +5 -0
  39. package/dist/source/components/plugins/PluginsAvailable.js +55 -0
  40. package/dist/source/components/plugins/PluginsList.d.ts +8 -0
  41. package/dist/source/components/plugins/PluginsList.js +18 -0
  42. package/dist/source/components/search/SearchBar.d.ts +8 -0
  43. package/dist/source/components/search/SearchBar.js +50 -0
  44. package/dist/source/components/search/SearchResults.d.ts +10 -0
  45. package/dist/source/components/search/SearchResults.js +111 -0
  46. package/dist/source/components/settings/Settings.d.ts +1 -0
  47. package/dist/source/components/settings/Settings.js +42 -0
  48. package/dist/source/components/theme/ThemeSwitcher.d.ts +1 -0
  49. package/dist/source/components/theme/ThemeSwitcher.js +11 -0
  50. package/dist/source/config/themes.config.d.ts +3 -0
  51. package/dist/source/config/themes.config.js +63 -0
  52. package/dist/source/contexts/theme.context.d.ts +13 -0
  53. package/dist/source/contexts/theme.context.js +29 -0
  54. package/dist/source/hooks/useKeyboard.d.ts +10 -0
  55. package/dist/source/hooks/useKeyboard.js +104 -0
  56. package/dist/source/hooks/useNavigation.d.ts +1 -0
  57. package/dist/source/hooks/useNavigation.js +5 -0
  58. package/dist/source/hooks/usePlayer.d.ts +23 -0
  59. package/dist/source/hooks/usePlayer.js +35 -0
  60. package/dist/source/hooks/usePlaylist.d.ts +8 -0
  61. package/dist/source/hooks/usePlaylist.js +50 -0
  62. package/dist/source/hooks/useSearch.d.ts +8 -0
  63. package/dist/source/hooks/useSearch.js +76 -0
  64. package/dist/source/hooks/useTerminalSize.d.ts +4 -0
  65. package/dist/source/hooks/useTerminalSize.js +24 -0
  66. package/dist/source/hooks/useTheme.d.ts +6 -0
  67. package/dist/source/hooks/useTheme.js +5 -0
  68. package/dist/source/hooks/useYouTubeMusic.d.ts +11 -0
  69. package/dist/source/hooks/useYouTubeMusic.js +112 -0
  70. package/dist/source/main.d.ts +4 -0
  71. package/dist/source/main.js +69 -0
  72. package/dist/source/services/config/config.service.d.ts +26 -0
  73. package/dist/source/services/config/config.service.js +125 -0
  74. package/dist/source/services/logger/logger.service.d.ts +10 -0
  75. package/dist/source/services/logger/logger.service.js +52 -0
  76. package/dist/source/services/player/player.service.d.ts +58 -0
  77. package/dist/source/services/player/player.service.js +349 -0
  78. package/dist/source/services/player-state/player-state.service.d.ts +24 -0
  79. package/dist/source/services/player-state/player-state.service.js +122 -0
  80. package/dist/source/services/plugin/plugin-audio-api.d.ts +17 -0
  81. package/dist/source/services/plugin/plugin-audio-api.js +36 -0
  82. package/dist/source/services/plugin/plugin-context.d.ts +5 -0
  83. package/dist/source/services/plugin/plugin-context.js +256 -0
  84. package/dist/source/services/plugin/plugin-hooks.service.d.ts +62 -0
  85. package/dist/source/services/plugin/plugin-hooks.service.js +135 -0
  86. package/dist/source/services/plugin/plugin-installer.service.d.ts +27 -0
  87. package/dist/source/services/plugin/plugin-installer.service.js +247 -0
  88. package/dist/source/services/plugin/plugin-loader.service.d.ts +33 -0
  89. package/dist/source/services/plugin/plugin-loader.service.js +161 -0
  90. package/dist/source/services/plugin/plugin-permissions.service.d.ts +72 -0
  91. package/dist/source/services/plugin/plugin-permissions.service.js +194 -0
  92. package/dist/source/services/plugin/plugin-registry.service.d.ts +76 -0
  93. package/dist/source/services/plugin/plugin-registry.service.js +215 -0
  94. package/dist/source/services/plugin/plugin-ui-api.d.ts +25 -0
  95. package/dist/source/services/plugin/plugin-ui-api.js +46 -0
  96. package/dist/source/services/plugin/plugin-updater.service.d.ts +23 -0
  97. package/dist/source/services/plugin/plugin-updater.service.js +206 -0
  98. package/dist/source/services/youtube-music/api.d.ts +13 -0
  99. package/dist/source/services/youtube-music/api.js +371 -0
  100. package/dist/source/services/youtube-music/search.service.d.ts +11 -0
  101. package/dist/source/services/youtube-music/search.service.js +38 -0
  102. package/dist/source/stores/navigation.store.d.ts +10 -0
  103. package/dist/source/stores/navigation.store.js +67 -0
  104. package/dist/source/stores/player.store.d.ts +28 -0
  105. package/dist/source/stores/player.store.js +458 -0
  106. package/dist/source/stores/plugins.store.d.ts +46 -0
  107. package/dist/source/stores/plugins.store.js +177 -0
  108. package/dist/source/types/actions.d.ts +119 -0
  109. package/dist/source/types/actions.js +1 -0
  110. package/dist/source/types/cli.types.d.ts +14 -0
  111. package/dist/source/types/cli.types.js +1 -0
  112. package/dist/source/types/config.types.d.ts +19 -0
  113. package/dist/source/types/config.types.js +1 -0
  114. package/dist/source/types/keyboard.types.d.ts +5 -0
  115. package/dist/source/types/keyboard.types.js +1 -0
  116. package/dist/source/types/navigation.types.d.ts +14 -0
  117. package/dist/source/types/navigation.types.js +1 -0
  118. package/dist/source/types/player.types.d.ts +16 -0
  119. package/dist/source/types/player.types.js +1 -0
  120. package/dist/source/types/playlist.types.d.ts +12 -0
  121. package/dist/source/types/playlist.types.js +1 -0
  122. package/dist/source/types/plugin.types.d.ts +239 -0
  123. package/dist/source/types/plugin.types.js +1 -0
  124. package/dist/source/types/theme.types.d.ts +18 -0
  125. package/dist/source/types/theme.types.js +1 -0
  126. package/dist/source/types/youtube-music.types.d.ts +35 -0
  127. package/dist/source/types/youtube-music.types.js +1 -0
  128. package/dist/source/types/youtubei.types.d.ts +60 -0
  129. package/dist/source/types/youtubei.types.js +3 -0
  130. package/dist/source/utils/constants.d.ts +65 -0
  131. package/dist/source/utils/constants.js +82 -0
  132. package/dist/source/utils/format.d.ts +3 -0
  133. package/dist/source/utils/format.js +24 -0
  134. package/dist/test.d.ts +1 -0
  135. package/dist/test.js +13 -0
  136. package/package.json +100 -0
package/README.md ADDED
@@ -0,0 +1,352 @@
1
+ <div align="center">
2
+
3
+ # 🎵 youtube-music-cli
4
+
5
+ A powerful Terminal User Interface (TUI) music player for YouTube Music
6
+
7
+ [![npm version](https://img.shields.io/npm/v/@involvex/youtube-music-cli.svg)](https://www.npmjs.com/package/@involvex/youtube-music-cli)
8
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
9
+
10
+ [Features](#features) • [Installation](#installation) • [Usage](#usage) • [Plugins](#plugins) • [Documentation](https://involvex.github.io/youtube-music-cli)
11
+
12
+ </div>
13
+
14
+ ---
15
+
16
+ ## Features
17
+
18
+ - 🎨 **Beautiful TUI** - Rich terminal interface built with React and Ink
19
+ - 🔍 **Search** - Find songs, albums, artists, and playlists
20
+ - 📋 **Queue Management** - Build and manage your playback queue
21
+ - 🔀 **Shuffle & Repeat** - Multiple playback modes
22
+ - 🎚️ **Volume Control** - Fine-grained volume adjustment
23
+ - 💡 **Smart Suggestions** - Discover related tracks
24
+ - 🎨 **Themes** - Dark, Light, Midnight, Matrix themes
25
+ - 🔌 **Plugin System** - Extend functionality with plugins
26
+ - ⌨️ **Keyboard-Driven** - Efficient vim-style navigation
27
+ - 🖥️ **Headless Mode** - Run without TUI for scripting
28
+
29
+ ## Prerequisites
30
+
31
+ **Required:**
32
+
33
+ - [mpv](https://mpv.io/) - Media player for audio playback
34
+ - [yt-dlp](https://github.com/yt-dlp/yt-dlp) - YouTube audio extraction
35
+
36
+ ### Installing Prerequisites
37
+
38
+ <details>
39
+ <summary><b>Windows</b></summary>
40
+
41
+ ```bash
42
+ # With Scoop
43
+ scoop install mpv yt-dlp
44
+
45
+ # With Chocolatey
46
+ choco install mpv yt-dlp
47
+
48
+ # With winget
49
+ winget install mpv yt-dlp
50
+ ```
51
+
52
+ </details>
53
+
54
+ <details>
55
+ <summary><b>macOS</b></summary>
56
+
57
+ ```bash
58
+ brew install mpv yt-dlp
59
+ ```
60
+
61
+ </details>
62
+
63
+ <details>
64
+ <summary><b>Linux</b></summary>
65
+
66
+ ```bash
67
+ # Ubuntu/Debian
68
+ sudo apt install mpv
69
+ pip install yt-dlp
70
+
71
+ # Arch Linux
72
+ sudo pacman -S mpv yt-dlp
73
+
74
+ # Fedora
75
+ sudo dnf install mpv yt-dlp
76
+ ```
77
+
78
+ </details>
79
+
80
+ ## Installation
81
+
82
+ ### npm (Recommended)
83
+
84
+ ```bash
85
+ npm install -g @involvex/youtube-music-cli
86
+ ```
87
+
88
+ ### Bun
89
+
90
+ ```bash
91
+ bun install -g @involvex/youtube-music-cli
92
+ ```
93
+
94
+ ### From Source
95
+
96
+ ```bash
97
+ git clone https://github.com/involvex/youtube-music-cli.git
98
+ cd youtube-music-cli
99
+ bun install
100
+ bun run build
101
+ bun link
102
+ ```
103
+
104
+ ## Usage
105
+
106
+ ### Interactive Mode
107
+
108
+ Launch the TUI:
109
+
110
+ ```bash
111
+ youtube-music-cli
112
+ ```
113
+
114
+ ### CLI Commands
115
+
116
+ ```bash
117
+ # Play a specific track
118
+ youtube-music-cli play <video-id>
119
+
120
+ # Search for music
121
+ youtube-music-cli search "artist or song name"
122
+
123
+ # Play a playlist
124
+ youtube-music-cli playlist <playlist-id>
125
+
126
+ # Get suggestions based on current track
127
+ youtube-music-cli suggestions
128
+
129
+ # Playback control
130
+ youtube-music-cli pause
131
+ youtube-music-cli resume
132
+ youtube-music-cli skip
133
+ youtube-music-cli back
134
+ ```
135
+
136
+ ### Options
137
+
138
+ | Flag | Short | Description |
139
+ | ------------ | ----- | -------------------------------------------- |
140
+ | `--theme` | `-t` | Theme: `dark`, `light`, `midnight`, `matrix` |
141
+ | `--volume` | `-v` | Initial volume (0-100) |
142
+ | `--shuffle` | `-s` | Enable shuffle mode |
143
+ | `--repeat` | `-r` | Repeat mode: `off`, `all`, `one` |
144
+ | `--headless` | | Run without TUI |
145
+ | `--help` | `-h` | Show help |
146
+
147
+ ### Examples
148
+
149
+ ```bash
150
+ # Launch with matrix theme at 80% volume
151
+ youtube-music-cli --theme=matrix --volume=80
152
+
153
+ # Search and play in headless mode
154
+ youtube-music-cli search "lofi beats" --headless
155
+
156
+ # Play with shuffle enabled
157
+ youtube-music-cli play dQw4w9WgXcQ --shuffle
158
+ ```
159
+
160
+ ## Keyboard Shortcuts
161
+
162
+ ### Global
163
+
164
+ | Key | Action |
165
+ | ----------- | --------------- |
166
+ | `?` | Show help |
167
+ | `/` | Search |
168
+ | `p` | Plugins manager |
169
+ | `g` | Suggestions |
170
+ | `,` | Settings |
171
+ | `q` / `Esc` | Quit / Go back |
172
+ | `Ctrl+L` | Refresh screen |
173
+
174
+ ### Playback
175
+
176
+ | Key | Action |
177
+ | --------- | ----------------- |
178
+ | `Space` | Play / Pause |
179
+ | `n` / `→` | Next track |
180
+ | `b` / `←` | Previous track |
181
+ | `Shift+→` | Seek forward 10s |
182
+ | `Shift+←` | Seek backward 10s |
183
+ | `=` | Volume up |
184
+ | `-` | Volume down |
185
+ | `s` | Toggle shuffle |
186
+ | `r` | Cycle repeat mode |
187
+
188
+ ### Navigation
189
+
190
+ | Key | Action |
191
+ | --------- | --------- |
192
+ | `↑` / `k` | Move up |
193
+ | `↓` / `j` | Move down |
194
+ | `Enter` | Select |
195
+ | `Esc` | Back |
196
+
197
+ ## Plugins
198
+
199
+ Extend youtube-music-cli with plugins!
200
+
201
+ ### Managing Plugins
202
+
203
+ **TUI Mode:** Press `p` to open the plugins manager.
204
+
205
+ **CLI Mode:**
206
+
207
+ ```bash
208
+ # List installed plugins
209
+ youtube-music-cli plugins list
210
+
211
+ # Install from default repository
212
+ youtube-music-cli plugins install adblock
213
+
214
+ # Install from GitHub URL
215
+ youtube-music-cli plugins install https://github.com/user/my-plugin
216
+
217
+ # Enable/disable
218
+ youtube-music-cli plugins enable my-plugin
219
+ youtube-music-cli plugins disable my-plugin
220
+
221
+ # Update
222
+ youtube-music-cli plugins update my-plugin
223
+
224
+ # Remove
225
+ youtube-music-cli plugins remove my-plugin
226
+ ```
227
+
228
+ ### Available Plugins
229
+
230
+ | Plugin | Description |
231
+ | --------------- | --------------------------------------- |
232
+ | `adblock` | Block ads and sponsored content |
233
+ | `lyrics` | Display synchronized lyrics |
234
+ | `scrobbler` | Scrobble to Last.fm |
235
+ | `discord-rpc` | Discord Rich Presence integration |
236
+ | `notifications` | Desktop notifications for track changes |
237
+
238
+ ### Developing Plugins
239
+
240
+ See [Plugin Development Guide](docs/PLUGIN_DEVELOPMENT.md) and [Plugin API Reference](docs/PLUGIN_API.md).
241
+
242
+ ```bash
243
+ # Start from a template
244
+ cp -r templates/plugin-basic my-plugin
245
+ cd my-plugin
246
+
247
+ # Edit plugin.json and index.ts
248
+ # Install for testing
249
+ youtube-music-cli plugins install /path/to/my-plugin
250
+ ```
251
+
252
+ ## Configuration
253
+
254
+ Config is stored in `~/.youtube-music-cli/config.json`:
255
+
256
+ ```json
257
+ {
258
+ "theme": "dark",
259
+ "volume": 70,
260
+ "shuffle": false,
261
+ "repeat": "off",
262
+ "streamQuality": "high"
263
+ }
264
+ ```
265
+
266
+ ### Stream Quality
267
+
268
+ | Quality | Description |
269
+ | -------- | ----------------------- |
270
+ | `low` | 64kbps - Save bandwidth |
271
+ | `medium` | 128kbps - Balanced |
272
+ | `high` | 256kbps+ - Best quality |
273
+
274
+ ## Troubleshooting
275
+
276
+ ### mpv not found
277
+
278
+ Ensure mpv is installed and in your PATH:
279
+
280
+ ```bash
281
+ mpv --version
282
+ ```
283
+
284
+ ### No audio
285
+
286
+ 1. Check volume isn't muted (`=` to increase)
287
+ 2. Verify yt-dlp is working: `yt-dlp --version`
288
+ 3. Try a different track
289
+
290
+ ### TUI rendering issues
291
+
292
+ Press `Ctrl+L` to refresh the screen, or try a different terminal emulator.
293
+
294
+ ### Plugin not loading
295
+
296
+ 1. Check `plugin.json` syntax is valid
297
+ 2. Verify the plugin is enabled: `youtube-music-cli plugins list`
298
+ 3. Check logs for errors
299
+
300
+ ## Contributing
301
+
302
+ Contributions are welcome!
303
+
304
+ 1. Fork the repository
305
+ 2. Create a feature branch: `git checkout -b feature/my-feature`
306
+ 3. Make your changes
307
+ 4. Run tests: `bun run test`
308
+ 5. Commit: `git commit -m 'feat: add my feature'`
309
+ 6. Push: `git push origin feature/my-feature`
310
+ 7. Open a Pull Request
311
+
312
+ ### Development
313
+
314
+ ```bash
315
+ # Install dependencies
316
+ bun install
317
+
318
+ # Run in development mode
319
+ bun run dev
320
+
321
+ # Build
322
+ bun run build
323
+
324
+ # Lint and format
325
+ bun run lint:fix
326
+ bun run format
327
+
328
+ # Type check
329
+ bun run typecheck
330
+ ```
331
+
332
+ ## Tech Stack
333
+
334
+ - **Runtime:** [Bun](https://bun.sh/) / Node.js
335
+ - **UI Framework:** [Ink](https://github.com/vadimdemedes/ink) (React for CLI)
336
+ - **Language:** TypeScript
337
+ - **Audio:** mpv + yt-dlp
338
+ - **API:** YouTube Music Innertube API
339
+
340
+ ## License
341
+
342
+ MIT © [Involvex](https://github.com/involvex)
343
+
344
+ ---
345
+
346
+ <div align="center">
347
+
348
+ **[Documentation](https://involvex.github.io/youtube-music-cli)** • **[Report Bug](https://github.com/involvex/youtube-music-cli/issues)** • **[Request Feature](https://github.com/involvex/youtube-music-cli/issues)**
349
+
350
+ Made with ❤️ for music lovers
351
+
352
+ </div>
@@ -0,0 +1,2 @@
1
+ declare const _default: import("eslint/config").Config[];
2
+ export default _default;
@@ -0,0 +1,55 @@
1
+ import pluginReact from 'eslint-plugin-react';
2
+ import hooksPlugin from 'eslint-plugin-react-hooks';
3
+ import { defineConfig } from 'eslint/config';
4
+ import tseslint from 'typescript-eslint';
5
+ import globals from 'globals';
6
+ import js from '@eslint/js';
7
+ export default defineConfig([
8
+ {
9
+ ignores: ['templates/**/*', 'plugins/**/*'],
10
+ },
11
+ {
12
+ files: ['**/*.{js,mjs,cjs}'],
13
+ plugins: { js },
14
+ extends: ['js/recommended'],
15
+ languageOptions: { globals: { ...globals.node } },
16
+ },
17
+ ...tseslint.configs.recommended,
18
+ {
19
+ files: ['**/*.{ts,mts,cts,jsx,tsx}'],
20
+ languageOptions: {
21
+ globals: { ...globals.node },
22
+ ecmaVersion: 'latest',
23
+ sourceType: 'module',
24
+ parserOptions: {
25
+ projectService: true,
26
+ tsconfigRootDir: import.meta.dirname,
27
+ },
28
+ },
29
+ },
30
+ {
31
+ files: ['**/*.jsx', '**/*.tsx'],
32
+ ...pluginReact.configs.flat['recommended'],
33
+ plugins: {
34
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
35
+ 'react-hooks': hooksPlugin,
36
+ },
37
+ settings: {
38
+ react: { version: 'detect' },
39
+ jsxRuntime: 'automatic',
40
+ },
41
+ rules: {
42
+ ...hooksPlugin.configs.recommended.rules,
43
+ 'react/react-in-jsx-scope': 'off',
44
+ 'react/jsx-uses-react': 'off',
45
+ '@typescript-eslint/no-unused-vars': [
46
+ 'error',
47
+ {
48
+ argsIgnorePattern: '^_',
49
+ varsIgnorePattern: '^_',
50
+ caughtErrorsIgnorePattern: '^_',
51
+ },
52
+ ],
53
+ },
54
+ },
55
+ ]);
@@ -0,0 +1,4 @@
1
+ import type { Flags } from './types/cli.types.ts';
2
+ export default function App({ flags }: {
3
+ flags?: Flags;
4
+ }): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,17 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ // Root application component
3
+ import { useApp } from 'ink';
4
+ import Main from "./main.js";
5
+ import { useEffect } from 'react';
6
+ // Handle unmounting
7
+ let unmount = null;
8
+ export default function App({ flags }) {
9
+ const { exit } = useApp();
10
+ // Store unmount function globally
11
+ useEffect(() => {
12
+ if (!unmount) {
13
+ unmount = exit;
14
+ }
15
+ }, [exit]);
16
+ return _jsx(Main, { flags: flags });
17
+ }
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
@@ -0,0 +1,241 @@
1
+ #!/usr/bin/env node
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ import App from "./app.js";
4
+ import { render } from 'ink';
5
+ import meow from 'meow';
6
+ import { getPluginInstallerService } from "./services/plugin/plugin-installer.service.js";
7
+ import { getPluginUpdaterService } from "./services/plugin/plugin-updater.service.js";
8
+ import { getPluginRegistryService } from "./services/plugin/plugin-registry.service.js";
9
+ const cli = meow(`
10
+ Usage
11
+ $ youtube-music-cli
12
+ $ youtube-music-cli play <track-id>
13
+ $ youtube-music-cli search <query>
14
+ $ youtube-music-cli playlist <playlist-id>
15
+ $ youtube-music-cli suggestions
16
+ $ youtube-music-cli pause
17
+ $ youtube-music-cli resume
18
+ $ youtube-music-cli skip
19
+ $ youtube-music-cli back
20
+
21
+ Plugin Commands
22
+ $ youtube-music-cli plugins list
23
+ $ youtube-music-cli plugins install <name|url>
24
+ $ youtube-music-cli plugins remove <name>
25
+ $ youtube-music-cli plugins update <name>
26
+ $ youtube-music-cli plugins enable <name>
27
+ $ youtube-music-cli plugins disable <name>
28
+
29
+ Options
30
+ --theme, -t Theme to use (dark, light, midnight, matrix)
31
+ --volume, -v Initial volume (0-100)
32
+ --shuffle, -s Enable shuffle mode
33
+ --repeat, -r Repeat mode (off, all, one)
34
+ --headless Run without TUI (just play)
35
+ --help, -h Show this help
36
+
37
+ Examples
38
+ $ youtube-music-cli
39
+ $ youtube-music-cli play dQw4w9WgXcQ
40
+ $ youtube-music-cli search "Rick Astley"
41
+ $ youtube-music-cli play dQw4w9WgXcQ --headless
42
+ $ youtube-music-cli plugins install adblock
43
+ `, {
44
+ importMeta: import.meta,
45
+ flags: {
46
+ theme: {
47
+ type: 'string',
48
+ shortFlag: 't',
49
+ },
50
+ volume: {
51
+ type: 'number',
52
+ shortFlag: 'v',
53
+ },
54
+ shuffle: {
55
+ type: 'boolean',
56
+ shortFlag: 's',
57
+ default: false,
58
+ },
59
+ repeat: {
60
+ type: 'string',
61
+ shortFlag: 'r',
62
+ },
63
+ headless: {
64
+ type: 'boolean',
65
+ default: false,
66
+ },
67
+ help: {
68
+ type: 'boolean',
69
+ shortFlag: 'h',
70
+ default: false,
71
+ },
72
+ },
73
+ autoVersion: true,
74
+ autoHelp: false,
75
+ });
76
+ if (cli.flags.help) {
77
+ cli.showHelp(0);
78
+ }
79
+ // Handle plugin commands
80
+ const command = cli.input[0];
81
+ const args = cli.input.slice(1);
82
+ if (command === 'plugins') {
83
+ const subCommand = args[0];
84
+ const pluginArg = args[1];
85
+ void (async () => {
86
+ const installer = getPluginInstallerService();
87
+ const updater = getPluginUpdaterService();
88
+ const registry = getPluginRegistryService();
89
+ // Load existing plugins
90
+ await registry.loadAllPlugins();
91
+ switch (subCommand) {
92
+ case 'list': {
93
+ const plugins = registry.getAllPlugins();
94
+ if (plugins.length === 0) {
95
+ console.log('No plugins installed.');
96
+ }
97
+ else {
98
+ console.log('Installed plugins:');
99
+ for (const plugin of plugins) {
100
+ const status = plugin.enabled ? '●' : '○';
101
+ console.log(` ${status} ${plugin.manifest.name} v${plugin.manifest.version}`);
102
+ }
103
+ }
104
+ process.exit(0);
105
+ break;
106
+ }
107
+ case 'install': {
108
+ if (!pluginArg) {
109
+ console.error('Usage: youtube-music-cli plugins install <name|url>');
110
+ process.exit(1);
111
+ }
112
+ console.log(`Installing ${pluginArg}...`);
113
+ let result;
114
+ if (pluginArg.startsWith('http')) {
115
+ result = await installer.installFromGitHub(pluginArg);
116
+ }
117
+ else {
118
+ result = await installer.installFromDefaultRepo(pluginArg);
119
+ }
120
+ if (result.success) {
121
+ console.log(`✓ Successfully installed ${result.pluginId}`);
122
+ }
123
+ else {
124
+ console.error(`✗ Failed: ${result.error}`);
125
+ process.exit(1);
126
+ }
127
+ process.exit(0);
128
+ break;
129
+ }
130
+ case 'remove':
131
+ case 'uninstall': {
132
+ if (!pluginArg) {
133
+ console.error('Usage: youtube-music-cli plugins remove <name>');
134
+ process.exit(1);
135
+ }
136
+ console.log(`Removing ${pluginArg}...`);
137
+ try {
138
+ await registry.unloadPlugin(pluginArg);
139
+ }
140
+ catch {
141
+ // Plugin may not be loaded
142
+ }
143
+ const result = await installer.uninstall(pluginArg);
144
+ if (result.success) {
145
+ console.log(`✓ Successfully removed ${pluginArg}`);
146
+ }
147
+ else {
148
+ console.error(`✗ Failed: ${result.error}`);
149
+ process.exit(1);
150
+ }
151
+ process.exit(0);
152
+ break;
153
+ }
154
+ case 'update': {
155
+ if (!pluginArg) {
156
+ console.error('Usage: youtube-music-cli plugins update <name>');
157
+ process.exit(1);
158
+ }
159
+ console.log(`Updating ${pluginArg}...`);
160
+ const result = await updater.updatePlugin(pluginArg);
161
+ if (result.success) {
162
+ console.log(`✓ Updated ${pluginArg} from ${result.oldVersion} to ${result.newVersion}`);
163
+ }
164
+ else {
165
+ console.error(`✗ Failed: ${result.error}`);
166
+ process.exit(1);
167
+ }
168
+ process.exit(0);
169
+ break;
170
+ }
171
+ case 'enable': {
172
+ if (!pluginArg) {
173
+ console.error('Usage: youtube-music-cli plugins enable <name>');
174
+ process.exit(1);
175
+ }
176
+ try {
177
+ await registry.enablePlugin(pluginArg);
178
+ console.log(`✓ Enabled ${pluginArg}`);
179
+ }
180
+ catch (error) {
181
+ console.error(`✗ Failed: ${error instanceof Error ? error.message : String(error)}`);
182
+ process.exit(1);
183
+ }
184
+ process.exit(0);
185
+ break;
186
+ }
187
+ case 'disable': {
188
+ if (!pluginArg) {
189
+ console.error('Usage: youtube-music-cli plugins disable <name>');
190
+ process.exit(1);
191
+ }
192
+ try {
193
+ await registry.disablePlugin(pluginArg);
194
+ console.log(`✓ Disabled ${pluginArg}`);
195
+ }
196
+ catch (error) {
197
+ console.error(`✗ Failed: ${error instanceof Error ? error.message : String(error)}`);
198
+ process.exit(1);
199
+ }
200
+ process.exit(0);
201
+ break;
202
+ }
203
+ default:
204
+ console.error('Usage: youtube-music-cli plugins <list|install|remove|update|enable|disable>');
205
+ process.exit(1);
206
+ }
207
+ })();
208
+ }
209
+ else {
210
+ // Handle other direct commands
211
+ if (command === 'play' && args[0]) {
212
+ // Play specific track
213
+ cli.flags.playTrack = args[0];
214
+ }
215
+ else if (command === 'search' && args[0]) {
216
+ // Search for query
217
+ cli.flags.searchQuery = args.join(' ');
218
+ }
219
+ else if (command === 'playlist' && args[0]) {
220
+ // Play specific playlist
221
+ cli.flags.playPlaylist = args[0];
222
+ }
223
+ else if (command === 'suggestions') {
224
+ // Show suggestions
225
+ cli.flags.showSuggestions = true;
226
+ }
227
+ else if (command === 'pause') {
228
+ cli.flags.action = 'pause';
229
+ }
230
+ else if (command === 'resume') {
231
+ cli.flags.action = 'resume';
232
+ }
233
+ else if (command === 'skip') {
234
+ cli.flags.action = 'next';
235
+ }
236
+ else if (command === 'back') {
237
+ cli.flags.action = 'previous';
238
+ }
239
+ // Render the app
240
+ render(_jsx(App, { flags: cli.flags }));
241
+ }
@@ -0,0 +1,15 @@
1
+ import { Component, type ErrorInfo, type ReactNode } from 'react';
2
+ interface Props {
3
+ children: ReactNode;
4
+ }
5
+ interface State {
6
+ hasError: boolean;
7
+ error: Error | null;
8
+ }
9
+ export declare class ErrorBoundary extends Component<Props, State> {
10
+ state: State;
11
+ static getDerivedStateFromError(error: Error): State;
12
+ componentDidCatch(error: Error, errorInfo: ErrorInfo): void;
13
+ render(): string | number | bigint | boolean | Iterable<ReactNode> | Promise<string | number | bigint | boolean | import("react").ReactPortal | import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | Iterable<ReactNode> | null | undefined> | import("react/jsx-runtime").JSX.Element | null | undefined;
14
+ }
15
+ export {};