GoplexCLI
A powerful, fast, and elegant command-line interface for browsing and streaming media from your Plex server.
Features
- Browse Media — Quickly browse your entire Plex library using fzf's fuzzy finder
- Search — Pass a search term directly to find movies and TV shows instantly
- Multi-Select — Select multiple items with TAB for batch downloads or sequential playback
- Download Queue — Add items to a persistent queue for batch downloads later
- Continue Watching — Resume playback from where you left off, with progress tracked via MPV IPC
- Recently Added — Jump straight to the newest items in your library
- Rich Previews — View detailed metadata (rating, duration, cast, summary) in fzf's preview pane
- Stream with MPV — Watch movies and TV shows directly with MPV player
- Download with Rclone — Download media files with a real-time progress bar UI
- Remote Streaming — Publish streams for playback on other devices via mDNS discovery and a web UI
- LAN Cache Sync — Copy the media cache between your computers over the local network instead of reindexing each one from Plex
- Transfer to WebDAV — Push media to gowebdav servers discovered on your LAN via mDNS
- Transfer to Outplayer — Upload media to the Outplayer iOS app over Wi-Fi to multiple configurable targets
- SenPlayer Integration — Play or download media in SenPlayer via deep links (macOS)
- Sort & Filter — Sort your library by name, date added, year, rating, or duration
- Smart Caching — Cache your media library locally for instant offline browsing
- Multi-Server Support — Connect to and manage multiple Plex servers
- Hierarchical TV Browsing — Drill down through Show → Season → Episode
- Self-Updating — Update to the latest release with a single command
- Shell Completions — Tab completions for Bash, Zsh, Fish, and PowerShell
- Cross-Platform — Works on macOS, Linux, and Windows (AMD64 and ARM64)
- Beautiful UI — Built with Charm libraries for a polished terminal experience
Prerequisites
Before using GoplexCLI, ensure you have the following installed:
- fzf — Fuzzy finder for browsing media (required)
- macOS:
brew install fzf
- Linux:
sudo apt install fzf or sudo pacman -S fzf
- Windows:
choco install fzf or winget install junegunn.fzf
- mpv — Media player for streaming (required for Watch)
- macOS:
brew install mpv
- Linux:
sudo apt install mpv or sudo pacman -S mpv
- Windows: Download from mpv.io
- rclone — For downloading media files (required for Download)
- macOS:
brew install rclone
- Linux:
sudo apt install rclone or download from rclone.org
- Windows: Download from rclone.org
- chafa (optional) — Terminal image viewer for poster art in the TUI browser
- macOS:
brew install chafa
- Linux:
sudo apt install chafa
Installation
From Releases
Download the latest binary for your platform from the Releases page and place it somewhere in your PATH.
From Source
Requires Go 1.24+.
git clone https://github.com/joshkerr/goplexcli.git
cd goplexcli
make build
This builds the goplexcli binary (or goplexcli.exe on Windows). The fzf preview pane is rendered by a hidden __preview subcommand of the same binary, so there's nothing else to install.
Then install to your PATH:
# macOS/Linux
sudo cp goplexcli /usr/local/bin/
# Or use make
make install
Desktop GUI
GoplexCLI also ships a cross-platform desktop app (macOS, Windows, Linux) with a
modern poster-grid interface. It reuses the same engine as the CLI — Plex
access, the local cache, MPV playback with progress tracking, and rclone
downloads — so logging in or indexing from either side is shared.
The GUI lives in gui/ and is built with Wails v2
(Go backend + a React/TypeScript frontend). Playback still launches MPV
externally and downloads still use rclone, so those prerequisites apply just
as they do for the CLI.
Building the GUI
Requires Go 1.24+, Node.js 18+, and the Wails CLI:
make gui-deps # one-time: installs the Wails CLI to GOPATH/bin
make gui-dev # build the frontend and run with Wails development tools
make gui-build # build a native binary into gui/build/bin/
make gui-install # Windows: install per-user and create a Start Menu shortcut
On Windows, make gui-install DESKTOP=1 also creates a desktop shortcut. The
icon-enabled executable is installed under
%LOCALAPPDATA%\Programs\GoplexCLI; administrator privileges are not required.
(Equivalently, cd gui && wails dev / wails build.)
Platform notes
| Platform |
Webview / extra deps |
| Windows |
WebView2 runtime (preinstalled on Windows 11) |
| macOS |
WKWebView (built in) |
| Linux |
libgtk-3 and libwebkit2gtk-4.0 (sudo apt install libgtk-3-dev libwebkit2gtk-4.0-dev) |
Using the GUI
- Sign in with your Plex account and pick the servers to index.
- Build library to populate the local cache (shows live progress).
- Browse Movies, TV Shows, Recently Added, and Continue Watching from the
sidebar; search filters the grid instantly. On the Movies grid, filter by
genre and sort by title, year, date added, rating, or duration
(ascending or descending).
- Open any title for details, then Play/Resume (MPV) or Download
(rclone, with live progress in the Downloads panel). TV shows drill into
Season → Episode with multi-select for playlist playback or batch downloads.
- Keep the library fresh from Settings → Library: Update (fetch only
newly-added titles), Reindex (rebuild from scratch), or Sync from LAN
(pull the cache from another computer running GoplexCLI — see below).
Poster grids request compact Plex-generated renditions and keep them in a
bounded local cache under the GoplexCLI cache directory. Visible posters are
prioritized and the on-screen window is warmed via the backend so jumping
around a large library fills in quickly without re-downloading artwork.
Quick Start
# 1. Authenticate with Plex
goplexcli login
# 2. Index your media library
goplexcli cache reindex
# 3. Browse and play
goplexcli browse
Usage
Quick Search
Pass a search term directly to find matching media:
goplexcli "The Lincoln Lawyer"
goplexcli -d "time travel" # Also search descriptions/summaries
Movies can be played immediately. TV shows drill into Season → Episode selection.
Browse
goplexcli browse
goplexcli browse --dry-run # Show what would download without downloading
goplexcli browse --dest ~/Movies # Override download directory
The browse flow:
- Pick a category — Movies, TV Shows, All, Recently Added, Continue Watching, or View Queue
- Select media — Fuzzy search with preview pane (Ctrl+P to toggle). TAB for multi-select.
- Pick an action — Watch, Download, Transfer to WebDAV, Transfer to Outplayer, SenPlayer Play, SenPlayer Download, Add to Queue, or Stream
For TV Shows, the picker drills hierarchically: Show → Season → Episode(s).
Sort
Sort and display media from your cache:
goplexcli sort added --desc --limit 20 # Last 20 added items
goplexcli sort name --asc # A-Z by title
goplexcli sort rating --desc --limit 10 # Top 10 rated
goplexcli sort year --desc --type movies # Newest movie releases
goplexcli sort duration --desc -i # Longest items, open in picker
Available fields: name, added, year, rating, duration
Flags:
--desc / --asc — Sort direction (defaults: descending for numeric fields, ascending for name)
--limit N — Max items to display (default 20)
--type — Filter: movies, shows, or all
-i / --interactive — Open results in the interactive browser for playback/download
Cache Management
goplexcli cache reindex # Rebuild entire cache from scratch
goplexcli cache update # Incremental update with new media
goplexcli cache info # Show cache statistics
goplexcli cache search "title" # Search in both cache and Plex server
Server Management
goplexcli server list # List configured servers
goplexcli server enable "Server Name" # Enable a server for indexing
goplexcli server disable "Server Name" # Disable a server
goplexcli server remove "Server Name" # Remove a server entirely
Stream Discovery
Publish a stream from one device and play it on another over the local network:
# On the publishing device: browse → select → choose "Stream"
goplexcli browse
# On the consuming device: discover and play
goplexcli stream
The stream server also exposes a web UI at http://<ip>:8765 with deep links to Infuse, VLC, OutPlayer, SenPlayer, IINA, and VidHub — play directly on an iPad, iPhone, or Apple TV from your browser.
Self-Update
goplexcli update # Download and install the latest release
goplexcli update --check # Check for updates without installing
Shell Completions
# Bash
source <(goplexcli completion bash)
# Zsh
goplexcli completion zsh > "${fpath[1]}/_goplexcli"
# Fish
goplexcli completion fish | source
# PowerShell
goplexcli completion powershell | Out-String | Invoke-Expression
WebDAV Transfer
Discover gowebdav servers on your LAN and push media to them:
goplexcli webdav discover # Scan for gowebdav servers
goplexcli webdav set-creds # Set shared username/password for transfers
Then during browse, select media and choose Transfer to WebDAV to push files to the discovered server.
Outplayer Transfer
Outplayer is an iOS media player with a "Wi-Fi transfer"
feature that runs a small HTTP upload server on your device. Configure one or
more Outplayer targets and push media to them straight from your rclone remotes
(the file is streamed through, never staged on local disk):
goplexcli outplayer add # Add a target (name + URL, e.g. http://192.168.0.34)
goplexcli outplayer list # List targets and their enabled/disabled status
goplexcli outplayer disable iPhone # Hide a target from the transfer menu
goplexcli outplayer enable iPhone # Show it again
goplexcli outplayer remove iPhone # Delete a target
Enable Wi-Fi transfer in Outplayer (which shows the address to use), add it as a
target, then during browse select media and choose Transfer to Outplayer.
You can also transfer an entire queue: from View Queue choose Transfer to
Outplayer (or Transfer to WebDAV) to send every queued item — the queue is
left intact afterwards. The Transfer to Outplayer action only appears when at
least one target is enabled, so disabling all targets hides it. Uploads default
to the device root; Outplayer's built-in folders (e.g. Inbox) are not writable.
LAN Cache Sync
If you run GoplexCLI on more than one computer, you can copy an already-built
media cache between them over your local network instead of reindexing each one
from Plex — for a large library this takes seconds rather than minutes.
One machine serves its cache; the other pulls it (only if the served
cache is newer):
# On the source machine — advertise and serve its cache (runs until Ctrl-C):
goplexcli sync serve
# --port N serve on a specific port (default 47820)
# --update-interval 30m refresh this cache from Plex on an interval so peers
# stay current (default 1h; 0 disables)
# On another machine — pull the newest cache found on the LAN:
goplexcli sync pull
# --peer ghost-2.local pull directly from a host, bypassing discovery
# --peer 192.168.1.20:47820 ...or an explicit host:port
Machines are found automatically via mDNS. Some networks block mDNS (Windows
firewall, VPNs, Wi-Fi client isolation); if auto-discovery doesn't find the
other computer, set the peer directly — either with --peer, or persistently in
config so the GUI's Sync from LAN button and sync pull both use it:
{ "sync_peer": "ghost-2.local" }
In the desktop GUI this is Settings → Preferences → Sync from computer (LAN),
and the Sync from LAN button on the Library tab performs the pull. The GUI
also serves its cache automatically while it is open, so it can be the source for
other machines without running sync serve.
The transferred cache carries the source machine's Plex server URLs and rclone
path mappings, so it works as-is only when those match on both machines. It never
contains Plex tokens (those live in config, not the cache).
Other Commands
goplexcli login # Authenticate with Plex (supports multi-server)
goplexcli config # Show current configuration
goplexcli version # Show version
Configuration
Configuration is stored in a platform-specific directory:
| Platform |
Path |
| macOS |
~/.config/goplexcli/config.json |
| Linux |
~/.config/goplexcli/config.json (or $XDG_CONFIG_HOME) |
| Windows |
%APPDATA%\goplexcli\config.json |
Config File
{
"plex_token": "your-auth-token",
"servers": [
{
"name": "My Plex Server",
"url": "http://192.168.1.100:32400",
"enabled": true
}
],
"plex_username": "your-username",
"mpv_path": "mpv",
"rclone_path": "rclone",
"fzf_path": "fzf",
"download_dir": "~/Downloads/Plex",
"sync_peer": "ghost-2.local",
"path_mappings": [
{ "prefix": "/mnt/media/tv/", "remote": "gdrive:Media/TV/" },
{ "prefix": "/mnt/media/", "remote": "gdrive:Media/" }
],
"webdav_user": "user",
"webdav_pass": "password",
"webdav_dir": "",
"outplayer_targets": [
{ "name": "iPhone", "url": "http://192.168.0.34", "dir": "", "enabled": true }
]
}
- servers — One or more Plex servers, individually enabled/disabled
- mpv_path, rclone_path, fzf_path — Override tool paths if not in PATH
- download_dir — Default download destination (
~ is expanded). Override per-run with --dest.
- sync_peer — Hostname/IP (optionally
host:port) of another computer to pull the cache from with LAN Cache Sync. Blank falls back to mDNS auto-discovery.
- path_mappings — Translate Plex file paths to rclone remotes. Longest matching prefix wins. Run
cache reindex after changing.
- webdav_user, webdav_pass, webdav_dir — Shared credentials and optional subdirectory for gowebdav transfers (set via
goplexcli webdav set-creds)
- outplayer_targets — Outplayer Wi-Fi transfer destinations, each with a
name, url, optional dir, and enabled flag (managed via goplexcli outplayer add/list/enable/disable/remove)
Setting Up rclone
Downloads pull the original media file directly from wherever your Plex
library is stored (a cloud drive, a remote server, a NAS, …) using
rclone — not by re-streaming from Plex. Plex reports each
item's on-disk file path; GoplexCLI rewrites that path into an rclone remote
path and runs rclone copyto. So there are two things to configure: an rclone
remote that can reach your media, and a path mapping that points Plex's
file paths at that remote.
1. Install rclone (see Prerequisites) and confirm it's on
your PATH:
rclone version
2. Create a remote for the storage your Plex library lives on:
rclone config
Follow the prompts to add a remote (Google Drive, S3, SFTP, WebDAV, …). Give it
a memorable name — that name is what you reference in the mapping below. rclone
saves this in its own config (~/.config/rclone/rclone.conf); GoplexCLI only
references the remote by name, never its credentials. Verify it can see your
media:
rclone lsd myremote:
3. Find your Plex file paths. Check what path Plex reports for an item — via
goplexcli cache search "title", Plex's own Get Info → file path, or by
looking on the Plex server. You'll see something like:
/mnt/media/tv/The Show/Season 01/episode.mkv
4. Map the Plex path prefix to the rclone remote with path_mappings in
your config file. Each mapping replaces a leading prefix with
remote:
"path_mappings": [
{ "prefix": "/mnt/media/tv/", "remote": "myremote:Media/TV/" },
{ "prefix": "/mnt/media/", "remote": "myremote:Media/" }
]
With the mapping above, the example path becomes
myremote:Media/TV/The Show/Season 01/episode.mkv. The longest matching
prefix wins, so list more specific prefixes first. The text after the colon is
the location inside the remote — adjust it so it matches where those files
actually live (the prefix and remote roots often line up, but they don't have
to).
5. Re-index and test. Path mappings are applied when the cache is built, so
re-index after changing them, then download something:
goplexcli cache reindex
goplexcli browse # pick an item → Download
If a download fails with an "object/directory not found" error, the mapped path
doesn't match the remote's layout — check it with rclone ls "myremote:Media/TV/…"
and adjust the mapping.
Tips
- Set
download_dir to control where files land (GUI: Settings → Download
directory; CLI: --dest). It defaults to the current directory.
- If rclone isn't on your PATH, set
rclone_path to its full path (GUI:
Settings → rclone path).
- With no
path_mappings, a legacy fallback strips a /home/joshkerr/
prefix and infers the remote from the first path segment. That only fits the
original author's setup, so configure your own path_mappings.
How It Works
Playback Progress
When you watch media through GoplexCLI, progress is tracked via MPV's IPC socket and reported back to your Plex server in real time. After playback ends, progress is also written to the local cache so items appear in Continue Watching immediately — no reindex needed.
Progress made on other Plex clients requires a cache reindex to refresh.
Resume Playback
If a media item has saved progress, you'll be prompted to resume from your last position or start from the beginning.
Download Queue
The queue is persistent between sessions and concurrent-safe (uses file locking). Multiple instances can add items while another downloads. Duplicate items are automatically deduplicated by key.
Rclone Path Conversion
GoplexCLI translates Plex on-disk file paths to rclone remote paths for downloads, then runs rclone copyto to fetch the original file. See Setting Up rclone for the full walkthrough; in short, path_mappings rewrites a Plex path prefix into a remote:path (longest prefix wins), with a legacy /home/joshkerr/ fallback when none is configured.
Troubleshooting
| Problem |
Solution |
| "fzf not found" |
Install fzf (see Prerequisites) |
| "mpv not found" |
Install mpv (see Prerequisites) |
| "rclone not found" |
Install rclone and run rclone config to set up remotes |
| "Cache is empty" |
Run goplexcli cache reindex |
| Stream discovery not working |
Ensure both devices are on the same network. Check firewall allows mDNS (port 5353 UDP) and HTTP (port 8765 TCP). |
| Web UI not accessible |
Verify the URL shown during stream publishing. Ensure port 8765 is not blocked. |
| Deep links not opening on iOS |
Ensure the target app (Infuse, VLC, etc.) is installed. Try copy/paste of the stream URL. |
Project Structure
goplexcli/
├── cmd/goplexcli/ # CLI entry point and all commands
├── gui/ # Cross-platform desktop app (Wails v2 + React)
│ ├── *.go # Backend bindings reusing the internal/ packages
│ └── frontend/ # React + TypeScript + Tailwind UI
├── internal/
│ ├── cache/ # JSON-based media cache
│ ├── config/ # Configuration loading/saving/validation
│ ├── download/ # Rclone download with progress UI
│ ├── errors/ # Shared error types
│ ├── interfaces/ # Shared interfaces
│ ├── logging/ # Logging utilities
│ ├── outplayer/ # Outplayer Wi-Fi transfer uploads (streamed via rclone)
│ ├── player/ # MPV player wrapper
│ ├── plex/ # Plex API client (SDK + direct HTTP)
│ ├── preview/ # fzf preview pane renderer
│ ├── progress/ # MPV IPC progress tracker
│ ├── queue/ # Persistent download queue with file locking
│ ├── stream/ # Stream server, mDNS, and web UI
│ ├── termuxfix/ # Termux/Android compatibility
│ ├── ui/ # fzf integration, TUI browser, resume prompts
│ ├── update/ # Self-update from GitHub releases
│ └── webdav/ # gowebdav server discovery via mDNS
├── Makefile
├── go.mod
└── go.sum
Dependencies
Go Libraries:
External Tools:
- fzf — Fuzzy finder
- mpv — Media player
- rclone — Cloud storage transfers
- chafa (optional) — Terminal image rendering
Contributing
Contributions are welcome! Please feel free to submit issues or pull requests.
License
MIT License — See LICENSE for details.