@ciphore/radiocli 0.2.3 → 0.2.5

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 (172) hide show
  1. package/CHANGELOG.md +147 -2
  2. package/CONTRIBUTING.md +46 -6
  3. package/README.md +108 -209
  4. package/SECURITY.md +23 -1
  5. package/dist/agent/alarm-service.js +10 -7
  6. package/dist/agent/cli.js +16 -1
  7. package/dist/agent/command-schema.js +47 -0
  8. package/dist/agent/headless-host.js +234 -67
  9. package/dist/agent/launcher.js +7 -67
  10. package/dist/agent/mcp-install.js +15 -15
  11. package/dist/agent/mcp-server.js +10 -5
  12. package/dist/agent/service.js +74 -39
  13. package/dist/agent/session.js +227 -53
  14. package/dist/agent/tui-session.js +213 -0
  15. package/dist/alarms/active-session.js +9 -12
  16. package/dist/alarms/cli.js +19 -3
  17. package/dist/alarms/guard.js +79 -36
  18. package/dist/alarms/inhibitor.js +27 -22
  19. package/dist/alarms/occurrence-cache.js +25 -0
  20. package/dist/alarms/power-guard-store.js +2 -10
  21. package/dist/alarms/runner.js +140 -45
  22. package/dist/alarms/schedule.js +37 -2
  23. package/dist/alarms/scheduler.js +202 -52
  24. package/dist/alarms/setup-verification.js +1 -2
  25. package/dist/alarms/system-volume-linux.js +160 -0
  26. package/dist/alarms/system-volume-ownership.js +335 -0
  27. package/dist/alarms/system-volume.js +188 -26
  28. package/dist/alarms/terminal-launcher.js +76 -136
  29. package/dist/alarms/tui-presence.js +2 -4
  30. package/dist/cli/arguments.js +212 -0
  31. package/dist/cli/completion.js +44 -0
  32. package/dist/cli/doctor.js +156 -0
  33. package/dist/cli/interactive.js +79 -0
  34. package/dist/cli/listener.js +227 -0
  35. package/dist/cli/output.js +121 -0
  36. package/dist/cli/render-tui.js +34 -0
  37. package/dist/cli.js +198 -154
  38. package/dist/platform/capabilities.js +60 -0
  39. package/dist/platform/desktop-media.js +61 -0
  40. package/dist/platform/desktop.js +36 -0
  41. package/dist/platform/diagnostics.js +273 -0
  42. package/dist/{player/command.js → platform/executables.js} +43 -9
  43. package/dist/platform/ipc.js +14 -0
  44. package/dist/platform/json-worker.js +111 -0
  45. package/dist/platform/launch-command.js +138 -0
  46. package/dist/platform/loopback.js +44 -0
  47. package/dist/platform/mpris.js +356 -0
  48. package/dist/platform/network.js +380 -0
  49. package/dist/platform/omarchy.js +147 -0
  50. package/dist/platform/packages.js +222 -0
  51. package/dist/platform/paths.js +40 -0
  52. package/dist/platform/runtime.js +67 -0
  53. package/dist/platform/shell.js +24 -0
  54. package/dist/platform/storage.js +48 -0
  55. package/dist/platform/support.js +214 -0
  56. package/dist/platform/terminal.js +63 -0
  57. package/dist/platform/terminals.js +223 -0
  58. package/dist/player/airplay-discovery.js +145 -60
  59. package/dist/player/airplay-policy.js +15 -0
  60. package/dist/player/airplay-process.js +63 -0
  61. package/dist/player/airplay-readiness.js +42 -0
  62. package/dist/player/airplay-sender-health.js +49 -49
  63. package/dist/player/airplay-sender-package.js +5 -0
  64. package/dist/player/airplay-sender-patch.js +102 -4
  65. package/dist/player/airplay-setup.js +51 -0
  66. package/dist/player/airplay-worker.js +97 -41
  67. package/dist/player/backend-install.js +17 -95
  68. package/dist/player/command-diagnostics.js +2 -2
  69. package/dist/player/ffmpeg-input.js +37 -0
  70. package/dist/player/mpv-desktop-media.js +194 -0
  71. package/dist/player/mpv-ipc-client.js +52 -2
  72. package/dist/player/player-controller.js +569 -82
  73. package/dist/player/radio-engine.js +282 -0
  74. package/dist/playlists/playlist.js +18 -16
  75. package/dist/providers/cache.js +293 -99
  76. package/dist/providers/discovery-session.js +111 -0
  77. package/dist/providers/provider-manager.js +106 -28
  78. package/dist/providers/radio-browser.js +418 -89
  79. package/dist/providers/radio-garden.js +18 -23
  80. package/dist/setup-playback.js +152 -0
  81. package/dist/setup.js +163 -168
  82. package/dist/storage/file-lock.js +113 -0
  83. package/dist/storage/read-settings.js +33 -0
  84. package/dist/storage/replace-file.js +20 -0
  85. package/dist/storage/repository.js +247 -0
  86. package/dist/storage/station-identity.js +21 -0
  87. package/dist/storage/station-schema.js +27 -0
  88. package/dist/storage/store.js +333 -107
  89. package/dist/streams/import-stream.js +163 -0
  90. package/dist/ui/AdaptiveContent.js +49 -32
  91. package/dist/ui/App.js +822 -481
  92. package/dist/ui/AppContent.js +5 -5
  93. package/dist/ui/airplay-settings.js +12 -5
  94. package/dist/ui/app-state.js +8 -1
  95. package/dist/ui/ascii.js +11 -2
  96. package/dist/ui/bidi-ranges.js +45 -0
  97. package/dist/ui/components/AdaptiveMarquee.js +20 -10
  98. package/dist/ui/components/Logo.js +5 -2
  99. package/dist/ui/components/Menu.js +2 -2
  100. package/dist/ui/components/ScreenHeader.js +1 -1
  101. package/dist/ui/components/StationList.js +6 -4
  102. package/dist/ui/components/TopTabs.js +1 -1
  103. package/dist/ui/display-context.js +8 -11
  104. package/dist/ui/format.js +37 -4
  105. package/dist/ui/help-content.js +9 -6
  106. package/dist/ui/layout.js +5 -2
  107. package/dist/ui/page-footer.js +3 -3
  108. package/dist/ui/rtl-output.js +137 -0
  109. package/dist/ui/screen-items.js +12 -6
  110. package/dist/ui/screen-meta.js +1 -1
  111. package/dist/ui/screens/AirPlayCodeScreen.js +6 -2
  112. package/dist/ui/screens/AirPlaySettingsScreen.js +10 -6
  113. package/dist/ui/screens/AlarmsScreen.js +5 -2
  114. package/dist/ui/screens/ExploreScreen.js +2 -1
  115. package/dist/ui/screens/HelpScreen.js +8 -4
  116. package/dist/ui/screens/HomeScreen.js +5 -1
  117. package/dist/ui/screens/MapScreen.js +1 -1
  118. package/dist/ui/screens/NowPlayingScreen.js +4 -4
  119. package/dist/ui/screens/SearchScreen.js +3 -1
  120. package/dist/ui/screens/SettingsScreen.js +28 -21
  121. package/dist/ui/screens/StatsScreen.js +3 -1
  122. package/dist/ui/system-actions.js +80 -52
  123. package/dist/ui/terminal-renderer.js +16 -0
  124. package/dist/ui/text-direction.js +9 -0
  125. package/dist/ui/use-alarm-tui.js +57 -42
  126. package/dist/ui/use-app-input.js +84 -30
  127. package/dist/ui/use-command-executor.js +50 -19
  128. package/dist/ui/visualizers/gallop.js +1 -1
  129. package/dist/ui/visualizers/receiver-style-registry.js +2 -1
  130. package/dist/update-check.js +10 -18
  131. package/docs/THIRD_PARTY_NOTICES.md +6 -4
  132. package/package.json +34 -11
  133. package/scripts/build-airplay-native.mjs +22 -0
  134. package/vendor/node-airtunes2/LICENSE +208 -0
  135. package/vendor/node-airtunes2/RADIOCLI_PATCH.md +29 -0
  136. package/vendor/node-airtunes2/README.md +225 -0
  137. package/vendor/node-airtunes2/UPSTREAM.json +50 -0
  138. package/vendor/node-airtunes2/binding.gyp +41 -0
  139. package/vendor/node-airtunes2/lib/ap2_test.js +4 -0
  140. package/vendor/node-airtunes2/lib/atv.js +307 -0
  141. package/vendor/node-airtunes2/lib/atvAuthenticator.js +136 -0
  142. package/vendor/node-airtunes2/lib/audio_out.js +69 -0
  143. package/vendor/node-airtunes2/lib/circular_buffer.js +133 -0
  144. package/vendor/node-airtunes2/lib/config.js +26 -0
  145. package/vendor/node-airtunes2/lib/device_airtunes.js +532 -0
  146. package/vendor/node-airtunes2/lib/devices.js +266 -0
  147. package/vendor/node-airtunes2/lib/ed25519.js +26 -0
  148. package/vendor/node-airtunes2/lib/homekit/credentials.js +86 -0
  149. package/vendor/node-airtunes2/lib/homekit/encryption.js +69 -0
  150. package/vendor/node-airtunes2/lib/homekit/number.js +44 -0
  151. package/vendor/node-airtunes2/lib/homekit/tlv.js +95 -0
  152. package/vendor/node-airtunes2/lib/http.js +189 -0
  153. package/vendor/node-airtunes2/lib/index.d.ts +141 -0
  154. package/vendor/node-airtunes2/lib/index.js +127 -0
  155. package/vendor/node-airtunes2/lib/ntp.js +37 -0
  156. package/vendor/node-airtunes2/lib/num_util.js +21 -0
  157. package/vendor/node-airtunes2/lib/packet_pool.js +43 -0
  158. package/vendor/node-airtunes2/lib/rtsp.js +1807 -0
  159. package/vendor/node-airtunes2/lib/srp.js +158 -0
  160. package/vendor/node-airtunes2/lib/udp_servers.js +214 -0
  161. package/vendor/node-airtunes2/lib/util.js +12 -0
  162. package/vendor/node-airtunes2/package.json +31 -0
  163. package/vendor/node-airtunes2/src/CADebugMacros.h +257 -0
  164. package/vendor/node-airtunes2/src/CAHostTimeBase.cpp +105 -0
  165. package/vendor/node-airtunes2/src/CAHostTimeBase.h +224 -0
  166. package/vendor/node-airtunes2/src/aes_utils.c +864 -0
  167. package/vendor/node-airtunes2/src/aes_utils.h +24 -0
  168. package/vendor/node-airtunes2/src/base64.c +136 -0
  169. package/vendor/node-airtunes2/src/base64.h +42 -0
  170. package/vendor/node-airtunes2/src/bindings.cc +29 -0
  171. package/vendor/node-airtunes2/src/codec.cc +170 -0
  172. package/vendor/node-airtunes2/src/coreaudio.cc +332 -0
package/CHANGELOG.md CHANGED
@@ -2,8 +2,151 @@
2
2
 
3
3
  All notable changes to RadioCLI are documented in this file.
4
4
 
5
- The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
- and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
5
+ ## [0.2.5] - 2026-10-18
6
+
7
+ ### Added
8
+
9
+ - Added direct shell playback, volume controls, station-name lookup, filtered
10
+ search, favorites, recents, named presets, and listening stats.
11
+ - Added a compact now-playing view with live track metadata and `--watch`,
12
+ readable terminal tables, JSON/plain output, and shell completion for Bash,
13
+ Zsh, Fish, and PowerShell.
14
+ - Added Linux desktop media controls for RadioCLI's station queue, metadata,
15
+ playback, and volume, with `radiocli media-controls auto|on|off` overrides.
16
+ - Added experimental Omarchy Quattro integration with preferred-terminal
17
+ launching and desktop/session diagnostics.
18
+ - Added experimental, opt-in Linux AirPlay with Avahi discovery, receiver
19
+ selection, passcode handling, and guided dependency setup.
20
+
21
+ ### Changed
22
+
23
+ - Simplified shell help around eight everyday commands, with `help --all` for
24
+ the full reference, `play` to resume, and favorites, recent, and popular queues.
25
+ - Expanded Doctor with separate terminal, desktop media, audio, Omarchy, and
26
+ AirPlay readiness checks.
27
+ - Included station presets in library backup, restore, and concurrent saves.
28
+ - Reduced Gallop's drawing scale by 10% while preserving its proportions,
29
+ centering, and animation timing.
30
+ - Removed the twelve preview receiver scenes, retaining the original 63 styles
31
+ and Ultracode default. Retired selections migrate without resetting saved data.
32
+
33
+ ### Fixed
34
+
35
+ - Kept TUI playback running after a terminal crash, recovering the active
36
+ station, queue, controls, and sleep timer when the terminal reopens.
37
+ - Recovered interrupted or stalled live mpv streams without restarting paused
38
+ sessions, finite recordings, or playback canceled by Stop.
39
+ - Prevented duplicate mpv desktop media players and kept desktop controls in
40
+ sync with the shared player, including live-edge resume and alarm transitions.
41
+ - Restored alarm volume to the original Linux output after default-device
42
+ changes and overlapping alarms, and kept imported alarm IDs distinct across
43
+ case-insensitive and Unicode-normalizing filesystems.
44
+ - Preserved AirPlay mute, volume, and station metadata during connection setup,
45
+ added legacy RAOP password authentication, and improved connection errors.
46
+ - Protected concurrent library saves and preserved the latest data in the safety
47
+ backup before a restore. Retried temporary Windows file-replacement conflicts.
48
+ - Preserved migrated custom-station IDs, corrected XSPF CDATA and Unicode URL
49
+ imports, and restored Windows drive-path playlist imports.
50
+ - Corrected mixed Arabic/Latin terminal layout and emoji clipping, padding, and
51
+ scrolling without changing plain output or screen-reader behavior.
52
+ - Expired future-dated provider cache entries after clock corrections and
53
+ preserved valid data when migrating older caches.
54
+ - Preserved package-manager paths during Unix updates and allowed slower
55
+ PowerShell startup when opening native Windows terminals.
56
+ - Fixed a documentation typecheck race and added a single required CI gate for
57
+ platform, playback, and documentation checks. Release checks now include
58
+ packed upgrades from 0.2.3 and 0.2.4 and native TUI crash recovery.
59
+
60
+ ### Security
61
+
62
+ - Removed the optional AirPlay sender's vulnerable elliptic dependency, using
63
+ Node's native Ed25519 while preserving pairing formats and optional installs.
64
+ - Enabled native stream certificate verification and restricted FFmpeg network
65
+ playlists that cannot safely carry TLS policy. Documented the remaining
66
+ native OpenSSL numeric-IP certificate identity limitation.
67
+ - Kept Doctor's probes read-only, bounded local service checks, and excluded
68
+ receiver codes and stream credentials from AirPlay diagnostics.
69
+ - Updated documentation and development dependencies to patched releases.
70
+
71
+ Quattro integration and Linux AirPlay remain experimental. Software playback
72
+ checks do not establish physical receiver, speaker, hardware-key, or suspend/wake
73
+ support; existing platform support tiers are unchanged.
74
+
75
+ ## [0.2.4] - 2026-09-17
76
+
77
+ ### Added
78
+
79
+ - Added a shared platform layer for runtime eligibility, capabilities, executable
80
+ discovery, package installation, storage paths, networking, IPC, desktop
81
+ helpers, and terminal launching.
82
+ - Added first-class Node.js 22 and 24 CI coverage for macOS Apple Silicon and
83
+ Intel, Ubuntu x64 and arm64, Windows x64, and Windows 11 arm64, including
84
+ packed installation and native mpv IPC playback checks.
85
+ - Added repeatable packed CLI and mpv playback checks in full FreeBSD, OpenBSD,
86
+ and NetBSD guest kernels, plus explicit installation and capability guidance
87
+ for additional Unix, WSL, Termux, Haiku, illumos, and AIX environments.
88
+ - Added offline, low-bandwidth, screen-reader, reduced-motion, ASCII, limited-
89
+ color, and noninteractive terminal modes with deterministic full, compact,
90
+ and micro rendering coverage.
91
+ - Added automatic HTTP/ICY metadata discovery when importing a direct station
92
+ URL from the CLI or the TUI command palette.
93
+
94
+ ### Changed
95
+
96
+ - Centralized native package recipes and guided setup so dry runs and executed
97
+ commands use the same platform-specific definitions.
98
+ - Expanded `radiocli doctor --json` with host, runtime, network, storage,
99
+ terminal, playback, desktop, scheduling, and optional-feature capabilities.
100
+ - Reorganized installation, platform, architecture, reliability, privacy, and
101
+ contributor documentation as stable reference material with explicit support
102
+ boundaries and troubleshooting paths.
103
+ - Changed TUI `:import` to add custom stream URLs, renamed full-library recovery
104
+ to `:restore`, and consolidated shell URL additions under `radiocli import`.
105
+ - Placed newest imported stations after favorites and before recently played
106
+ stations in the Library.
107
+ - Changed resume for live radio to reload the active stream at its current live
108
+ edge instead of replaying audio accumulated in mpv's paused buffer.
109
+
110
+ ### Fixed
111
+
112
+ - Kept playback and the TUI usable when optional history, presence, cache, or
113
+ library writes fail, while preserving recoverable data after interrupted or
114
+ permission-denied writes.
115
+ - Hardened alarm deletion, native scheduler cleanup, terminal reopening, Alarm
116
+ Guard ownership, system-volume restoration, and forced-process teardown.
117
+ - Preserved exact arguments, data locations, and supported environment selectors
118
+ across macOS, Linux, BSD, and Windows child processes without forwarding
119
+ unrelated shell state.
120
+ - Improved player discovery, mpv readiness and IPC handling, provider timeouts,
121
+ mirror fallback, offline cache behavior, and degraded terminal rendering.
122
+ - Recovered ARM Linux playback from mpv audio-service initialization failures
123
+ by retrying once with ALSA first, retained bounded player diagnostics, and
124
+ stopped system-wide backend failures from skipping through every station.
125
+ - Replaced stale Radio Browser hosts with live DNS service discovery and added
126
+ a TLS-verified resolver fallback for temporary hostname failures without
127
+ bypassing configured proxies.
128
+ - Preserved full RGB theme colors when a terminal explicitly advertises
129
+ truecolor, even when its Node.js stream reports a conservative 256-color
130
+ depth; explicit 256-color, 16-color, and no-color modes remain unchanged.
131
+ - Kept retained Search results playable after clearing the submitted query and
132
+ added `Ctrl+F` to favorite the selected result while query input is active,
133
+ without intercepting an ordinary `f` typed into the search text.
134
+ - Dismissed added and removed favorite confirmations after 4.5 seconds on
135
+ Overview, Now Playing, Library, Explore, Search, Nearby, and country station
136
+ views.
137
+ - Marked AirPlay controls as macOS-only, hid the unsupported Settings shortcut,
138
+ and kept non-macOS users on their current screen with a direct platform notice.
139
+ - Corrected Windows terminal launches to create independent interactive console
140
+ handles and retain the intended user data location.
141
+
142
+ ### Security
143
+
144
+ - Updated documentation-site dependencies to patched releases.
145
+ - Limited child-process environments to the settings required for RadioCLI data
146
+ identity and native integrations, excluding unrelated credentials and proxy
147
+ secrets.
148
+ - Made native cleanup and ownership checks fail closed when a job, helper,
149
+ process, or saved state cannot be identified safely.
7
150
 
8
151
  ## [0.2.3] - 2026-09-07
9
152
 
@@ -397,7 +540,9 @@ Initial public release.
397
540
  [0.2.1]: https://github.com/Ciphore/RadioCLI/releases/tag/v0.2.1
398
541
  [0.2.2]: https://github.com/Ciphore/RadioCLI/releases/tag/v0.2.2
399
542
  [0.2.3]: https://github.com/Ciphore/RadioCLI/releases/tag/v0.2.3
543
+ [0.2.4]: https://github.com/Ciphore/RadioCLI/releases/tag/v0.2.4
400
544
  [0.1.4]: https://github.com/Ciphore/RadioCLI/releases/tag/v0.1.4
401
545
  [0.1.3]: https://github.com/Ciphore/RadioCLI/releases/tag/v0.1.3
402
546
  [0.1.2]: https://github.com/Ciphore/RadioCLI/releases/tag/v0.1.2
403
547
  [0.1.1]: https://github.com/Ciphore/RadioCLI/releases/tag/v0.1.1
548
+ [0.2.5]: https://github.com/Ciphore/RadioCLI/releases/tag/v0.2.5
package/CONTRIBUTING.md CHANGED
@@ -12,19 +12,22 @@ npm run build
12
12
  npm run test
13
13
  ```
14
14
 
15
- Install `mpv` for playback controls, metadata polling, and the best playback
16
- experience:
15
+ Install `mpv` for playback controls and metadata polling. On a macOS
16
+ configuration supported by Homebrew:
17
17
 
18
18
  ```bash
19
19
  brew install mpv
20
20
  ```
21
21
 
22
- On Linux, use your package manager's `mpv` package. On Windows, use:
22
+ On Linux, use your package manager's `mpv` package. On Windows x64, use:
23
23
 
24
24
  ```powershell
25
25
  winget install --id shinchiro.mpv -e
26
26
  ```
27
27
 
28
+ Use the [platform installation routes](apps/docs/content/docs/platforms.mdx#installation-and-playback-prerequisites)
29
+ for Windows arm64 and other package managers.
30
+
28
31
  ## Verification
29
32
 
30
33
  Run these before opening a PR:
@@ -34,11 +37,29 @@ npm run check
34
37
  npm run lint
35
38
  npm run test
36
39
  npm run build
40
+ npm run pack:check
41
+ npm run fresh:check -- --require-mpv
42
+ npm run check:package
43
+ npm run smoke:mcp
44
+ npm run docs:check
45
+ npm run docs:build
37
46
  ```
38
47
 
39
- Run `npm run smoke:playback` when changing playback code. It opens a public
40
- stream briefly, so do not run it in environments where audio/network access is
41
- not acceptable.
48
+ Install documentation dependencies with `npm --prefix apps/docs ci` first.
49
+ Run `npm run smoke:playback` when changing playback code. Its default fixture is
50
+ a local WAV file; mpv uses null audio in deterministic package
51
+ checks. These checks exercise the player process and controls, and do not prove
52
+ speaker output. `npm run smoke:data` intentionally contacts public providers.
53
+
54
+ Also run `npm run smoke:network` for playback or transport changes. It uses
55
+ loopback HTTP/TLS fixtures with null/dummy audio to verify certificate rejection,
56
+ live EOF and stall recovery, finite-media EOF, Stop ownership, and installed
57
+ fallback readiness. Set `RADIOCLI_REQUIRE_FALLBACKS=1` when the test host should
58
+ have FFmpeg, ffplay and VLC; missing tools then fail instead of being skipped.
59
+
60
+ Run `npm run build && npm run smoke:cli` when changing shell playback or session
61
+ control. It uses an isolated library and silent local WAV with mpv's null audio
62
+ output to check background startup, separate CLI controls, presets, and shutdown.
42
63
 
43
64
  Live provider checks are useful before releases, but ordinary pull requests
44
65
  should stay deterministic. Run `npm run verify:release` for a full maintainer
@@ -52,9 +73,28 @@ checks.
52
73
  - Never make location lookup implicit.
53
74
  - Prefer clear terminal text over decorative filler.
54
75
  - Keep command-line and TUI behavior aligned.
76
+ - Put OS decisions in `src/platform`; keep capability availability separate from
77
+ runtime eligibility and recorded platform verification.
55
78
  - Add tests for parsing, storage, layout, or provider transformations when the
56
79
  behavior can be checked without live audio.
57
80
 
81
+ ## Platform verification
82
+
83
+ The required Node 22/24 CI matrix tests x64 and arm64 installations and real mpv
84
+ control. Weekly or manually triggered BSD checks execute the packed JavaScript
85
+ in guest kernels. Changes to script harnesses
86
+ also require `node --test scripts/packed-smoke.test-node.mjs scripts/install-smoke-mpv.test-node.mjs`.
87
+
88
+ Record OS release, CPU, endianness, libc, Node/npm versions, artifact hash, and
89
+ whether execution was native, virtualized, emulated, or mocked. An installation
90
+ test, native command mock, or foreign binary inspection alone cannot promote a
91
+ platform to supported. Follow the [support tiers](apps/docs/content/docs/platforms.mdx).
92
+
93
+ The deterministic visual fixtures cover full, compact, and micro layouts, all
94
+ major screens, and receiver styles. Preserve Unicode captures. When rendering
95
+ changes intentionally, describe the visible effect in the pull request and do
96
+ not update snapshots merely to hide failures.
97
+
58
98
  ## Issue Triage
59
99
 
60
100
  Playback issues should include station name, country, backend, and
package/README.md CHANGED
@@ -1,39 +1,70 @@
1
- ![RadioCLI Now Playing visualizer demo](apps/docs/public/demo/radiocli-now-playing.gif)
2
-
3
1
  # RadioCLI
4
2
 
5
- [![CI](https://github.com/Ciphore/RadioCLI/actions/workflows/ci.yml/badge.svg)](https://github.com/Ciphore/RadioCLI/actions/workflows/ci.yml)
3
+ RadioCLI is an open-source internet radio player with a full-screen terminal
4
+ interface and a scriptable CLI. Discover and stream stations from around the
5
+ world without leaving your terminal. No account. No cloud library.
6
+
7
+ [![CI](https://github.com/Ciphore/RadioCLI/actions/workflows/ci.yml/badge.svg?branch=master)](https://github.com/Ciphore/RadioCLI/actions/workflows/ci.yml)
6
8
  [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
7
9
  [![Node.js](https://img.shields.io/badge/node-%3E%3D22-brightgreen.svg)](package.json)
8
10
 
9
- RadioCLI brings live radio to your terminal. Browse stations around the world,
10
- save favorites, and listen through `mpv`—without an account or cloud library.
11
-
12
- Built with [Ink](https://github.com/vadimdemedes/ink),
13
- [React](https://react.dev/), and the
14
- [Radio Browser](https://api.radio-browser.info/) directory.
15
-
16
- ## Highlights
17
-
18
- - Discover stations through Explore, Search, Countries, or approximate-location Nearby.
19
- - Listen with a receiver-style Now Playing screen, live metadata, sleep timer, diagnostics, and selectable visualizers.
20
- - Keep favorites, recents, imports, track history, and listening stats on your machine.
21
- - Create one-time or recurring radio alarms from the TUI, with native background
22
- scheduling, station fallback, missed-run grace, snooze, and optional Alarm Guard.
23
- - Move through the exact station list you tuned from with previous and next controls.
24
- - Use `mpv` for complete playback control, with `ffplay` and VLC as limited fallbacks.
25
- - Resize freely: full, compact, and micro layouts preserve navigation and essential controls; Explore retains its interactive world map at every usable size.
11
+ ![RadioCLI playing SomaFM while cycling through terminal receiver styles](apps/docs/public/demo/radiocli-now-playing.gif)
12
+
13
+ ## Features
14
+
15
+ - **Station discovery:** Search by name or genre, filter by country, language,
16
+ codec, and bitrate, or browse country lists. The interactive world map uses a
17
+ cached station atlas to find broadcasts around the map cursor and sort them by
18
+ distance. Cached directory results remain available during provider outages.
19
+ - **63 receiver styles:** Switch between braille animation, ASCII geometry,
20
+ waves, fire, cityscapes, and the Gallop display without interrupting
21
+ playback. Color themes are selected independently. Receivers animate during
22
+ active playback and return to a zero-signal display when audio is inactive.
23
+ - **Listening stats:** A 52-week activity graph, listening time, session counts,
24
+ active days, streaks, and your most-listened station. Stats are recorded locally
25
+ across TUI and CLI listening sessions.
26
+ - **Alarms (beta):** One-time and recurring schedules with timezones, independent
27
+ volume, fade-in, fallback stations, snooze, and auto-stop. Native OS scheduling
28
+ allows alarms to run after the terminal closes. See the
29
+ [alarm guide](apps/docs/content/docs/alarms.mdx) for setup and power requirements.
30
+ - **Agent control:** An optional Model Context Protocol (MCP) server exposes
31
+ typed tools for discovery, playback, favorites, stats, alarms, AirPlay, and
32
+ appearance. Coding assistants can operate RadioCLI directly; `radiocli agent`
33
+ provides the same controls for other local tools.
34
+ - **Terminal support:** Full, compact, and micro layouts adapt to window resizing.
35
+ Keyboard, mouse, and trackpad controls work alongside Unicode and ASCII
36
+ rendering, reduced motion, screen-reader output, transparent backgrounds, and
37
+ limited-color or `NO_COLOR` environments. Offline browsing and low-bandwidth
38
+ modes are also supported.
39
+ - **Playback:** Pause, volume, mute, and live track metadata through `mpv`, with
40
+ configurable media keys and a sleep timer. Previous and next follow the station
41
+ list you tuned from. Track history and stream diagnostics are available in
42
+ the TUI.
43
+ - **Nearby stations:** Discover stations around an approximate location and
44
+ browse them by distance. Location lookup runs when you open Nearby and can be
45
+ disabled in Settings.
46
+ - **Local library:** Save favorites, revisit recent stations, and manage imports
47
+ in one place. Settings, track history, and listening data stay on your machine,
48
+ with JSON backup and restore. No account is required.
49
+ - **AirPlay (experimental):** Discover network receivers and switch audio output
50
+ from the TUI, including passcode entry when required. Availability depends on
51
+ the platform and receiver; see [supported setups](apps/docs/content/docs/platforms.mdx).
52
+ - **Custom stations:** Add direct HTTP(S) stream URLs with automatic ICY metadata
53
+ lookup. Import M3U, PLS, or XSPF playlists and export an M3U library.
54
+ - **Shell commands:** Start background playback by station name, save named
55
+ presets, and watch the current track from your prompt. Shell completion and
56
+ JSON or plain output support interactive use and scripting.
26
57
 
27
58
  ## Quick start
28
59
 
29
- macOS with Homebrew:
60
+ **Homebrew**
30
61
 
31
62
  ```bash
32
63
  brew install ciphore/tap/radiocli
33
64
  radiocli
34
65
  ```
35
66
 
36
- macOS, Linux, or Windows with npm:
67
+ **npm · Node.js 22 or newer**
37
68
 
38
69
  ```bash
39
70
  npm install -g @ciphore/radiocli
@@ -41,216 +72,84 @@ radiocli setup
41
72
  radiocli
42
73
  ```
43
74
 
44
- RadioCLI requires Node.js 22 or newer. The Homebrew formula installs `mpv` and
45
- FFmpeg. After an npm install, `radiocli setup` detects the operating system and
46
- package manager, lets you choose `mpv`, FFmpeg, and VLC, installs the selected
47
- native tools with branded progress feedback, and verifies playback readiness.
48
-
49
- See the [installation guide](apps/docs/content/docs/getting-started/install.mdx)
50
- for Windows, Linux distributions, AirPlay prerequisites, and fallback players.
75
+ Setup helps install the playback tools for your system. See
76
+ [installation](apps/docs/content/docs/getting-started/install.mdx) for other
77
+ routes and [platform support](apps/docs/content/docs/platforms.mdx) for
78
+ macOS, Linux, Windows, and BSD details.
51
79
 
52
- ## Visual tour
80
+ Launch `radiocli`, open Search or Explore, select a station, and press `Enter`
81
+ to start playback.
53
82
 
54
- These recordings come from the built TUI. Generate them locally with
55
- `npm run demo:assets`.
56
-
57
- ### Library
83
+ | Key | Action |
84
+ | --- | --- |
85
+ | `←` / `→` | Switch screens |
86
+ | `↑` / `↓`, then `Enter` | Select and tune a station |
87
+ | `space` | Pause or resume |
88
+ | `f` | Toggle a favorite |
89
+ | `v` / `t` | Change receiver style / color theme on Playing |
90
+ | `?` / `q` | Show shortcuts / quit |
58
91
 
59
- ![Favorites and recent stations in the RadioCLI Library](apps/docs/public/demo/radiocli-library.gif)
92
+ The footer shows controls for the current screen. See the
93
+ [controls guide](apps/docs/content/docs/getting-started/tui-controls.mdx) for
94
+ filters, station skipping, media keys, and the command palette.
60
95
 
61
- ### Explore
96
+ ## Screenshots
62
97
 
63
- ![World map discovery in RadioCLI Explore](apps/docs/public/demo/radiocli-explore-map.gif)
98
+ **Explore:** Move the map cursor with WASD or click a location to list stations
99
+ by distance.
64
100
 
65
- ### Search
101
+ ![Interactive world map and station discovery in RadioCLI](apps/docs/public/demo/radiocli-explore-map.gif)
66
102
 
67
- ![Station search results in RadioCLI](apps/docs/public/demo/radiocli-search.gif)
103
+ **Search:** Browse results with station names, countries, codecs, and bitrates.
68
104
 
69
- ### Nearby
105
+ ![Searching internet radio stations in the terminal](apps/docs/public/demo/radiocli-search.gif)
70
106
 
71
- ![Nearby stations in RadioCLI](apps/docs/public/demo/radiocli-nearby.gif)
107
+ **Library:** Switch between favorites, recent stations, and imported streams.
72
108
 
73
- ### Stats
109
+ ![Favorites and recent stations in the RadioCLI library](apps/docs/public/demo/radiocli-library.gif)
74
110
 
75
- ![Local listening stats with selectable display colors](apps/docs/public/demo/radiocli-stats-colors.gif)
111
+ **Nearby:** Browse stations around your approximate location.
76
112
 
77
- ## Essential controls
113
+ ![Nearby radio stations in RadioCLI](apps/docs/public/demo/radiocli-nearby.gif)
78
114
 
79
- | Key | Action |
80
- | --- | --- |
81
- | `←` / `→` or `Tab` / `Shift+Tab` | Switch screens |
82
- | `↑` / `↓` or `n` / `p` | Move the selection |
83
- | `Enter` | Open or tune the selection |
84
- | `space` or `F8` | Pause or resume with `mpv` |
85
- | `,` / `.` or `F7` / `F9` | Previous or next station |
86
- | `+` / `-` | Change volume |
87
- | `f` | Save or remove a favorite |
88
- | `?` | Open all shortcuts and commands |
89
- | `q` or `Ctrl+C` twice | Quit cleanly |
90
-
91
- The footer always shows controls for the current screen. Press `:` to open the
92
- command palette. The [TUI controls guide](apps/docs/content/docs/getting-started/tui-controls.mdx)
93
- covers filters, playback, media-key learning, AirPlay, and every command.
94
-
95
- ## CLI
96
-
97
- RadioCLI can also be controlled by local coding agents. Run `radiocli setup`
98
- and opt into MCP, or use `radiocli setup --mcp`, to configure detected Codex,
99
- Claude, OpenCode, Cursor, Gemini, VS Code/Copilot, and Orca-backed runtimes
100
- automatically. From the TUI, open **Settings → Agent control & MCP** and turn on
101
- **Allow local agent control** for the same one-step setup—no terminal command is
102
- required. The same actions are
103
- available to non-MCP harnesses through `radiocli agent` and `radiocli alarm`:
104
- search and play stations, browse recents/favorites/nearby stations, favorite the
105
- current station, inspect listening stats, create and control alarms, control
106
- macOS AirPlay, change the receiver look, or run a user-configured completion
107
- preset. Codex Voice can invoke those same typed MCP tools. Agent playback opens
108
- the normal RadioCLI TUI in a terminal window by default on macOS, Windows, and
109
- Linux. Interactive setup explains that macOS may require the agent host to approve
110
- a one-time Automation prompt; users can explicitly opt into headless playback.
111
- Scheduled alarms remain isolated and always use local output rather than
112
- unattended AirPlay. See the
113
- [CLI guide](apps/docs/content/docs/getting-started/cli.mdx#local-agent-and-mcp-control).
115
+ **Stats:** Review listening activity and totals, with selectable display colors.
114
116
 
115
- ```bash
116
- radiocli # Start the TUI
117
- radiocli check # Check providers, playback tools, and the local store
118
- radiocli doctor --json # Create a redacted support report
119
- radiocli search "japan hits"
120
- radiocli countries
121
- radiocli import stations.m3u
122
- radiocli export favorites.m3u
123
- radiocli add-url <stream-url> [station name]
124
- radiocli alarm list
125
- radiocli alarm doctor
126
- radiocli update --install # Upgrade and repair enabled MCP registrations
127
- ```
117
+ ![Listening stats and the 52-week activity graph with selectable colors](apps/docs/public/demo/radiocli-stats-colors.gif)
128
118
 
129
- Existing installations keep their library and preferences when upgraded. Use
130
- `radiocli update` to inspect the detected Homebrew, npm, pnpm, or Bun command,
131
- or `radiocli update --install` to run it. MCP registrations use an
132
- upgrade-stable launcher so versioned package paths do not break them. On
133
- Windows this is a shell-free Node command; on Unix it uses the `radiocli` shim.
134
- Run `radiocli mcp status` to inspect registrations and `radiocli mcp repair`
135
- after moving an installation or when an agent client reports a stale server;
136
- fully quit and reopen agent clients after enabling, repairing, or upgrading.
137
- Until that restart, even a newly created task in an already-running client will
138
- not have RadioCLI's tools and may incorrectly fall back to browser playback.
139
-
140
- RadioCLI imports `.m3u`, `.pls`, and `.xspf` playlists. It exports favorites
141
- and imported streams as `.m3u`.
142
-
143
- Alarms are experimental beta functionality and live under **Overview**,
144
- immediately before Settings. Saving an enabled
145
- alarm registers it with launchd on macOS, a systemd user timer on Linux, or Task
146
- Scheduler on Windows, so the terminal does not need to remain open. When it
147
- fires, RadioCLI reopens the saved supported terminal and shows the ringing
148
- screen. Enter transfers the station into normal interactive playback; Space
149
- stops it and snoozes for 10 minutes. If a
150
- RadioCLI TUI is already open, that instance shows the controls instead. The
151
- computer must still be powered on with a logged-in interactive audio session; wake timing
152
- depends on hardware and OS power policy. See the [CLI guide](apps/docs/content/docs/getting-started/cli.mdx)
153
- and [reliability notes](apps/docs/content/docs/reliability.mdx) before relying on
154
- an alarm for something critical. Use a secondary device as the primary alarm
155
- for safety-critical, medical, travel, or emergency timing. See the dedicated
156
- [Alarms guide](apps/docs/content/docs/alarms.mdx) for the full workflow.
157
-
158
- The **Verify alarm setup** row performs a disposable native-scheduler
159
- registration, an authenticated terminal/control handshake, sleep-inhibitor and
160
- system-volume checks, and a short sample from the next configured alarm. It
161
- cleans up the temporary job and reports hard blockers separately from hardware-
162
- or policy-dependent wake limitations.
163
-
164
- See the [CLI guide](apps/docs/content/docs/getting-started/cli.mdx) for all
165
- arguments and examples.
166
-
167
- ## Playback and reliability
168
-
169
- RadioCLI prefers `mpv` because it handles redirects, HLS, real-world codecs,
170
- ICY metadata, and interactive controls reliably. `ffplay` and VLC can keep a
171
- stream playing when `mpv` is unavailable, but the UI labels their controls as
172
- limited.
173
-
174
- Station providers use mirror fallback, bounded caches, and stale-cache recovery.
175
- Playback waits for backend readiness, applies tune timeouts, and can skip broken
176
- streams. Corrupt library and cache files are backed up instead of silently
177
- overwritten.
178
-
179
- Scheduled playback retries the primary station once, then tries an optional
180
- fallback. A missed-run grace window controls catch-up after sleep or logout.
181
- True fade-in requires `mpv`; `ffplay` and VLC start audibly at the configured
182
- target volume. Scheduled alarms always use local speakers, never unattended
183
- AirPlay.
184
-
185
- On macOS, an npm or source installation is executed by Node, so System Settings
186
- may identify its background item as `node`. Showing RadioCLI as the providing
187
- application requires a future signed macOS app bundle with a bundled helper;
188
- changing a launchd label cannot safely relabel the executable.
189
-
190
- Read the [reliability notes](apps/docs/content/docs/reliability.mdx) for failure
191
- handling and troubleshooting.
192
-
193
- ## Privacy
194
-
195
- RadioCLI does not require an account, proxy audio, or upload your listening
196
- history. Favorites, recents, imports, settings, alarms, track history, and
197
- activity stay in a local JSON library. Full JSON library backups include alarm
198
- definitions, while native scheduler registrations, runtime health, Alarm Guard
199
- state, and authenticated loopback-control tokens remain machine-local.
200
-
201
- Nearby contacts `ipapi.co` only when you open that screen, then uses an
202
- approximate location to sort the local station atlas. Disable the lookup with
203
- `l`, Settings, or `:location off`.
204
-
205
- Favoriting a Radio Browser station sends a best-effort public directory vote by
206
- default. Turn off **Share favorite votes with Radio Browser** in Settings to
207
- keep favorites local-only.
208
-
209
- See [Privacy and security](apps/docs/content/docs/privacy-security.mdx) for the
210
- complete data-flow description.
211
-
212
- ## Project structure
213
-
214
- - `src/ui` — screens, input, layout, and terminal rendering
215
- - `src/providers` — station directories, resolution, and caches
216
- - `src/player` — playback backends, metadata, and AirPlay
217
- - `src/alarms` — schedules, native registration, Alarm Guard, and active controls
218
- - `src/storage` — local library persistence and migration
219
- - `apps/docs` — documentation website and manual
220
-
221
- More detail lives in the [architecture guide](apps/docs/content/docs/architecture.mdx)
222
- and [design notes](apps/docs/content/docs/design.mdx).
223
-
224
- ## Development
119
+ ## CLI and agent control
225
120
 
226
121
  ```bash
227
- git clone https://github.com/Ciphore/RadioCLI.git
228
- cd RadioCLI
229
- npm ci
230
- npm run verify
231
- npm run dev
122
+ radiocli play jazz
123
+ radiocli now
124
+ radiocli favorite
125
+ radiocli stop
232
126
  ```
233
127
 
234
- `npm run verify` checks types, lint, tests, the production build, and package
235
- contents. Playback and live-data smoke tests are available separately because
236
- they contact public services or start a local player.
237
-
238
- ## Contributing
128
+ `play` starts background playback and returns to your prompt. If the TUI is
129
+ already open, commands control its player instead. Both interfaces use the same
130
+ library, metadata, and listening history. Use `radiocli help` for common commands
131
+ or `radiocli help --all` for the full reference.
239
132
 
240
- Contributions are welcome. Start with [CONTRIBUTING.md](CONTRIBUTING.md), and
241
- include `radiocli check` output with playback reports.
133
+ Run `radiocli setup --mcp` to configure the optional local MCP integration for
134
+ coding assistants. Ordinary CLI playback does not require MCP setup. The
135
+ [CLI and agent guide](apps/docs/content/docs/getting-started/cli.mdx) covers
136
+ commands, presets, shell completion, and integration details.
242
137
 
243
138
  ## Documentation
244
139
 
245
- - [Getting started](apps/docs/content/docs/index.mdx)
246
- - [Installation](apps/docs/content/docs/getting-started/install.mdx)
247
- - [Controls](apps/docs/content/docs/getting-started/tui-controls.mdx)
248
- - [Architecture](apps/docs/content/docs/architecture.mdx)
249
- - [Roadmap](apps/docs/content/docs/roadmap.mdx)
250
- - [Release packaging](apps/docs/content/docs/release-packaging.mdx)
140
+ [Getting started](apps/docs/content/docs/index.mdx) ·
141
+ [Controls](apps/docs/content/docs/getting-started/tui-controls.mdx) ·
142
+ [Alarms](apps/docs/content/docs/alarms.mdx) ·
143
+ [Troubleshooting](apps/docs/content/docs/troubleshooting.mdx) ·
144
+ [Architecture](apps/docs/content/docs/architecture.mdx)
145
+
146
+ Your library and listening history stay on your machine. Read
147
+ [Privacy and security](apps/docs/content/docs/privacy-security.mdx) for the
148
+ network requests and data flow.
251
149
 
252
- Run the documentation site locally with `npm run docs:dev`.
150
+ Want to contribute? [CONTRIBUTING.md](CONTRIBUTING.md) covers development and
151
+ checks. RadioCLI is [MIT licensed](LICENSE).
253
152
 
254
- ## License
153
+ ---
255
154
 
256
- [MIT](LICENSE)
155
+ ![Radio on internet, from Silicon Valley](apps/docs/public/demo/silicon-valley-radio-on-internet.gif)
package/SECURITY.md CHANGED
@@ -24,10 +24,32 @@ information, or unexpected command execution.
24
24
  - The app stores recents, favorites, settings, imports, and provider cache data
25
25
  locally under the user data directory.
26
26
  - RadioCLI does not proxy audio. It resolves public stream URLs and hands
27
- playback to `mpv` or `ffplay`.
27
+ playback to native players.
28
28
  - Favoriting a Radio Browser station sends a best-effort vote to that public
29
29
  directory by default; the Settings screen can disable vote sharing.
30
30
 
31
+ ## Stream Certificate Verification
32
+
33
+ RadioCLI enables mpv TLS verification, including redirected and nested streams,
34
+ and enables TLS verification for direct FFmpeg/ffplay network media. Native
35
+ trust stores and player certificate configuration apply. It never retries an
36
+ HTTPS input with certificate verification disabled.
37
+
38
+ FFmpeg releases in circulation do not propagate TLS policy to every resource
39
+ opened by network playlist demuxers. Those inputs are restricted in FFmpeg
40
+ fallbacks: use mpv for HLS/DASH/IMF playback, or a direct audio stream for AirPlay.
41
+ Local FFmpeg inputs cannot open network protocols. The plain HTTP compatibility
42
+ retry explicitly blocks both HTTPS and TLS, including changed redirects.
43
+
44
+ Known upstream limitation: tested FFmpeg/OpenSSL builds can accept a trusted
45
+ certificate with a mismatched **numeric IP address**, even with verification
46
+ enabled. This also affects mpv builds using that native TLS implementation.
47
+ DNS hostname mismatch fixtures are rejected. Prefer DNS station URLs. A
48
+ separate Node preflight would not secure the player's actual connection, so
49
+ RadioCLI does not present one as a fix. See the
50
+ [reliability reference](apps/docs/content/docs/reliability.mdx#playback-recovery-and-secure-streams)
51
+ and native smoke results for the precise guarantees and remaining limits.
52
+
31
53
  ## Supported Versions
32
54
 
33
55
  Until a tagged release cadence is established, security fixes target the active