jellyfin-tui: a Jellyfin music player for the terminal
🪼 Modern music streaming client for the terminal
At a glance
- What is it?
- jellyfin-tui is a Rust terminal client for a Jellyfin media server, with mpv playback, sixel cover art, offline caching in sqlite, Last.fm scrobbling and remote control from the Jellyfin web interface. It is packaged for most Linux distributions, builds from source with cargo, and needs libmpv2 and sqlite3 present on the machine.
- Who is it for?
- jellyfin-tui fits someone with a self-hosted Jellyfin or Navidrome server who works in a terminal and wants the library, queue and playlists reachable over ssh or tmux. It is a poor fit for a NetEase style commercial catalogue, since the whole client is built on a server you control, and it is the wrong choice if your terminal cannot draw images, because the cover art needs sixel support.
- Can I use it commercially?
- Yes, with conditions. GPL-3.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
- Is it still maintained?
- Yes. The repository received new commits within the last day.
- What is it written in?
- Mainly Rust, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A terminal client for a server you already run
jellyfin-tui is a music streaming client for the Jellyfin media server, described as inspired by CMUS and others, with the goal of offering a self-hosted terminal music player with the features you expect from a modern client. The project is written in Rust, licensed under GPL-3.0, and the interface is built with ratatui, the Rust terminal UI framework.
The positioning matters for who it is for. This is not a client for a commercial streaming catalogue, it is a front end for a media server you or your household runs. The feature list assumes that arrangement: streaming your own music, multi-library support, playlists you can create and reorder, a Spotify-like double queue with order control, shuffle and repeat modes, and transcoding.
Two features put it beyond a plain player. It can be controlled remotely from the Jellyfin web UI or any other Jellyfin client, so the same session can be driven from a phone. And it has a full offline mode with metadata caching, track downloads, background updates and a fallback for slow networks, which is the feature that makes it usable on a train or a plane.
There is also support for Navidrome through its experimental Jellyfin API, with the Navidrome server URL expected to end at the `/jellyfin` path.
mpv plays the audio, sqlite stores the offline copy
The dependency list in `Cargo.toml` describes the architecture more plainly than any diagram would. Audio playback is delegated to `libmpv2` at version 6.0.0, and the README states plainly that jellyfin-tui depends on libmpv2 for audio playback and sqlite3 for offline caching, both of which should be available in your distribution's package manager.
The user interface is ratatui at 0.30.1 with the crossterm backend, and images are drawn with `ratatui-image` at 11.0.4, which is what makes the sixel cover image possible. The image crate handles decoding with the jpeg, png and webp features enabled, and `color-thief` extracts the primary colour from the album art for the theme system.
Storage is `sqlx` with the sqlite feature and the migrate and macros features enabled, so the offline metadata cache is a real database with migrations rather than a pile of JSON files. The Cargo manifest declares a workspace with two members, the root crate and `crates/media-controls`, which is the piece that handles MPRIS integration, the Linux media key protocol. `discord-rich-presence` is there for Discord presence, `crokey` for configurable key chords, and `arboard` for clipboard access in the editing workflows.
One detail worth noticing is the TLS feature setup. The default feature is `tls-native`, which turns on native-tls for both reqwest and tokio-tungstenite, and there is an alternative `tls-rustls` feature using rustls with webpki roots for people who would rather not link against the system OpenSSL.
Install it from a package, a binary or cargo
Pre-built binaries for Linux and macOS are published on the releases page, and the instruction is to download the binary for your platform, make it executable and put it somewhere on your `PATH`.
For Linux distributions there are packages in most of the usual places: the AUR for Arch, Nixpkgs, the Alpine Linux community repository and the official Void Linux repository. The Void install is:
xbps-install -S jellyfin-tuiBuilding from source needs a Rust toolchain, mpv and sqlite3. On Debian and Ubuntu based systems you may need `libmpv-dev` and `libssl-dev` as well, and the documented system packages are:
# Arch
sudo pacman -S mpv sqlite
# Ubuntu/Debian
sudo apt install mpv libmpv-dev sqlite3 libssl-devThen the clone and install sequence, with an optional step to check out the newest tag:
# clone this repository
git clone https://github.com/dhonus/jellyfin-tui
cd jellyfin-tui
# optional: use latest tag
git fetch --tags
git checkout $(git tag | sort -V | tail -1)
cargo install --path .macOS has its own sequence, since Homebrew's mpv prefix has to be on the library path before cargo builds:
brew install mpv
git clone https://github.com/dhonus/jellyfin-tui
cd jellyfin-tui
# add exports to your shell profile (~/.zshrc etc.)
export LIBRARY_PATH="$LIBRARY_PATH:$(brew --prefix)/lib"
export PATH=$PATH:~/.cargo/bin/
cargo install --path .The repository also carries a `flake.nix`, a `shell.nix` and a `rust-toolchain.toml`, so the Nix path and the pinned toolchain are both available.
The configuration file is plain YAML you can edit
The first run walks you through creating a configuration file, and the program prints where that file lives. On Linux it is `~/.config/jellyfin-tui/config.yaml`, and the documentation invites you to edit it by hand afterwards.
Three authentication styles are supported, and each of them ends up using locally stored auth tokens for future logins: username and password, a password file containing the password, and Jellyfin Quick Connect. A server entry can be marked as the default so the server picker is skipped on startup, which is overridden with the `--select-server` flag.
servers:
- name: Password Server
url: 'https://jellyfin.example.com'
username: 'username'
password: 'imcool123'
default: true # Add to skip server picker on startup. Use --select-server to override
- name: Quick Connect Server
url: 'http://localhost:8096'
quick_connect: true # use Jellyfin Quick ConnectEverything after the server list is optional, and the values shown are the defaults apart from the discord and mpv examples:
art: true
# Save and restore the state of the player (queue, volume, etc.)
persist: true
# Grab the primary color from the cover image (false => uses the current theme's `accent` instead)
auto_color: true
# Time in milliseconds to fade between colors when the track changes
auto_color_fade_ms: 500
# Always show the lyrics pane, even if no lyrics are available
lyrics: 'always' # options: 'always', 'never', 'auto'Two of those keys are worth pausing on. `persist` saves and restores the player state, which is what makes restarting the client keep your queue and volume. And `auto_color` pulls the primary colour out of the album art, with `auto_color_fade_ms` setting how long the transition between colours takes when the track changes, which is a small detail that makes a text interface feel less static than it sounds.
The layout is designed around narrow terminals
Several configuration keys exist because a terminal is a hostile place for a music player, and the client adapts to it.
The `layout` key takes `auto`, `vertical` or `horizontal`, and `auto` switches to the vertical layout below `vertical_threshold` columns, set to 100 by default. The vertical layout exists for narrow terminals, and the panes can be resized with `Ctrl+Up/Down`. There is a separate `album_column` setting with `auto`, `true` and `false` options, where `auto` hides the Album column in panes narrower than `album_column_threshold`, 140 columns, because at that width the track titles need the space more, while still showing the column during a search.
The `lyrics` key takes `always`, `never` or `auto`, and the lyrics pane autoscrolls, which requires a Jellyfin server newer than 10.9. The `zen_mode_timeout_minutes` key auto-enters a zen mode after N idle minutes, and `auto_browse` opens the selected artist, album or playlist once the selection rests on it, either with a default delay or with a delay in seconds you choose.
The symbol set is configurable too, for people on Nerd Fonts, and each character of the `spinner` entry is one animation frame. That is the sort of detail that separates a project people actually keep installed from a weekend project.
Offline mode and lyrics both depend on the server
The features that sound most impressive are the ones with the most server dependency, and the README is reasonably clear about where the lines are.
Lyrics with autoscroll need Jellyfin 10.9 or newer. Last.fm scrobbling needs the jellyfin-plugin-lastfm plugin installed on the server. Navidrome support goes through its experimental Jellyfin API, so it inherits whatever stability that word implies.
Transcoding has a hard ceiling that the configuration file spells out in a comment: Jellyfin arbitrarily limits the bitrate of transcoded audio to 256kbps, so aac at 256 is the best you can get. That is a server side limit, not something the client can work around.
Offline mode is the feature with real local machinery: metadata caching, track downloads, background updates and a fallback for slow networks, all sitting on the sqlite database. The offline cache is therefore a local copy of your library that has to be kept in step with the server, and the background update path is what does that work.
What is entirely client side is the remote control story: the session can be driven from the Jellyfin web interface or any other Jellyfin client, so the terminal is one remote control among several rather than the only way in.
A GPL-3.0 project with a steady release line
The licence is GPL-3.0, with the licence file at the root of the repository. For a client application that talks to a server you control over HTTP, that has one practical consequence worth naming: if you modify the source and distribute the modified binary, you owe the recipients the corresponding source under the same terms. Running it on your own machines raises no obligation.
The release history shows a project with a steady hand. Version 1.5.1 was tagged on 2026-07-03, 1.5.2 on 2026-07-13 and 1.6.0 on 2026-09-14, and the last push was on 2026-10-18 on the default branch `main`. The repository is not archived, and the version in `Cargo.toml` matches the 1.6.0 tag.
For a project of this size that is a good sign, and the repository structure backs it up: separate `src` and `crates` directories, a `rustfmt.toml` for formatting, a `Cargo.lock` checked in, and a `flake.lock` for reproducible Nix builds. The feature list ends with a line about being fast and nifty, and the code gives a reason to believe the first half of that.
Editorial conclusion
jellyfin-tui fits someone with a self-hosted Jellyfin or Navidrome server who works in a terminal and wants the library, queue and playlists reachable over ssh or tmux. It is a poor fit for a NetEase style commercial catalogue, since the whole client is built on a server you control, and it is the wrong choice if your terminal cannot draw images, because the cover art needs sixel support. Before installing, confirm libmpv2 and sqlite3 are available on the system, decide whether you want Quick Connect or a stored password in `~/.config/jellyfin-tui/config.yaml`, and check that your Jellyfin server is newer than 10.9 if you want the lyrics pane.
Frequently asked questions
How do I install jellyfin-tui on Linux?
Packages exist for Arch through the AUR, for Nixpkgs, for the Alpine Linux community repository and for Void Linux. Otherwise build from source with cargo, which needs mpv and sqlite3 installed, and on Debian or Ubuntu also `libmpv-dev` and `libssl-dev`.
Where is the jellyfin-tui configuration file?
The program prints the config location when it runs, and on Linux the file is `~/.config/jellyfin-tui/config.yaml`. It is created through a guided first run and can be edited by hand afterwards.
Can jellyfin-tui work without an internet connection?
Yes, there is a full offline mode with metadata caching, track downloads, background updates and a fallback for slow networks. The offline cache uses sqlite3, which the project lists as a dependency alongside libmpv2 for audio playback.
Does jellyfin-tui support Navidrome?
It also works with Navidrome's experimental Jellyfin API. In the configuration file the Navidrome server URL is expected to point at the `/jellyfin` path that Navidrome serves its API under.
What do I need for the lyrics pane and Last.fm scrobbling?
Lyrics with autoscroll require a Jellyfin server newer than 10.9. Last.fm scrobbling requires the jellyfin-plugin-lastfm plugin to be installed on the Jellyfin server.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/dhonus-jellyfin-tui)Was this useful?