Skip to main content

cmus-web

PyPI - Version PyPI - Python Version

image

A self-hosted PWA remote control for cmus. Control your player from any device on your network.


Table of contents

Features

  • Real-time player state via SSE (track, position, volume, shuffle/repeat)
  • Embedded album art extraction (MP3, FLAC, M4A, etc.)
  • Installable PWA with offline caching
  • Keyboard shortcuts for all playback controls
  • Customizable accent color (persisted in localStorage)
  • Zero-build frontend (vanilla HTML/CSS/JS + Alpine.js)

A note on PWA and HTTPS

The install/Add to Home Screen prompt only works over HTTPS. Browsers require a secure context for service workers and PWA installation. If you're only accessing cmus-web over LAN on http://192.168.x.x:8000, the app still works fine as a regular web page, you just won't get the install prompt.

If you want full PWA support, you need a domain name with a TLS certificate. This is straightforward with a reverse proxy like Traefik, which handles automatic HTTPS via Let's Encrypt. Put cmus-web behind Traefik and you're done.

Prerequisites

  • Python 3.13+
  • cmus running with a socket (default: $XDG_RUNTIME_DIR/cmus-socket or /tmp/cmus-socket)
  • cmus-remote on your PATH

Installation

From PyPI

pip install cmus-web

Or with pipx (isolated, recommended for CLI tools):

pipx install cmus-web

From source

git clone https://github.com/FawkesOficial/cmus-web.git
cd cmus-web
uv sync

Usage

Make sure cmus is running, then:

cmus-web

Open http://127.0.0.1:8000 in your browser.

CLI options

cmus-web [OPTIONS]

Options:
  --host TEXT       Bind address (default: 127.0.0.1)
  --port INTEGER    Port (default: 8000)
  --socket TEXT     cmus socket path (overrides CMUS_SOCKET env)
  --music-dir TEXT  Path to music directory for album art in Docker
  --prefix TEXT     Host path prefix from cmus-remote to strip (for Docker)
  --help            Show this message and exit.

Examples

# Bind to all interfaces (accessible from other devices)
cmus-web --host 0.0.0.0

# Use a custom socket path
cmus-web --socket /run/user/1000/cmus-socket

# Run on a different port
cmus-web --port 9090

Docker

Important: cmus socket

cmus-web communicates with cmus through a Unix domain socket. If the socket path you mount does not exist on the host, Docker will silently create a directory in its place, which will break the connection and can be confusing to debug.

Use this helper script to verify the socket exists before starting the container:

#!/usr/bin/env bash
# start-cmus-web.sh - verify cmus socket exists, then start the container

SOCKET="${CMUS_SOCKET:-$XDG_RUNTIME_DIR/cmus-socket}"

if [ ! -S "$SOCKET" ]; then
  echo "Error: cmus socket not found at $SOCKET"
  echo "Make sure cmus is running and the socket path is correct."
  exit 1
fi

docker run -d \
  -v "$SOCKET":/tmp/cmus-socket \
  -v ~/Music:/music \
  -e CMUS_WEB_PREFIX="$HOME/Music" \
  -p 8000:8000 \
  cmus-web

docker run

docker build -t cmus-web .

docker run -d \
  -v /run/user/1000/cmus-socket:/tmp/cmus-socket \
  -v ~/Music:/music \
  -e CMUS_WEB_PREFIX=/home/user/Music \
  -p 8000:8000 \
  cmus-web

The music volume mount enables album art extraction. Use CMUS_WEB_PREFIX to tell cmus-web what host path to strip from cmus-remote file paths so they resolve correctly inside the container.

docker compose

services:
  cmus-web:
    build: .
    container_name: cmus-web
    ports:
      - "8000:8000"
    volumes:
      - /run/user/1000/cmus-socket:/tmp/cmus-socket
      - ~/Music:/music
    environment:
      - CMUS_WEB_PREFIX=/home/user/Music
    restart: unless-stopped
docker compose up -d

Keyboard shortcuts

Key Action
Space / C Play / Pause
B Next track
Z Previous track
S Toggle shuffle
R Toggle repeat
L Search lyrics online
+ / - Volume up / down
Arrow Left / Right Seek -5s / +5s
Arrow Up / Down Volume up / down

Tech stack

  • Backend: Python, FastAPI, uvicorn, Mutagen, SSE-Starlette
  • Frontend: Vanilla HTML/CSS/JS, Alpine.js
  • Packaging: uv, Hatchling
  • Container: Debian slim, uv

License

cmus-web is distributed under the terms of the GPL-3.0 license.

Metadata

Release files for cmus-web 0.1.3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for cmus-web 0.1.3
File Size Uploaded
cmus_web-0.1.3.tar.gz 132.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for cmus-web 0.1.3
File Interpreter ABI Platform
cmus_web-0.1.3-py3-none-any.whl Python 3 none any Details

Total release size: 236.5 kB

Release files / cmus_web-0.1.3.tar.gz

Download URL cmus_web-0.1.3.tar.gz
Size 132.6 kB
Tags Source
SHA-256 checksum
How to use checksums
8e1bca839b3dfb33dce22fea3c28026703aa45f26b886a2278346005a5a17531
BLAKE2b-256 checksum
How to use checksums
4d67eb01af905ef6452549081771057830240a172403bf0b67c7fbf0717886d3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on May 24, 2026.

Transparency log

Release files / cmus_web-0.1.3-py3-none-any.whl

Download URL cmus_web-0.1.3-py3-none-any.whl
Size 103.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
3c22ffc9e2ede53faf5d0c89b05e146ac7c1ddd0d5422716e32f79410d9d9fd7
BLAKE2b-256 checksum
How to use checksums
7a53d85c40f7b9a523b94fd2e3e05eea22198e17848571dd2b1c4b503f5ea23d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on May 24, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.3 This release

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page