~/audio/cliamp

cliamp

A full music player that lives in your terminal. No browser tab required.

Playlists, a 10-band equalizer, 31 visualizers, synced lyrics, podcasts, remote control, and Lua plugins. Stream from Spotify, Qobuz, Tidal, YouTube Music, Plex, Jellyfin, Emby, Navidrome, Lyrion, Yandex Music — plus podcast feeds and about 58,000 internet radio stations.

Linux · macOS · Windows Android ↗ cliamp mobile MIT licensed Go 1.26
$ cliamp --provider radioplays live in your browser
tty1 C L I A M P
♫Lofi
pick a station below and press play
00:00 ■ stopped live stream
EQ [Rock]
SRC [Radio] 1/14
▸─ Playlist[Shuffle: Off][Repeat: All]
$ cliamp https://radio.cliamp.stream/lofi/stream.plsspace · < >

Install

One line. Click any command to copy it.

then just run cliamp — cliamp setup walks you through streaming services and media servers. Optional: ffmpeg for AAC, ALAC, Opus and WMA, yt-dlp for YouTube, SoundCloud, Mixcloud, Bandcamp, Bilibili and NetEase. Windows builds are in Releases.

Every source, one interface

Streaming services, self-hosted libraries, local files, podcasts, and radio — all through the same playlist, EQ, visualizer, and lyrics pipeline.

Radio favorites follow the station: press f in Catalog, search results, or the playback playlist after browsing countries or genres. Stations are saved locally under Radio → Favorites by URL, using the station name rather than the current song and retaining station details, including the region, after restart. The header’s star badge counts all starred rows, including offscreen rows, with the same meaning as the row markers. Radio favorites do not reserve a star column in playlists containing no favorited stations. M3U/PLS wrappers keep their original station URL after playback resolution. Toggling a favorite preserves the selected station and completed catalog pages, including during loading. Favoriting does not fetch more catalog stations or interrupt an in-progress station load. IPC clients use the stable URL-based favorite IDs returned by provider.playlists; positional favorite IDs are not supported. On Linux and macOS, favorite mutations preserve other cliamp instances’ changes through a shared file lock. The action follows the displayed star: it favorites an unstarred station or unfavorites a starred station, without reversing the same change already made by another instance. Other instances’ changes become visible in another open player on its next favorite mutation or restart, not through live refresh. Windows assumes one writer per config directory. Press f again to remove one. In saved local playlists, f still bookmarks the track; n remains the separate heart favorite, available when the playback playlist has focus. Remote account favorites are unchanged. Radio favorites guide.

Choose where TUI Ctrl+S saves yt-dlp downloads and temporary audio files: set directory = "/media/usb/CLAPt/Music" under [downloads] in config.toml and restart cliamp. Empty uses ~/Music/cliamp. Relative paths are rejected (literal ~ is not expanded). Mount external drives first; missing directories are created without checking mount status. The setting also applies to IPC Save in the TUI; headless daemon saving is unchanged. Saved files can be opened locally and are not automatically substituted into online playlists.

Navidrome uses the player's transcoding settings, or streams the original file if none are configured. Set format = "raw" under [navidrome] to always request the original. Navidrome guide.

With Jellyfin as the default provider, reopen cliamp without files, URLs, or a playlist to restore the last track, position, and complete source list. Queued tracks keep their own album context. Press Enter to resume; restored sessions stay silent even with auto_play. Playback is checkpointed every two seconds and on normal exit, without saving unfinished seeks. Stream URLs use current API-key or password authentication when playback starts. Jellyfin guide.

Large Spotify playlists fill in as they load: the first tracks appear right away, later pages append in the background, and playback works while the list is still arriving. Spotify guide.

What's inside

10-BAND EQ

Parametric equalizer with 14 presets — Rock, Jazz, Classical, Bass Boost, Vocal, Podcast and more — or dial in your own curve. The Custom preset survives restarts.

VISUALIZERS

31 built-in modes rendered in the terminal from live FFT data: spectrum bars, scope, wave, matrix, flame, and a true-stereo LED peak meter. ClassicPeak uses smooth bars and floating peak caps, with sampling aligned to audible playback and adaptive redraws for smooth motion. Neighboring bands are averaged into each bar. v cycles, V goes full screen.

SYNCED LYRICS

Embedded LRC first, then Spotify for signed-in Spotify tracks, with LRCLIB and NetEase fallback. Time-aligned lines scroll with song playback; fine-tune timing with [/] if a source is slightly off. Live radio refreshes on every ICY track change and uses manual scrolling, even with timestamped lyrics. Press y.

PLAYLISTS & QUEUE

TOML playlists with live [[dir]] folder sources, M3U/M3U8/PLS import and export, cross-playlist favorites, a play-next queue that reads like the playlist and toggles in place with A, saved playlists you can append to what is playing or put the current track at the front of, and undo.

REMOTE CONTROL

Newline-delimited JSON over a local Unix socket, with full state snapshots and push events for scripts, status bars, and GUIs. Media keys via MPRIS on Linux and Now Playing on macOS. Run --daemon for headless playback.

THEMES

22 built-in color schemes that pass contrast checks — catppuccin, dracula, gruvbox, nord, tokyo-night, winamp and more — or drop a TOML file in ~/.config/cliamp/themes. Press t.

PODCASTS

Apple's top charts and 19 genre categories, or any RSS feed. Browse episodes, subscribe locally with f, and, with ffmpeg installed, seek anywhere in an episode; the real length is measured from the file, not the feed. Episodes resume where you left off and are ticked once finished. F lists your subscriptions and pulls the newest episode of any show, or of all of them, without replacing the queue. No account or API key.

GAPLESS & STREAMS

Preloads the next track for seamless transitions. Plays URLs, HLS (.m3u8) and internet radio with jitter buffering and live ICY metadata, and cliamp:// links from a browser or chat.

cliamp radio

Fourteen channels we run ourselves — always on, no account. Play any of them in the player above, or pipe the URL straight into cliamp or any player of your choice. In cliamp, a channel with a song library opens as a playlist of its songs.

read the radio docs ↗

Who's listening right now

Live connections to the cliamp radio channels and their playlists, by country. Drag the globe to spin it, or hover a country for its count.

–
LISTENERS
–
ON PLAYLISTS
–
COUNTRIES

$ cliamp radio --stats --globe● live
TOP COUNTRIESLISTENERS

Keyboard first

Everything is one keystroke away — no mouse, no menus. Vim-style j/k movement, Tab cycles the controls, and ? or Ctrl+K shows the full keymap for the screen you are on. All keybindings ↗

Extend it with Lua

Hook playback events, add commands and key bindings, scrobble, post to a status bar, or draw a visualizer — plugins drop into ~/.config/cliamp/plugins/ and run in sandboxed Lua 5.1 VMs. A crashing plugin never takes the player down.

plugins/now-playing.lua
-- write the current track for Waybar, Polybar, tmux…
local p = plugin.register({
    name = "now-playing",
    type = "hook",
})

p:on("track.change", function(track)
    cliamp.fs.write("/tmp/cliamp-now-playing",
        track.artist .. " - " .. track.title)
end)
track.change · playback.state · queue.end
Twelve events to subscribe to: track changes, scrobbles, seeks, volume, EQ, shuffle and repeat, queue edits, end of queue, explicit stops, start and quit. Track-change events fire after playback starts successfully, including YouTube, SoundCloud, and gapless transitions. Buffering, failed, or superseded starts do not emit a track change. End-of-queue events report the last track that started playing; a manual stop, a stream still buffering, or a failed start does not emit one. Ask cliamp.track.is_live() before treating a track as one that ends.
cliamp.queue.has_next()
Reports whether another playable track exists, honoring the play-next queue, repeat, and shuffle.
cliamp.queue.add({ path, title, artist, … })
Queue a track exactly as described, such as a Spotify track with its title and artist, without resolving its path.
p:bind("ctrl+n", fn) · p:command("name", fn)
Register your own key bindings and shell-invokable commands.
cliamp.http · cliamp.fs · cliamp.store · cliamp.timer
Talk to any API, write files for status bars, persist state and schedule work — inside a sandbox with declared permissions.
type = "visualizer" → p:render(bands, frame, rows, cols)
Draw your own visualizer from the live spectrum bands. Plugin API reference ↗
COMMUNITY PLUGINScliamp plugins install user/cliamp-plugin-name

Close the tab. Play the music.

star on github