If you're old-fashioned like me and still enjoy flicking through the next week of TV films, this project is for you. Pex is as my personal way to dig through two weeks of Plex DVR listings, decide what to record, and—most importantly—see which airings I already own in Plex, all in a super-visual grid.
Pex helps you:
- Browse up to 14 days of film listings in the Plex EPG with a poster-forward layout.
- Choose to visually dim movies you already own or hide them from the grid entirely.
- Spot HD airings, including HD upgrades for titles you currently only have in SD.
- See at a glance which films are already scheduled to record in Plex.
- Bring channel art, genre groupings, and on-demand TMDb ratings (click the ⭐ button in the detail pane) into the experience while keeping everything cached locally for speedy, offline-friendly launches.
To get rolling, copy config.example.json (or the platform-specific samples in make_portable/) to config.json and fill in your Plex database paths. The only real prerequisite is that you're using Plex DVR with its standard EPG—Pex mirrors Plex's own library database to figure out what you already own, so there's no filesystem scraping or directory configuration to babysit.
Because the app is written in Rust, it runs on Windows, Linux, and macOS, and it's easy to tweak. Grab the code, point your favourite AI at the included primer, and you'll have a head start on customising things for your own setup—especially if your filenames don't follow the Title (Year) pattern the app expects today.
- This started as a personal project: each week I sift through upcoming TV movies to decide what to record.
- The stock Plex web UI felt too barebones for that workflow, so I wanted a richer experience for anyone in the Plex community who still enjoys browsing broadcast schedules.
- While the app concentrates on TV films, the bundled SQLite explorer tools make it easy for others to tweak or extend it for different Plex data.
- Developed primarily on Windows 11 with WSL Fedora 42; both environments are exercised regularly. macOS hasn't been tested first-hand, but the Rust/egui stack produces native binaries for both x86_64 and ARM64, so it should run wherever those architectures are supported (Intel/AMD).
- Releases live on the GitHub Releases page; each tagged version includes portable bundles.
- Use the scripts in
make_portable/to produce fresh zips before a release; the outputs land inmake_portable/dist/ready for upload. - On Windows run
pwsh ./release_windows.ps1 -Version 1.2.3to build, tag, push, package, and publish/update the GitHub release with the Windows bundle. - On Linux (including WSL) run
pwsh ./release_linux.ps1 -Version 1.2.3to do the same for the Linux bundle. Each script can safely rerun and will add or replace only its platform’s asset. - Generated binaries are not checked into git; attach them to the corresponding GitHub release instead.
- Downloads & Releases
- Overview
- Prerequisites
- Getting Started
- Configuration Reference
- Data & Cache Locations
- Typical Workflows
- Troubleshooting & Diagnostics
- Development Notes
- Legal
Highlights:
- 🚀 Fast start-up – poster and channel artwork are cached and uploaded on demand, keeping the UI responsive even on large guides.
- 🗂️ Powerful filtering – search, day-range slicing, HD-only toggle, channel and genre selectors, plus multiple sort orders.
- ?? Owned library awareness - mirrored Plex library data feeds owned/HD badges and "recorded on" timestamps directly into the grid.
- 🎯 DVR awareness – scheduled recordings show a red REC badge and detail call-out pulled from the Plex library database.
- 🎨 Detail-rich panels – long-title scroller with copy button, channel badges, optional TMDb ratings, and formatted descriptions.
- 🧰 Operator controls – quick refresh/clear actions for poster and owned caches as well as worker tuning knobs.
Pex runs on Windows, macOS, and Linux (including WSL) using egui/eframe for the native UI.
src/main.rs/lib.rs– launch the egui app and wire tracing.config.rs– parsesconfig.json, ownsOwnedSourceKind, and exposes helper paths for the copied databases.app/mod.rs– central application state, message pump, advanced actions, and egui integration.prep.rs– copies the Plex databases (daily freshness), queries poster rows, and emitsPrepMsg.prefetch.rs/gfx.rs– background workers + GPU upload helpers for poster textures.cache.rs/prefs.rs– cache directory helpers, poster/file pruning, persisted UI preferences.owned/– Plex-library scanners that build owned sidecars for fast restarts.scheduled.rs– loads scheduled DVR entries frommedia_grabs,media_subscriptions, andmetadata_subscription_desired_items.detail.rs,filters.rs,types.rs,utils.rs– UI panels, filtering & sorting logic, shared structs, and formatting helpers.ui/– splash/grid/top bar egui widgets.
assets/– embedded icon and other compile-time resources.bin/– optional CLI entry-points used during development.
epg_explorer_tool/db_explorer.rs– CLI for poking at the EPG SQLite.library_db_explorer.rs– companion CLI for the Plex library database (owned + DVR state).*_ai_primer.yaml– primers that document how the helpers should be extended.
make_portable/– scripts and template config for packaging a portable build.db/– working copies of the Plex databases (populated on first run)..pex_cache/– generated cache directory (posters, owned sidecars, UI prefs).config.example.json– starter configuration; copy toconfig.jsonfor local runs.
- Plex DVR/EPG must be enabled so that
tv.plex.providers.epg.cloud-*.db(and the accompanying WAL/SHM files) exist on disk. - Common locations:
- Windows:
%LOCALAPPDATA%\Plex Media Server\Plug-in Support\Databases - Linux (service install):
/var/lib/plexmediaserver/Library/Application Support/Plex Media Server/Plug-in Support/Databases - Docker: bind the Plex config volume; copy the database out via the host.
- Windows:
- Pex expects a working copy in
db/plex_epg.db. You can supply it manually or pointplex_epg_db_sourceat the live Plex database so Pex pulls in a fresh copy once per day.
- Rust toolchain 1.74 or newer (
rustup toolchain install stable) - Cargo (bundled with Rust)
- Git (to clone the repository)
- TMDb API key (optional, but recommended). Add your personal TMDb V3 key if you want to fetch TMDb vote-average ratings from the detail pane.
-
Clone and bootstrap
git clone https://github.com/AnicetusCer/pex.git cd pex cp config.example.json config.json -
Populate the database folder
- Copy your Plex EPG SQLite file into
db/plex_epg.db, or - Set
plex_epg_db_sourceinconfig.jsonto the path of Plex’s live DB so Pex can refreshdb/plex_epg.dbautomatically. - Do the same for your Plex library database: copy it into
db/plex_library.dbor setplex_library_db_sourceand let Pex maintain the mirror. Owned detection relies on this copy so you don’t have to crawl your filesystem.
- Copy your Plex EPG SQLite file into
-
Edit
config.json(see the Configuration Reference). -
Build and run the app
cargo run --release
The first launch will
- copy the Plex database if
plex_epg_db_sourceis set, - copy the Plex library database if
plex_library_db_sourceis set, - load owned titles from the mirrored library database, and
- start poster prefetching.
Subsequent runs reuse the cached data, so they reach the UI much faster.
- copy the Plex database if
Pex reads config.json from the repository root. All keys are optional unless
otherwise stated; absent keys fall back to reasonable defaults.
| Key | Type | Default | Description |
|---|---|---|---|
plex_epg_db_source |
string or null |
null |
When set, Pex copies the live Plex EPG SQLite file into db/plex_epg.db no more than once every 24 hours. Leave unset if you manage db/plex_epg.db yourself. |
plex_library_db_source |
string or null |
null |
When set, Pex copies Plex’s library SQLite file into db/plex_library.db on the same 24-hour freshness cadence. Leave unset if you manage db/plex_library.db yourself. |
cache_dir |
string or null |
.pex_cache |
Root folder for poster caches, owned sidecars, and UI prefs. |
tmdb_api_key |
string or null |
null |
TMDb V3 API key for vote-average ratings. Leave unset to disable the rating button. |
log_level |
string | info |
Controls tracing output (trace, debug, info, warn, error). |
Example configuration:
{
"plex_epg_db_source": "\\\\nas\\PlexConfig\\Databases\\tv.plex.providers.epg.cloud.db",
"plex_library_db_source": "\\\\ds\\PlexMediaServer\\AppData\\Plex Media Server\\Plug-in Support\\Databases\\com.plexapp.plugins.library.db",
"cache_dir": ".pex_cache",
"tmdb_api_key": "YOUR-TMDB-KEY",
"log_level": "info"
}Tip: on Linux paths use forward slashes; on Windows double any backslashes in JSON strings or switch to forward slashes.
plex_epg_db_source– path totv.plex.providers.epg.cloud*.dbon the Plex server. Pex copies it intodb/plex_epg.db(refreshing at most once every 24 h).plex_library_db_source– path tocom.plexapp.plugins.library.db. Pex clones it intodb/plex_library.dband uses it for owned detection and DVR badges.
You can locate these files by:
| Platform | Default location |
|---|---|
| Windows (desktop) | %LOCALAPPDATA%\Plex Media Server\Plug-in Support\Databases\ |
| Windows (service mode) | %PROGRAMDATA%\Plex Media Server\Plug-in Support\Databases\ |
| Linux | /var/lib/plexmediaserver/Library/Application Support/Plex Media Server/Plug-in Support/Databases/ |
| Synology | /var/packages/Plex Media Server/target/Plex Media Server/Plug-in Support/Databases/ |
| Docker | Whatever host path you bind to /config/Library/Application Support/Plex Media Server/Plug-in Support/Databases/ |
Copy both .db files plus their -wal/-shm companions (if present) while Plex is stopped, or let Pex copy from the live path on each start.
cache_dir– move the poster/owned/UI cache elsewhere; relative paths are resolved relative to the repo root.tmdb_api_key– add your TMDb V3 API key to enable the on-demand rating button.log_level– override the default tracing verbosity (trace→ most verbose).
PEX_DISABLE_PREFETCH=1– skip poster downloads (useful when testing offline modes).RUST_LOG=info(ordebug) – surface prep/owned/scheduled traces in the terminal.
db/plex_epg.db— working copy of the Plex EPG database (plus WAL/SHM files created on demand).db/plex_library.db— optional working copy of Plex’s library database, copied whenplex_library_db_sourceis configured.- DVR metadata (
media_grabs,media_subscriptions,metadata_subscription_desired_items) is read fromdb/plex_library.dbto drive the REC badge and owned detection. .pex_cache/— posters, channel icons, owned sidecars, and UI preference files. Poster images older than 14 days are pruned automatically on startup.db/and.pex_cache/are created automatically; you can relocate caches by settingcache_dirin the config file.
- Copy or configure access to the Plex EPG DB (and optionally the library DB).
- Populate
config.jsonwith your Plex database paths and OMDb settings. - Launch with
cargo run --release. - Let the initial owned scan and poster prefetch finish (progress appears in the status bar). Large libraries may take several minutes.
- Launch the app; the UI resumes where you left off.
- If
plex_epg_db_sourceorplex_library_db_sourceis set, Pex checks once per day whether the respective database copy needs refreshing. - Scheduled recordings sync automatically after poster prep; queued movies show a red REC badge in the grid and detail panel.
- Owned and HD badges stay up-to-date thanks to incremental scanning of the mirrored Plex library database.
- Use Advanced ▸ Refresh owned scan after adding/removing many files.
- Use Advanced ▸ Clear owned cache only when you want a full rescan from scratch (e.g., after reorganising folder structures).
- Advanced ▸ Clear & rebuild poster cache wipes cached artwork and immediately restarts prefetching.
See make_portable/README.md for instructions on
producing a self-contained ZIP using the provided PowerShell/Bash scripts.
- Status bar stuck on Stage 2/4 (DB copy): verify the
plex_epg_db_sourceandplex_library_db_sourcepaths are reachable and readable. - Owned scan never completes: check the Advanced panel log for the most recent message, ensure
plex_library_db_sourceis set correctly, and confirm the copieddb/plex_library.dbcontains your movie metadata. - REC badge missing: confirm
plex_library_db_sourceis configured, the copieddb/plex_library.dbcontains up-to-datemedia_subscriptionsrows, and you restarted after scheduling the recording. - Missing posters: confirm outbound network access to the artwork URLs and that the cache directory is writable. Pex prunes posters older than 14 days automatically, so re-open the app after a while to fetch fresh artwork.
- HD badge looks wrong: rescan the owned library from Advanced ▸ Refresh owned scan after updating your Plex library database.
- Logging: set
log_leveltodebugand relaunch to capture richer logs in the console.
- Format the code with
cargo fmt. - Run tests with
cargo test. - Optional:
cargo clippy --all-targets -- -D warnings(requires the Clippy component). - DB inspection helpers:
cargo run --bin db_explorer metadata_items 10cargo run --bin library_db_explorer -- --tables
- Licensed under the PEX Attribution License (PAL).
- TMDb ratings are fetched via the TMDb API; please respect their usage terms and attribution requirements.
- Plex is a registered trademark of Plex, Inc. This project is an independent client that reads the Plex DVR database.
- Additional third-party notices are listed in
NOTICE.
