A small standalone Plex terminal UI.
Project description
plex-tui
A terminal Plex client built for watching media, not managing servers.
There are plenty of tools for administering Plex from the command line. Surprisingly few are built for sitting down, browsing your library, and watching something without leaving the terminal.
plex-tui is a standalone Textual application that brings Plex browsing, poster
artwork, collection cards, playlists, search, stream preferences, and mpv
playback into a keyboard-first terminal interface.
Built for people who spend their day in a terminal and would rather stay there.
Why?
Most terminal Plex tools are built for administration, automation, or quick status checks. Those are useful jobs, but they are not the same as browsing a library, comparing options, and choosing something to watch.
Meanwhile, terminal applications got better. Tools like lazygit, gitui, btop, and modern Textual apps raised the bar for what a TUI can be: rich layouts, keyboard-first workflows, responsive interfaces, and even artwork are no longer unusual.
plex-tui exists because browsing Plex and choosing something to watch deserves that same kind of terminal-native experience.
Project Status
plex-tui is still early, but already usable. Login, server selection, library browsing, search, playlists, artwork, stream preferences, and playback are working today. Expect rough edges, but expect progress too.
Screenshots
Movie grid
TV show grid
Collection cards
List view
Features
- Plex PIN login and server selection.
- Paged library browsing with automatic loading near the end of loaded items.
- Library submenu entrypoints for all items, Recommended, Collections, Playlists, and Categories. Library rows open all items by default; Space opens the browse-mode menu, and Settings can swap the primary and alternate actions.
- Current-library search and bounded global search.
- List view plus configurable-density grid view with terminal poster artwork, missing-artwork placeholders, and intentional glyph cards for collections and hubs.
- External subtitle support and direct playback for embedded PGS/VOBSUB tracks.
- Audio and subtitle pickers with saved language preferences.
- Separate play-from-start and resume actions with Plex progress reporting.
- Watched/unwatched toggling for selected playable Plex items.
- Continue Watching episode rows show their show, season, and episode context, and items can be removed from the Continue Watching view.
- Playlist management for creating playlists from selected media, adding media to existing playlists, and removing items while browsing a playlist.
- Movie editions appear as distinct variants when Plex reports multiple editions for a selected movie.
- Settings screen for stream preferences, playback mode and transcode quality,
artwork modes, grid density, page size, auto-load threshold, grid artwork
prefetching, media view, library Enter behavior, and
mpvwindow size. - App diagnostics view for version, paths,
mpv, Plex connection, artwork, and browsing settings.
Requirements
- Python 3.11 or newer
mpvavailable onPATH- A Plex account/server
When installing with PyPI or from GitHub, install mpv with your platform
package manager:
# macOS
brew install mpv
# Debian / Ubuntu
sudo apt install mpv
# Fedora
sudo dnf install mpv
# Arch Linux / Manjaro
sudo pacman -S mpv
Installation
PyPI
pipx install plex-tui
plex-tui --smoke
plex-tui
This is the recommended cross-platform install path. It keeps Python
dependencies isolated, but you still need to install mpv separately. If
pipx is not installed, install it with your platform package manager first or
follow the pipx installation guide.
Homebrew
brew trust --tap so1omon563/plex-tui
brew tap so1omon563/plex-tui
brew install plex-tui
plex-tui --smoke
The Homebrew formula installs mpv automatically. Apple Silicon macOS uses
prebuilt bottles when available, while Intel macOS still uses Homebrew's
source-build path. Homebrew 6 requires non-official taps to be trusted before
loading formulae from them; plex-tui only depends on formulae from
Homebrew/core, so no additional tap trust is required for dependencies.
Arch Linux
paru -S plex-tui
plex-tui --smoke
The AUR package depends on mpv. Any AUR helper can be used; paru is only an
example.
GitHub
pipx install "git+https://github.com/so1omon563/plex-tui.git"
pipx install "git+https://github.com/so1omon563/plex-tui.git@v0.4.4"
Use this path for testing main before a tagged/PyPI release.
Useful CLI checks:
plex-tui --version
plex-tui --config-path
plex-tui --debug-log-path
plex-tui --diagnostics
plex-tui --smoke
For local development:
git clone https://github.com/so1omon563/plex-tui.git
cd plex-tui
python3 -m venv .venv
source .venv/bin/activate
make install-dev
make run
First Run & Configuration
On first run, plex-tui starts a Plex browser login and asks which server connection to save. If a browser cannot be opened, use the login URL shown in the terminal.
The login flow writes a config file with the selected server URL and token. Use
the Settings screen or plex-tui --config-path to find the active file.
You can also configure a server manually. macOS config path:
mkdir -p "$HOME/Library/Application Support/plex-tui"
$EDITOR "$HOME/Library/Application Support/plex-tui/config.toml"
Linux config path:
mkdir -p "$HOME/.config/plex-tui"
$EDITOR "$HOME/.config/plex-tui/config.toml"
Minimal config:
base_url = "http://127.0.0.1:32400"
token = "your-plex-token"
Environment variables also work:
export PLEX_TUI_BASE_URL="http://127.0.0.1:32400"
export PLEX_TUI_TOKEN="your-plex-token"
See config.example.toml for optional settings.
Playback
Playback is launched through mpv; plex-tui does not embed a video player.
Use p to start the selected item from the beginning, or r to resume from
the saved Plex position when one is available. While playback is active, Plex
progress is updated in the background. Saved audio/subtitle language
preferences are applied when matching streams are available, and the details
pane shows the effective playback choices. Playback mode defaults to
direct/default behavior and can be changed in Settings to force Plex
transcoding with Original, 1080p 8 Mbps, 720p 4 Mbps, or 480p 2 Mbps quality
presets. The default mpv launch uses --autofit=80% so videos open at a
comfortable size on modern displays; Settings can override this with values
such as 90%, 1280x720, or 80%x80%. If an older config has an exact
mpv_window_size = "1280x720" override, cycle the mpv window-size setting once
to return to the Default preset.
Use w from a playable movie or episode to toggle its Plex watched state.
When playback is active, choosing an audio or subtitle track from the picker
also asks mpv to switch the active track when the launched stream exposes a
matching track.
Key Bindings
| Key | Action |
|---|---|
q |
Quit |
ctrl+r |
Reload Plex connection |
/ |
Search current library |
g |
Search all libraries |
? |
Show help |
tab / shift+tab |
Move focus |
l |
Focus libraries |
m |
Focus media |
space |
Run the alternate action for a selected library |
v |
Toggle list/grid view |
pageup / pagedown |
Move one page in grid view |
, |
Show settings |
escape |
Clear search, go back, or close current view |
enter |
Open selected item |
p |
Play selected item from the beginning |
r |
Resume selected item from the saved Plex position |
w |
Mark selected item watched / unwatched |
P |
Add selected playable item to a playlist |
backspace / delete |
Remove selected item from Continue Watching or a playlist |
a / s |
Choose audio / subtitle preference |
A / S |
Clear audio preference / cycle subtitle mode |
x |
Stop launched mpv |
Artwork
Poster artwork renders as portable colored block art by default, so it works in
ordinary terminals without native image support. In Kitty and Ghostty, set
artwork_renderer to auto to render native terminal images through Kitty
Unicode placeholders. Set artwork_renderer to kitty to explicitly try the
Kitty graphics protocol in other compatible terminals. This keeps Textual in
charge of layout and redraws while the terminal paints the poster inside those
cells. Outside detected Kitty-compatible terminals, auto falls back to block
art; plex-tui --diagnostics reports the active renderer status.
Cards that represent collections, playlists, categories, hubs, or query shelves
use geometric glyph artwork instead of pretending to be missing posters. Rows
made entirely of those cards use roomier navigation-grid spacing. See
docs/collection-artwork-design.md for the design notes behind that visual
language.
Grid view prefetches artwork for the visible page immediately and, by default,
prepares three pages ahead in the background. grid_prefetch_pages can be set
from 0 to 5; use 0 to fetch only the visible page on slower systems.
Compact, comfortable, and large density modes adjust card and poster sizing. The
artwork cache is bounded and stored in the app cache directory shown in
Settings.
Diagnostics
Playback diagnostics are written to debug.log in the app config directory.
Tokens are redacted from logged mpv arguments.
The Settings diagnostics section can show the debug log path, recent log lines,
and an app diagnostics summary for support reports.
Useful paths:
plex-tui --config-path
plex-tui --debug-log-path
Enable browsing performance timings before launch:
PLEX_TUI_PERF_LOG=1 plex-tui
This also records alphabet-jump decisions, including the current title, Plex sort title, loaded alphabet buckets, and selected target row.
To collect environment information for issue reports:
plex-tui --diagnostics
Verbose grid artwork internals are quieter by default. Include them only when debugging poster loading:
PLEX_TUI_PERF_LOG=1 PLEX_TUI_ARTWORK_LOG=1 plex-tui
Development
Common commands:
make smoke # app construction and helper sanity check
make test # pytest suite
make compile # compile src and tests
make check-package # build and validate package metadata
make check # smoke, tests, compile, package validation
Packaging and release docs:
PACKAGING.md: PyPI/pipx, Homebrew, AUR, and standalone packaging options.RELEASE.md: release validation and tagging checklist.ROADMAP.md: planned follow-up work.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file plex_tui-0.4.7.tar.gz.
File metadata
- Download URL: plex_tui-0.4.7.tar.gz
- Upload date:
- Size: 7.7 MB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7a5195b6b1ea1b542458ecaf1ddc16140fcf93f3d95317edc56660bb3d21dfc7
|
|
| MD5 |
1ff7f45d11dc91468309fc05f8dad0ce
|
|
| BLAKE2b-256 |
dccd1442a73cef232d2e84a3a67e04d2761295dec1b6cee2b6367dd6d3481cf7
|
Provenance
The following attestation bundles were made for plex_tui-0.4.7.tar.gz:
Publisher:
bump.yml on so1omon563/plex-tui
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
plex_tui-0.4.7.tar.gz -
Subject digest:
7a5195b6b1ea1b542458ecaf1ddc16140fcf93f3d95317edc56660bb3d21dfc7 - Sigstore transparency entry: 1877834008
- Sigstore integration time:
-
Permalink:
so1omon563/plex-tui@4c293925079026cac08909a9729de2eef4abdcc0 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/so1omon563
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
bump.yml@4c293925079026cac08909a9729de2eef4abdcc0 -
Trigger Event:
pull_request
-
Statement type:
File details
Details for the file plex_tui-0.4.7-py3-none-any.whl.
File metadata
- Download URL: plex_tui-0.4.7-py3-none-any.whl
- Upload date:
- Size: 63.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
28a8507b48970afd05a7f21a5516898140e64fa167b77c9b2008f07e38d460ce
|
|
| MD5 |
9fddd424beb72f99f09a494623974f2f
|
|
| BLAKE2b-256 |
f2b05d2c8fb6ec3ce7b06b48b2dcb412931fb1af2554197a8447f964c3303772
|
Provenance
The following attestation bundles were made for plex_tui-0.4.7-py3-none-any.whl:
Publisher:
bump.yml on so1omon563/plex-tui
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
plex_tui-0.4.7-py3-none-any.whl -
Subject digest:
28a8507b48970afd05a7f21a5516898140e64fa167b77c9b2008f07e38d460ce - Sigstore transparency entry: 1877834074
- Sigstore integration time:
-
Permalink:
so1omon563/plex-tui@4c293925079026cac08909a9729de2eef4abdcc0 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/so1omon563
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
bump.yml@4c293925079026cac08909a9729de2eef4abdcc0 -
Trigger Event:
pull_request
-
Statement type: