plavno
A lightweight TUI player for Linux, macOS and Windows with music streams from popular services, library shuffle, and mouse controls.
Features · Quick start · Services · Controls
Features
- Media controls — media keys and system playback controls on Linux, macOS and Windows, with track information, album artwork, playback position and speed.
- Service waves and shuffle — Yandex My Vibe, VK recommendations, library shuffle, and Wave Shuffle across connected services.
- Likes and dislikes — like/unlike in Yandex, VK or YouTube Music, exclude unwanted tracks, and undo dislikes.
- Mouse and hotkeys — click controls, drag to seek, scroll for volume, and select track text to copy.
- Listening history — search past plays by title or artist and replay tracks.
- RAM buffering and prefetch — start playback while downloading; cache adjacent tracks for seeking and replay.
- Audio-reactive visuals — an animated wave with album artwork, toggled with
v.
Quick start
macOS
Install with Homebrew:
This installs the player and both service helpers. Alternatively, download the
*-macos-aarch64.tar.gz (Apple Silicon) or *-macos-x86_64.tar.gz (Intel) archive from
GitHub Releases and put all
two executables together. Run ./plavno, or add the directory to PATH.
Linux
Download the *-linux-x86_64-gnu.tar.gz or *-linux-aarch64-gnu.tar.gz archive from
GitHub Releases. Extract it
and keep plavno and plavno-spotify together. Run ./plavno,
or put all three in a directory on PATH, such as ~/.local/bin.
Requires glibc 2.35+, ALSA and D-Bus. Install the runtime packages for your distribution:
# Debian / Ubuntu (on newer Ubuntu releases, use libasound2t64 instead of libasound2)
# Fedora
# Arch Linux
Audio uses the ALSA default device; PipeWire/PulseAudio needs its ALSA plugin
(for example pipewire-alsa or pulseaudio-alsa on Arch). A desktop D-Bus session
enables media keys and Now Playing. Alpine/musl requires a separate source build.
Windows
On Windows 10/11 x64, download the *-windows-x86_64-msvc.zip archive from
GitHub Releases. Extract it,
keeping plavno.exe and plavno-spotify.exe together.
Add the extracted folder to your user PATH and open a new Windows Terminal.
Connect and play
Connect a service using the instructions below, then start playback
with plavno --source SOURCE. For local music, run plavno local /path/to/music,
then plavno --source local.
Install ffmpeg and make it available on PATH for HLS playback and conversion of
formats such as YouTube Opus/WebM. YouTube also needs yt-dlp installed separately. Browser-based
service sign-in needs Chrome/Chromium, or Edge on Windows. These external programs
are not included in the archives. On macOS, use brew install ffmpeg.
PLAVNO_FFMPEG and PLAVNO_BROWSER override their paths.
Services
| Service | Source key | Stable | Playback | Connection |
|---|---|---|---|---|
| Yandex Music | yandex |
🟢 | My Vibe, favorites (shuffle or newest first), flow presets | OAuth token; full tracks require account access / Yandex Plus |
| VK Music | vk |
🟢 | Recommendations, My Music shuffle, flow presets | Installed Chrome/Chromium or manual session import |
| SoundCloud | soundcloud |
— | Track stations | Browser sign-in or a public seed track |
| Spotify | spotify |
— | Track radio | Optional Rust helper; Premium and OAuth |
| YouTube Music | ytmusic |
— | Home mixes, mood playlists, track radio and Liked Music shuffle | External yt-dlp; cookies or a public seed |
| Local music | local |
— | Recursive directory shuffle | A local music directory |
Yandex Music
Get an OAuth token from the token guide, paste it
into plavno login yandex, then run plavno --source yandex.
VK Music
Run plavno login vk and sign in through installed Chrome/Chromium, then run
plavno --source vk. Alternatively, import a session manually
with plavno login vk --manual.
SoundCloud
Run plavno login soundcloud, sign in through Chrome/Chromium, and choose a
seed track when prompted. Start with plavno --source soundcloud.
Use plavno --source soundcloud --seed TRACK_URL for a one-time public station
or to override the saved seed for this run.
Manual setup also supports public track stations.
Spotify
Run plavno login spotify and paste a JSON profile with an OAuth token with
streaming scope and client ID. Premium is required. Start with
plavno --source spotify --seed spotify:track:TRACK_ID.
A saved profile seed is also supported; --seed overrides it for this run.
YouTube Music
Install yt-dlp separately and make it
available on PATH. On Debian/Ubuntu, run sudo apt install yt-dlp; on macOS,
run brew install yt-dlp. It is optional and is not bundled with plavno.
For full YouTube support, yt-dlp also needs yt-dlp-ejs and a JavaScript runtime:
Node.js 22+ or Deno 2.3+. plavno enables Node.js alongside yt-dlp's default Deno
support; install the runtime separately and put it on PATH.
For public track radio, no login is needed:
For personal mixes, run plavno login ytmusic and paste
{"cookies":"/absolute/path/youtube-cookies.txt"} using a Netscape cookie export,
then start with plavno --source ytmusic.
--seed uses any saved credentials and overrides the saved seed or mix for this
run without changing the profile. Live streams are not supported.
With signed-in cookies, l toggles the track's YouTube like. Press f to shuffle
YouTube Music's Liked Music, or start with plavno --source ytmusic --favorites.
This uses the music playlist, rather than YouTube's general Liked videos list.
Press w to return to radio. Likes also work for YouTube tracks in mixed.
Homebrew and release archives include the Spotify helper. Cargo installations need separate helper builds. See service setup for profile examples and troubleshooting.
Run
Controls
Buttons display their hotkeys and support mouse clicks. Hold Shift to replace
f Favorites with F Newest first. Windows uses native console key events;
on Linux and macOS, modifier reporting requires the Kitty keyboard protocol
(for example, foot, Ghostty, or iTerm2).
| Key | Action |
|---|---|
| Space / x | Pause or resume / stop |
| p / n | Previous / next track |
| ← / → | Seek 5 seconds; Shift or Ctrl: 30 seconds |
| Home / End | Start / end of track |
| + / - | Volume; also click beside the percentage |
| [ / ] | Playback speed: 0.1–2x, step 0.05; click buttons or scroll over Speed |
| l | Like / unlike in Yandex, VK or YouTube Music |
| d / u | Dislike and skip / undo dislike |
| h or / | History: type to search, ↑/↓ select, Enter play |
| s / m | Choose a service / mix service waves |
| w / f | New wave / library shuffle (VK: My Music) |
| Shift+F | Favorites in order, most recently added first (Yandex, VK, YouTube Music) |
| g | Flow: Calm, Balanced, Energetic, Work; choose with 1–4 or a click |
| v | Toggle visualization |
| b | Toggle a dancing silhouette over the wave; --dance starts with both |
| Ctrl+C | Copy selected text; quit when nothing is selected |
| Esc / q | Clear selection or close a view / quit |
Use --dance for a continuous, audio-reactive silhouette drawn in the same Braille
style as the wave, which stays visible. The prototype blends free-flowing gestures,
weight-shifting groove, and sharper pulse accents based on rhythm and energy.
Variable phrases mix club footwork, torso accents, stage travel, crouches, and jumps.
A 3D skeleton turns the body and head; projected limbs shorten naturally, with
depth-based occlusion in the CPU Braille renderer.
Track changes retain the pose and blend into the next movement character. Strong beats drive
body impulses; overcommitted moves can lead to a recovery step or a rare fall.
Subtle rim lighting and small face details help the figure stand out over album art.
auto mixes house-inspired footwork, hip-hop rocks, and rave-inspired steps using
tempo, energy, and available genre metadata (Yandex/SoundCloud). Ambient favors Flow.
Compare with --dance-style house, hiphop, or rave; flow, groove, and pulse
remain available as basic movement profiles.
--renderer auto and --renderer braille select terminal dots. To compare native
pixels in foot: plavno --dance-style flow --renderer sixel. The wave stays in
Braille; sixel draws the dancer over it. Run directly in the terminal if a
multiplexer hides its pixel dimensions.
Sixel uses a detailed violet-jacket skin; --dance-skin silhouette selects the
previous look. See dance rendering for the original pose sheet.
Sixel defaults to --sixel-update diff, restoring and redrawing only the changed
region. Use --sixel-update full to clear and repaint each frame instead.
Sixel requires a compatible terminal; the default braille renderer works without it.
Hover over the album artwork: the left third plays the previous track, the center toggles playback, and the right third plays the next track. Click the progress bar to jump, or drag it for audible 2–4x scrubbing. Scroll over the bar to seek, over Speed to change the rate, and elsewhere to change volume. Drag over the title or artist and press Ctrl+C to copy (requires terminal OSC 52 support). In History and Sources, click to select, double-click to play, scroll to navigate, and right-click to close.
Flow changes recommendations. Work requests calm ambient without vocals on Yandex
and calm instrumental tracks on VK. w returns from library shuffle to a new wave;
VK filters recent tracks to avoid repeating the initial queue.
With signed-in YouTube cookies and no --seed, Flow selects YouTube Music's Chill
(Calm), Energize (Energetic), or Focus (Work) playlists. Focus can include vocals.
Balanced returns to the usual personal mix or configured seed/playlist.
Flow also works in Wave Shuffle: it changes supported sources, while other sources,
including local music, keep playing their full libraries without mood filtering.
Local music discovers MP3, FLAC, M4A/MP4, and Ogg Vorbis files recursively in the
background, visiting subdirectories in random order. Playback can start before
discovery finishes; the first tracks depend on which files have been discovered.
Tracks shuffle without repeats within a pass, then start a new pass without an
immediate boundary repeat when more than one playable track is available. Symlinks
are skipped. Files that cannot be opened or recognized are skipped when preparing
the queue. Titles and artists come from embedded tags, with filenames used when
the title is missing or blank. Embedded cover art is displayed in the TUI;
duration comes from the audio header. Tags are read only for queued tracks.
Press w to rescan and start a new shuffle. The file list stays in RAM; only the
configured directory is saved in ~/.config/plavno/local.json.
Playback and data
Playback starts while downloading, at the highest available supported quality. Previous, current, and next audio files stay in RAM for seeking and replay; RAM use depends on track size. Service audio is not saved to disk.
Configuration lives in ~/.config/plavno; history and permanent dislikes live in
~/.local/state/plavno. On Windows, settings and tokens use %APPDATA%\plavno,
while history and caches use %LOCALAPPDATA%\plavno; private directories use a
protected user ACL. XDG_CONFIG_HOME, XDG_STATE_HOME and XDG_CACHE_HOME
override the corresponding roots on all platforms.
History stores metadata for the last 2000 plays. Yandex and VK also receive account
dislikes; u undoes them. Volume starts at 100%, speed at 1x. Changing speed also
changes pitch.
On Linux, media keys and playerctl work through session D-Bus, for example:
playerctl -p plavno play-pause or playerctl -p plavno position 5+.
Build from source
Install Rust and the build dependencies for your OS:
- Linux:
libasound2-dev libdbus-1-devon Debian/Ubuntu, oralsa-lib-devel dbus-develon Fedora. - macOS: Xcode Command Line Tools (
xcode-select --install). - Windows: the Rust MSVC toolchain and Visual Studio Build Tools with Desktop development with C++.
Install the player from crates.io:
Or run cargo build --release from a checkout. The executable is
target/release/plavno (target\release\plavno.exe on Windows).
Build the Spotify helper separately using the
service setup instructions.
For development, use cargo run or cargo check and keep the build cache.
Checks
CI checks the player and Spotify helper on Linux, macOS 15 (Apple Silicon and
Intel), and Windows Server 2025. Windows tests exercise native SMTC, ConPTY,
private ACLs, the Chrome pipe protocol and streamed audio.
cargo test --locked --features test-audio also runs the PTY UI tests on macOS
without a physical output device. Unit tests use a software audio sink; the
test-audio feature enables that sink in the test executable only when
PLAVNO_TEST_AUDIO=1 is set. Normal builds use the platform's audio device.
Release steps: Publishing to crates.io.