a terminal-based radio player for discovering new music through human-curated live streams. hop between stations, automatically log every song, and break the algorithm's hold on your musical taste.
- 🎶 instant station switching: seamlessly hop between stations with smooth audio crossfades
- 📝 interactive curation: review stations with rich metadata and save only the best
- 🎛️ first-run wizard: guided setup fetches fresh stations based on your favorite genres
- 📊 rich metadata display: see bitrate, country, tags, and ratings during curation
- 🔍 advanced discovery: fetch stations by genre and curate them interactively
- 📋 multi-panel UI: stations, now playing, and history in a clean ncurses interface
- ⚡ performance modes: Balanced, Performance, and Focus modes for different usage scenarios
- 🤖 auto-hop discovery: let the app cycle through stations for passive discovery
- 💾 persistent favorites: mark favorite stations saved between sessions
- 🔄 multi-url fallbacks: cycle between backup streams with
+ - 🖥️ responsive TUI: adapts to terminal size with compact and full layouts
you'll need a C++17 compiler, make, pkg-config, and the development libraries for libmpv and ncurses.
| distribution | installation command |
|---|---|
| Debian/Ubuntu | sudo apt install build-essential libmpv-dev libncursesw5-dev pkg-config |
| Fedora/RHEL | sudo dnf install gcc-c++ mpv-devel ncurses-devel pkg-config make |
| Arch Linux | sudo pacman -S gcc make pkg-config mpv ncurses |
- compile the project
make
- run the application
./build/stream-hopper
New users will be guided through first-run setup to create a personalized station list.
| key | action |
|---|---|
↑/↓ |
navigate stations / scroll history |
⏎ |
mute/unmute current station |
a |
toggle auto-hop mode |
p |
cycle performance profiles |
f |
toggle favorite for current station |
d |
toggle audio ducking (lower volume) |
+ |
cycle to next stream url for station |
⇥ |
switch focus between panels |
c |
enter copy mode (pause ui for selection) |
q |
quit |
| key | action |
|---|---|
k |
keep station in final list |
d |
discard station |
p |
play/pause current station |
q |
save and exit curation |
stations.jsonc: Your main station list (generated by first-run wizard)[genre].jsonc: Curated station lists (e.g.,techno.jsonc)radio_history.json: Timestamped listening historyradio_favorites.json: Your favorited stationsradio_session.json: Remembers last played station
example stations.jsonc with rich metadata:
- modern architecture: actor model with unidirectional data flow
- audio engine: libmpv with optimized streaming configuration
- ui framework: ncursesw with full unicode/emoji support
- concurrency: std::atomic, mutexes, and condition variables
- error handling: comprehensive exception safety
- static analysis: clean reports from cppcheck and flawfinder
- radio browser api - for comprehensive station data
- libmpv - robust media playback engine
- ncurses - terminal UI foundation
- nlohmann/json - JSON persistence
- AI collaboration: the architecture, code, and documentation were heavily shaped through conversation with large language models, primarily Gemini 2.5 Pro and Claude 4 Sonnet.
- all the radio stations - for keeping real, human-curated music alive.
this project is licensed under the Mozilla Public License 2.0 (MPL-2.0).
the algorithm knows what you liked yesterday. radio knows what you'll love tomorrow.
