Skip to content

index-null/cmus-lyric

Repository files navigation

cmus-lyric banner

Go Bubble Tea Lipgloss Bubbles LRCLIB Release License

cmus-lyric

English | 中文

A terminal-based synced lyrics viewer for cmus, built with Bubble Tea.

Inspired by pekrockstar/cmus-lyric, rewritten from scratch with a modern Go stack.

cmus-lyric demo

Overview

cmus-lyric connects to your running cmus instance via Unix socket (with cmus-remote fallback), reads the current track, and displays time-synced lyrics in a beautiful TUI. It resolves lyrics from multiple sources — embedded audio tags, local .lrc files, a disk cache, and online APIs — all fetched asynchronously without blocking the UI.

Features:

  • Real-time synced lyric scrolling with highlight
  • Auto-fetch from LRCLIB and Netease Music (non-blocking)
  • Translation lyrics support (.t.lrc / .t.lyric side-by-side)
  • Embedded lyrics extraction from audio files (ID3/Vorbis Comment)
  • Album cover display (lyrics cover)
  • Lyrics caching (location determined by os.UserCacheDir(), e.g. ~/Library/Caches/cmus-lyric/ on macOS, ~/.cache/cmus-lyric/ on Linux) for offline and read-only directories
  • Duration tolerance (±2s) for better lyric matching
  • Unix socket IPC for low-overhead cmus communication
  • GBK/UTF-8 auto-detection
  • Progress bar and playback status
  • Debug mode (d key) to inspect track metadata and lyric sources
  • Minimal, distraction-free UI

Install

Homebrew (macOS / Linux)

brew install index-null/tap/lyrics

Shell script

curl -fsSL https://raw.githubusercontent.com/index-null/cmus-lyric/master/install.sh | bash

Or install to a custom directory:

INSTALL_DIR=~/.local/bin curl -fsSL https://raw.githubusercontent.com/index-null/cmus-lyric/master/install.sh | bash

Go

go install github.com/index-null/cmus-lyric/cmd/lyrics@latest

Manual download

Download the binary for your platform from the Releases page, extract and move to your PATH:

tar xzf cmus-lyric_*_darwin_arm64.tar.gz
sudo install -m 755 lyrics /usr/local/bin/lyrics

From source

git clone https://github.com/index-null/cmus-lyric.git
cd cmus-lyric
task install   # or: go build -o lyrics ./cmd/lyrics && sudo mv lyrics /usr/local/bin/

Prerequisites

  • cmus music player (must be running)

Usage

Start cmus and play a song, then in another terminal:

lyrics
Key Action
q Ctrl+C Quit
? Toggle help
d Toggle debug
r Refetch lyrics

How lyrics are resolved

  1. Extract embedded lyrics from the audio file (ID3 USLT / Vorbis Comment)
  2. Look for <filename>.lrc or <filename>.lyric next to the audio file
  3. If a .t.lrc / .t.lyric file exists alongside, translation lines are shown below each lyric line
  4. Check the local cache (location determined by os.UserCacheDir(), e.g. ~/Library/Caches/cmus-lyric/ on macOS, ~/.cache/cmus-lyric/ on Linux)
  5. If nothing is found, fetch from LRCLIB (preferred) then Netease Music, save as .lrc and cache
    • Duration tolerance: ±2 seconds when matching tracks by duration

Album cover

Display the album cover of the current track:

lyrics cover

Cover is fetched from:

  1. Embedded album art in audio file
  2. Local cache (location determined by os.UserCacheDir(), e.g. ~/Library/Caches/cmus-lyric/ on macOS, ~/.cache/cmus-lyric/ on Linux)
  3. Netease Music API (auto-saved to cache)

Project Structure

cmus-lyric/
├── cmd/lyrics/           # Application entry point
├── internal/
│   ├── cmus/             # cmus IPC (Unix socket + exec fallback)
│   ├── cover/            # Album cover display
│   ├── lyric/            # Lyric loading, parsing, fetching, caching
│   └── player/           # Bubble Tea model, view, styles
├── .github/workflows/    # CI/CD (auto-release on tag)
├── Taskfile.yml          # Build tasks
├── .golangci.yml         # Linter config (v2)
├── lefthook.yml          # Git hooks (fmt + lint + build + test)
├── .goreleaser.yaml      # Release config
├── install.sh            # One-line install script
└── go.mod

Development

# First time: install git hooks & verify toolchain (one-time)
task setup

task build          # Build binary to bin/
task run            # Build and run
task lint           # Run golangci-lint
task test           # Run tests
task check          # Full quality check (tidy + lint + test)

Note

Linting requires golangci-lint v2.x. Install with brew install golangci-lint or other methods.

task setup installs lefthook git hooks (pre-commit: fmt+lint+build, pre-push: lint+test). Hooks prevent pushing code that would fail CI — they mirror the same checks that run on GitHub.

Release

Releases are fully automated via GitHub Actions. To create a new release:

git tag v0.1.0
git push origin v0.1.0

This triggers the workflow which:

  1. Builds binaries for linux/darwin x amd64/arm64
  2. Creates a GitHub Release with checksums
  3. Updates the Homebrew tap formula

Tip

To preview a release locally: goreleaser release --snapshot --clean

About

Modern synced lyrics viewer for cmus with auto-fetching from LRCLIB/Netease, supports cover. Built with Bubble Tea TUI framework. One-line install via Homebrew.

Topics

Resources

License

Contributing

Stars

2 stars

Watchers

0 watching

Forks

Contributors