Terminal Music Player · Winamp for your shell

Playlists, EQ, visualizers, lyrics, remote control, and a Lua plugin system. Streams from Spotify, YouTube Music, NetEase, Plex, Jellyfin, Emby, Navidrome, and 30,000+ radio stations.

$ cliamp --provider radio tty1
C L I A M P [Playlist]
Lofi Hip Hop Radio
00:00 / 00:00 ■ Stopped (click to play) ◌ Buffering… ● Streaming


        
━━━━━━━━━━━━━━━━━━━━ STREAMING ━━━━━━━━━━━━━━━━━━━━
EQ [Rock] +5 +4 +2 -1 -2 +2 +4 +5 +5 +5 VOL +0dB
SRC [Local] [Navidrome] [Plex] [Jellyfin] [Emby] [Spotify] [YouTube] [YT Music]
▸─ Playlist ── [Shuffle] [Repeat: Off] [1/3] ──
▶ 1. Lofi Hip Hop Radio
  2. EDM Pulse
  3. Synthwave Nights
↑↓ Scroll Enter Play Spc ▶❚❚ * Fav Tab Focus ? Keys
SPD [1x] ↓ 0.7 MB  32 KB/s
$ cliamp https://radio.cliamp.stream/lofi/stream.pls
01 demo.mp4
02 install.sh
Direct
$ curl -fsSL …/install.sh | sh COPIED
Homebrew
$ brew install bjarneo/cliamp/cliamp COPIED
Arch (AUR)
$ yay -S cliamp COPIED
Or build from source — see the README.
Next step · configure providers

Run the setup wizard

An interactive TUI walks you through Navidrome, Plex, Jellyfin, Emby, Spotify, NetEase, and YouTube Music. It links to each provider's credential page, validates the connection, and writes the right block to your config file.

Setup
$ cliamp setup COPIED
03 sources

Stream from everywhere. Every provider runs through the same playlist, EQ, visualizer, and lyrics pipeline — your config follows you across services. Run cliamp setup for an interactive wizard that walks you through Navidrome, Plex, Jellyfin, Emby, Spotify, NetEase, and YouTube Music.

OAuth · cached
Spotify
Stream your Premium library. Bring your own developer client_id for a private quota, or use the built-in shared one. Search & add tracks with F.
yt-dlp
YouTube
Search videos with Ctrl+F, then play, append, or queue from a results list.
OAuth · cached
YT Music
Browse your playlists with auto music/non-music classification.
Media server
Plex
Browse albums and stream from your Plex Media Server.
Media server
Jellyfin
Artists, albums, tracks — buffered gapless playback.
Media server
Emby
Browse your Emby music library with API key or username/password auth.
Subsonic API
Navidrome
Browse your self-hosted library with synced lyrics.
Provider · yt-dlp
SoundCloud
Opt-in: set [soundcloud] enabled = true. Search with Ctrl+F, browse curated genre playlists, or add user for your profile. cookies_from unlocks Go+ tracks via your browser session.
Provider · yt-dlp
NetEase
Opt-in: run cliamp setup after signing in at music.163.com, then choose your browser. Browse liked songs, account playlists, saved playlists, and charts with browser-cookie playback.
yt-dlp
Bandcamp
Paste any Bandcamp URL and it just plays.
yt-dlp
Bilibili
Audio tracks from Bilibili videos via yt-dlp.
30k+ stations
Radio
Browse stations by country, tag, or name. ICY metadata.
RSS feeds
Podcasts
Pass any podcast RSS URL and listen in your terminal.
Local
Files
MP3, FLAC, OGG, Opus, WAV, AAC, ALAC, WMA. ID3 tags read.
NetEase Cloud Music

Browser-session setup

Sign in at music.163.com, then run cliamp setup. Choose NetEase Cloud Music, pick the browser you used, and the wizard validates the session before writing config.

[netease]
enabled = true
cookies_from = "chrome"
user_id = "your-account-user-id"

After setup, press M to open NetEase and Ctrl+F to search. Playback uses yt-dlp with the same browser cookie source.

04 features
10-Band Equalizer

Parametric EQ with presets: Rock, Jazz, Pop, Classical, and more.

Themes & Visualizers

17 built-in themes and multiple visualizer modes. Hot-swap with t / v.

Playlists

TOML playlists, M3U/M3U8/PLS support, playlist manager with album grouping.

Recently Played

Auto-recorded listening history. Browse it as a virtual playlist or run cliamp history from the shell.

HTTP Streaming

Play from URLs, internet radio, and remote M3U playlists.

Synced Lyrics

Auto-scrolling lyrics for local & Navidrome tracks. Press y.

Gapless Playback

Seamless transitions with preloaded next-track buffering.

MPRIS / Media Keys

Desktop integration. Hardware media keys and playerctl.

Audio Quality

Configurable sample rate (22kHz–192kHz), buffer size, resample.

Live Radio Metadata

ICY/Shoutcast metadata — current song on internet radio streams.

Embedded Tag Reading

ID3v2, Vorbis comments, MP4 atoms — artist, album, genre, year.

CLI Flags

Override volume, shuffle, repeat, theme, EQ, sample rate per-session.

Diagnostic Logging

File logs at ~/.config/cliamp/cliamp.log. Set log_level in config or --log-level on the CLI: debug, info, warn, error.

Self-Update

Run --upgrade to update to the latest release in-terminal.

$
Env-Interpolated Secrets

Reference any string in config.toml from the environment with ${VAR} or $VAR. Keep passwords and tokens out of the file.

Remote Control

Control a running instance from another terminal via Unix-socket IPC. Run with --daemon for headless playback driven entirely by scripts or Waybar.

Lua Plugins

Lua 5.1 sandboxed plugin system. Hook events, add visualizers, push data.

💾
Save to Disk

Press Ctrl+S to save the current track to ~/Music.

05 themes.toml

17 built-in themes. Press t to switch, or use --theme "name" from the CLI. Drop a .toml file in ~/.config/cliamp/themes/ to add your own.

Ayu Mirage Dark
██ ██ ██ ██ ██ ██
Catppuccin
██ ██ ██ ██ ██ ██
Catppuccin Latte
██ ██ ██ ██ ██ ██
Ethereal
██ ██ ██ ██ ██ ██
Everforest
██ ██ ██ ██ ██ ██
Flexoki Light
██ ██ ██ ██ ██ ██
Gruvbox
██ ██ ██ ██ ██ ██
Hackerman
██ ██ ██ ██ ██ ██
Kanagawa
██ ██ ██ ██ ██ ██
Matte Black
██ ██ ██ ██ ██ ██
Miasma
██ ██ ██ ██ ██ ██
Nord
██ ██ ██ ██ ██ ██
Osaka Jade
██ ██ ██ ██ ██ ██
Ristretto
██ ██ ██ ██ ██ ██
Rosé Pine
██ ██ ██ ██ ██ ██
Tokyo Night
██ ██ ██ ██ ██ ██
Vantablack
██ ██ ██ ██ ██ ██
Each swatch: accent · bright fg · fg · green · yellow · red
06 keybindings.conf
Transport
SpacePlay / Pause
sStop
> / <Next / Previous track
← →Seek −/+5s
Shift+← Shift+→Seek −/+30s (default)
N then jSeek to N×10% (e.g. 7j = 70%)
Ctrl+JJump to time
+ / −Volume up / down
] / [Speed ±0.25x
mToggle mono
r / zRepeat / Shuffle
Navigation
TabFocus: Playlist / EQ
j / kScroll or adjust EQ (wraps)
h / lEQ band left / right
PgUp / PgDnPage up / down
Ctrl+U / Ctrl+DHalf-page scroll
Home / EndJump to top / end
g / GVim-style top / bottom
EnterPlay selected
Shift+↑ Shift+↓Move track up / down
Esc / bBack to provider
Search & Browse
/Search playlist
Ctrl+FSearch active provider (Spotify, Navidrome, Jellyfin, Emby, Plex, NetEase, Local) or YouTube fallback
fToggle bookmark ★ / radio favorite
uLoad URL (stream / playlist)
oOpen file browser
a / AQueue (play next) / Queue manager
xRemove highlighted track from current playlist
pPlaylist manager
LBrowse local playlists
Ctrl+XExpand playlist
Inside Playlist Manager
/Filter playlists or tracks (incremental)
EnterOpen playlist · play highlighted track on the tracks screen
PPlay all tracks from the top
aAdd the now-playing track (footer shows which one)
dDelete playlist (confirms) / remove track
Esc / pClose (or clear active filter)
Provider Playlists Pane
/ j kMove cursor (wraps)
EnterLoad the highlighted playlist's tracks into the queue
/Filter the visible playlists
Ctrl+FOnline / server search via the provider's own search
Ctrl+RRefresh — re-pull playlists from the provider
S N P J E Y C M L RSwitch to Spotify / Navidrome / Plex / Jellyfin / Emby / YouTube / SoundCloud / NetEase / Local / Radio
Marker on the row whose tracks are currently loaded
Provider Browser (N)
/ j kMove cursor (wraps top↔bottom)
/ h lBack / drill in
EnterOpen (artists/albums) · play the highlighted track and queue the rest
RReplace queue with all visible tracks (start from #1)
aAppend all visible tracks to the queue
qQueue the highlighted track to play next
sCycle album sort (album list only)
/Filter the visible list (search bar appears under the title)
S N P J E Y C M L RQuick-switch to another provider without going back to the main pane
EscWalk back one level / close the browser
Search Results
EnterPlay selected track now
aAppend selected to playlist
qQueue selected to play next
pSave to Spotify playlist (Spotify only)
EscBack to search input
Providers & UI
NNavidrome
SSpotify
PPlex
JJellyfin
EEmby
YYouTube
RRadio
e / t / vEQ preset / Theme / Visualizer
VFull-screen visualizer
y / iLyrics / Track info
Ctrl+HToggle album headers
Ctrl+SSave to ~/Music
? / Ctrl+KShow keymap
qQuit
07 cli & remote control

CLI flags override any config option for a single session. Remote commands control a running instance over Unix-socket IPC — open another terminal and talk to cliamp directly.

Flags
--volume <dB>[-30, +6]
--shuffleEnable shuffle
--repeat <mode>off, all, one
--mono / --no-monoMono downmix
--auto-playStart immediately
--theme <name>UI theme
--eq-preset <name>EQ preset
--visualizer <mode>Bars, Wave, Matrix, Retro…
--sample-rate <Hz>Output sample rate
--buffer-ms <ms>Speaker buffer 50–500
--resample-quality <n>1–4
--bit-depth <n>PCM: 16 or 32
--compactCap width at 80 cols
--low-powerDisable visualizer to save CPU
--daemon / -dRun headless (IPC only, no TUI)
--playlist <name>Load TOML playlist
--provider <name>Default provider
--upgradeUpdate in place
--help / --versionHelp & version
Remote
play / pause / togglePlayback control
stopStop playback
next / prevTrack navigation
status [--json]Current state
volume <dB>Set volume
seek <secs>Relative seek
load "Name"Load a playlist
queue /path/fileQueue a track
history [--limit N]Show recently played
history clearWipe recently-played file
shuffle [on|off]Toggle or set shuffle
repeat [off|all|one]Set or cycle repeat
mono [on|off]Mono output
speed <ratio>0.25–2.0
eq <preset>Flat, Rock, Pop, Jazz…
eq --band <0-9> <dB>Set individual band
device listList output devices
device <name>Switch device
theme <name|list>Set or list themes
vis <name|next|list>Set or cycle visualizer
08 plugins.lua

Lua 5.1 plugin system. Hook into playback events, add custom visualizers, or push data to external services. Each plugin runs in an isolated sandbox — a crash in one cannot affect others or the player. Drop a .lua file in ~/.config/cliamp/plugins/ and restart.

now-playing.lua
-- ~/.config/cliamp/plugins/now-playing.lua
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)

p:on("app.quit", function()
    cliamp.fs.remove("/tmp/cliamp-now-playing")
end)
webhook.lua
-- ~/.config/cliamp/plugins/webhook.lua
local p = plugin.register({
    name = "webhook",
    type = "hook",
})

local url = p:config("url")

p:on("track.change", function(track)
    if not url then return end
    cliamp.http.post(url, {
        json = { title = track.title, artist = track.artist }
    })
end)
simple-bars.lua (custom visualizer)
-- ~/.config/cliamp/plugins/simple-bars.lua
local p = plugin.register({
    name = "simple-bars",
    type = "visualizer",
})

-- Called ~20 FPS. bands: 10 values (0.0-1.0)
function p:render(bands, frame)
    local lines = {}
    for row = 5, 1, -1 do
        local line = ""
        for i = 1, 10 do
            if bands[i] > (row - 1) / 5 then
                line = line .. "██████ "
            else
                line = line .. "       "
            end
        end
        table.insert(lines, line)
    end
    return table.concat(lines, "\n")
end
Events
track.changeNew track starts playing
track.scrobbleTrack played ≥50% or ≥4 min
playback.statePlay, pause, stop, seek, volume change
app.startAfter all plugins loaded
app.quitBefore shutdown
API
player

Read-only state: state(), position(), volume(), shuffle(), eq_bands()

track

Current metadata: title(), artist(), album(), genre(), duration_secs()

http

HTTP client: get(), post(). JSON, form body, headers, 5s timeout.

fs

Sandboxed I/O: write(), read(), append(), remove(), exists(), mkdir(), listdir()

exec

Spawn from allowlist (yt-dlp, ffmpeg by default): run(bin, args, opts), streams stdout/stderr, cancelable. Requires permissions = {"exec"}.

json

encode() and decode() for JSON serialization.

crypto

md5(), sha256(), hmac_sha256() for hashing and signing.

notify

Desktop notifications via notify-send. Works with mako, dunst, etc.

message

message(text, secs) → transient message in the player's status bar.

timer

Schedule callbacks: after(), every(), cancel()

log

info(), warn(), error(), debug()plugins.log

config

Read per-plugin values from [plugins.name] in config.toml via p:config(key)

bind

p:bind(key, desc, fn) — register a TUI keybinding. With a description it appears in the Ctrl+K overlay. Rejects keys reserved by cliamp. Requires permissions = {"keymap"}.

command

p:command(name, fn) — register a shell-invokable command. Run with cliamp plugins call <plugin> <cmd> [args].

Community
Last.fm scrobbling
09 radio.stats
LIVE
-
listening now
-
total sessions
-
listen hours
Daily Activity
Listeners Around the World
Top Countries