npx skills add ...
npx skills add reason-machines/devtools-skills --skill cliamp-terminal-music-player
Expert guide for using cliamp, a retro terminal music player inspired by Winamp that supports local files, streaming services, and remote media servers
npx skills add reason-machines/devtools-skills --skill cliamp-terminal-music-player
Skill by ara.so — Devtools Skills collection.
cliamp is a retro terminal music player inspired by Winamp. It plays local files (MP3, FLAC, WAV, OGG, AAC, ALAC, Opus, WMA), streams (HTTP, HLS, Icecast), podcasts, and integrates with Spotify, YouTube Music, SoundCloud, Bilibili, NetEase Cloud Music, Navidrome, Plex, and Jellyfin. Features include a spectrum visualizer, parametric EQ, playlist management, radio browser, and Lua plugin system.
The Homebrew formula automatically installs all required codec libraries (FLAC, Vorbis, Ogg).
Prerequisites:
libasound2-dev on Debian/Ubuntu, alsa-lib-devel on Fedora, alsa-lib on Arch)Or without Make:
Install these for extended format and streaming support:
Configure remote providers (Navidrome, Plex, Jellyfin, Spotify, YouTube Music, NetEase Cloud Music):
The wizard validates connections and writes configuration to ~/.config/cliamp/config.toml.
Press Ctrl+K in the player to see all keybindings.
Space / P: Play/PauseN: Next trackShift+N: Previous trackS: StopR: Open radio browserL: Toggle lyrics viewF: Toggle fullscreen modeQ / Ctrl+C: Quit+ / -: Volume up/downM: Mute/unmuteE: Toggle equalizerA: Add to playlistD: Remove from playlistC: Clear playlistShift+S: Shuffle playlistCtrl+S: Save playlistV: Cycle visualizer modes (spectrum, bars, dots, etc.)B: Toggle visualizer displayConfiguration file: ~/.config/cliamp/config.toml
Run cliamp setup and select Spotify to authenticate. The wizard handles OAuth flow and stores credentials securely.
Get your Plex token: https://support.plex.tv/articles/204059436-finding-an-authentication-token-x-plex-token/
Extract cookies with yt-dlp:
Create ~/.config/cliamp/radios.toml:
cliamp supports IPC commands when running in daemon mode:
cliamp supports Lua plugins for custom visualizers, audio effects, and UI extensions.
~/.config/cliamp/plugins/pulse-visualizer/plugin.lua:
Add to ~/.config/cliamp/config.toml:
Available Lua functions:
Install community plugins:
Enable in config:
Stream audio from a remote server to your local machine:
Enable MPRIS support to control cliamp with media keys:
Control with playerctl:
Example Quickshell widget configuration for displaying currently playing track:
On Linux with PipeWire or PulseAudio, install the ALSA bridge:
If you downloaded pre-built binaries directly (not via Homebrew):
Or install via Homebrew to avoid this:
Ensure yt-dlp is installed and up-to-date:
Re-run setup wizard:
Select Spotify and follow the OAuth flow. Ensure your Spotify account is Premium (free accounts are not supported for streaming).
Reduce visualizer complexity or disable it:
Or use a lighter visualizer mode (press V to cycle).
Ensure the directory exists and is writable:
Check firewall rules and server URL:
Add to shell profile:
This skill covers installation, configuration, CLI usage, plugin development, remote control, integrations, and troubleshooting for the cliamp terminal music player.
git clone https://github.com/bjarneo/cliamp.git
cd cliamp
make && make installgo build -o cliamp .# macOS
brew install ffmpeg yt-dlp
# Debian/Ubuntu
sudo apt install ffmpeg yt-dlp
# Arch
sudo pacman -S ffmpeg yt-dlp# Play a directory
cliamp ~/Music
# Play specific files
cliamp *.mp3 *.flac
# Play a stream URL
cliamp https://example.com/stream.mp3
# Play YouTube video/playlist
cliamp "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
# Play SoundCloud track
cliamp "https://soundcloud.com/artist/track"cliamp setupcliamp setup[player]
volume = 80
shuffle = false
repeat = "none" # none, one, all
visualizer = "spectrum"
[ui]
theme = "winamp" # winamp, nord, dracula, gruvbox, catppuccin
show_spectrum = true
show_lyrics = true
[audio]
sample_rate = 44100
buffer_size = 4096[spotify]
enabled = true
username = "${SPOTIFY_USERNAME}"
# Credentials stored separately, configured via 'cliamp setup'[navidrome]
enabled = true
server_url = "https://music.example.com"
username = "${NAVIDROME_USERNAME}"
password = "${NAVIDROME_PASSWORD}"[plex]
enabled = true
server_url = "https://plex.example.com:32400"
token = "${PLEX_TOKEN}"[jellyfin]
enabled = true
server_url = "https://jellyfin.example.com"
api_key = "${JELLYFIN_API_KEY}"
user_id = "${JELLYFIN_USER_ID}"[youtube_music]
enabled = true
# Requires yt-dlp and browser cookies
cookies_from_browser = "firefox" # chrome, firefox, safari, etc.yt-dlp --cookies-from-browser firefox --print cookies https://music.youtube.com[[stations]]
name = "Soma FM Groove Salad"
url = "https://somafm.com/groovesalad130.pls"
genre = "Ambient"
[[stations]]
name = "NTS Radio 1"
url = "https://stream-relay-geo.ntslive.net/stream"
genre = "Eclectic"
[[stations]]
name = "Jazz24"
url = "https://live.wostreaming.net/direct/ppm-jazz24aac-ibc1"
genre = "Jazz"# Save current playlist
cliamp --save-playlist my-playlist.m3u
# Load playlist
cliamp --playlist ~/Music/playlists/favorites.m3u
# Create M3U playlist manually
cat > my-playlist.m3u << EOF
#EXTM3U
#EXTINF:180,Artist - Song Title
/path/to/song.mp3
#EXTINF:240,Another Artist - Another Song
https://example.com/stream.mp3
EOF
cliamp --playlist my-playlist.m3u# Start in headless daemon mode
cliamp --headless ~/Music
# Control from another terminal
cliamp ipc play
cliamp ipc pause
cliamp ipc next
cliamp ipc previous
cliamp ipc volume 75
cliamp ipc seek 30 # seek to 30 seconds
cliamp ipc status # get current track info#!/bin/bash
# Skip to next track if current track is longer than 10 minutes
status=$(cliamp ipc status --json)
duration=$(echo "$status" | jq -r '.duration')
if [ "$duration" -gt 600 ]; then
cliamp ipc next
fi~/.config/cliamp/plugins/
└── my-plugin/
├── plugin.lua
└── config.toml (optional)-- Plugin metadata
plugin = {
name = "Pulse Visualizer",
version = "1.0.0",
author = "Your Name",
description = "Pulsing circle visualizer"
}
-- Called on each audio frame
function on_audio_frame(samples, sample_rate)
-- samples: table of audio samples [-1.0, 1.0]
-- sample_rate: integer
local sum = 0
for i, sample in ipairs(samples) do
sum = sum + math.abs(sample)
end
local avg = sum / #samples
local radius = math.floor(avg * 50)
-- Return render data
return {
type = "circle",
x = 40,
y = 12,
radius = radius,
color = {r = 255, g = 100, b = 200}
}
end
-- Called when plugin loads
function on_load()
print("Pulse Visualizer loaded")
end
-- Called when plugin unloads
function on_unload()
print("Pulse Visualizer unloaded")
end[plugins]
enabled = ["pulse-visualizer"]-- Audio data
on_audio_frame(samples, sample_rate)
-- Track events
on_track_change(track) -- track: {title, artist, album, duration}
on_play()
on_pause()
on_stop()
-- Lifecycle
on_load()
on_unload()
-- Drawing functions (available in plugin context)
draw_text(x, y, text, color)
draw_rect(x, y, width, height, color)
draw_circle(x, y, radius, color)
draw_line(x1, y1, x2, y2, color)
-- Utility functions
log(message)
get_config(key) -- Read plugin config.toml
http_get(url) -- Simple HTTP requestcd ~/.config/cliamp/plugins/
git clone https://github.com/bjarneo/cliamp-plugin-soap-bubbles.git soap-bubbles[plugins]
enabled = ["soap-bubbles"]# On remote server, start cliamp in headless mode
cliamp --headless --http-server 0.0.0.0:8080 ~/Music
# On local machine, forward port and play
ssh -L 8080:localhost:8080 user@remote-server
cliamp http://localhost:8080/stream# High quality playback
cliamp --sample-rate 96000 --buffer-size 8192 ~/Music
# Low latency (smaller buffer)
cliamp --buffer-size 2048 ~/Music#!/bin/bash
# Play all albums in directory sequentially
for album_dir in ~/Music/*/; do
echo "Playing: $album_dir"
cliamp "$album_dir"
done[player]
mpris = trueplayerctl -p cliamp play-pause
playerctl -p cliamp next
playerctl -p cliamp previous// ~/.config/quickshell/nowplaying.qml
import Quickshell
import Quickshell.Services.Mpris
MprisPlayer {
player: "cliamp"
Text {
text: player.metadata.title + " - " + player.metadata.artist
font.pointSize: 12
}
}# PipeWire (Arch)
sudo pacman -S pipewire-alsa
# PulseAudio (Arch)
sudo pacman -S pulseaudio-alsa
# PipeWire (Debian/Ubuntu)
sudo apt install pipewire-alsa
# PulseAudio (Debian/Ubuntu)
sudo apt install pulseaudio-alsabrew install flac libvorbis libogg# Update yt-dlp
pip install --upgrade yt-dlp
# or
brew upgrade yt-dlp
# Test yt-dlp
yt-dlp --version[ui]
show_spectrum = falsemkdir -p ~/.config/cliamp/playlists
cliamp --save-playlist ~/.config/cliamp/playlists/my-playlist.m3u# Test Navidrome connection
curl -u "${NAVIDROME_USERNAME}:${NAVIDROME_PASSWORD}" \
"https://music.example.com/rest/ping.view?v=1.16.1&c=cliamp"
# Test Plex connection
curl -H "X-Plex-Token: ${PLEX_TOKEN}" \
"https://plex.example.com:32400/library/sections"
# Test Jellyfin connection
curl -H "X-Emby-Token: ${JELLYFIN_API_KEY}" \
"https://jellyfin.example.com/Users/${JELLYFIN_USER_ID}"#!/bin/bash
# Rotate through daily playlists
day=$(date +%u) # 1-7 for Mon-Sun
cliamp --playlist ~/.config/cliamp/playlists/day-${day}.m3u#!/bin/bash
# Play a random album from library
albums=(~/Music/*/)
random_album=${albums[$RANDOM % ${#albums[@]}]}
cliamp "$random_album"#!/bin/bash
# Display current track in status bar
status=$(cliamp ipc status --json 2>/dev/null)
if [ $? -eq 0 ]; then
title=$(echo "$status" | jq -r '.title // "N/A"')
artist=$(echo "$status" | jq -r '.artist // "N/A"')
echo "♫ $artist - $title"
else
echo ""
fi# ~/.bashrc or ~/.zshrc
alias music='cliamp --playlist ~/.config/cliamp/last-session.m3u'
# Save on exit (add to cliamp config or wrapper script)
trap 'cliamp ipc save-playlist ~/.config/cliamp/last-session.m3u' EXIT