Feature Details
1. .plexcached Backup System
When files are moved to cache, the original array file is renamed to filename.plexcached instead of being deleted. This prevents data loss if the cache drive fails. Includes:
One-time migration to create backups for existing cached files
--restore-plexcached emergency restore flag
Smart handling of Radarr/Sonarr upgrades (detects both filename changes and in-place upgrades via filesize comparison)
2. OAuth PIN-Based Authentication
Replaces manual token entry with Plex's official PIN-based OAuth flow:
User visits plex.tv/link and enters a 4-character PIN
Automatic token retrieval and validation
Re-authentication option without full setup re-run
3. Cache Retention Period
New cache_retention_hours setting prevents files from being moved back to array immediately after caching. Solves the "file bouncing" problem when users are actively watching.
4. Watchlist Retention Period
New watchlist_retention_days setting auto-expires cached watchlist items after a configurable period. Includes:
RSS feed fallback for remote users (who can't use API for watchlist)
Per-user watchlist attribution in logs
Proper timezone handling for RSS pubDate timestamps
5. Cache Size Limit
New cache_limit setting to cap total cache usage.
6. Setup Wizard
Auto-detects missing settings and prompts to add them
OAuth flow integration
refresh_users option to update local/remote detection
7. Unraid Mover Exclusion File (manual custom entries)
There is now a new generated file (unraid_mover_exclusions.txt) which allows for manually-entered custom exclusion links.
Those custom links must be entered above the marker line. See wiki for more details.
8. Multi-Path Mapping Support
Problem: The single plex_source → real_source mapping fails for users with complex folder structures, nested libraries, or libraries with different base paths (e.g., /tv-a-g/, /tv-h-p/, /tv-q-z/).
Solution: New path_mappings array with per-library configuration:
{
"path_mappings": [
{
"name": "TV A-G",
"plex_path": "/media/tv-a-g/",
"real_path": "/mnt/user/data/media/tv-a-g/",
"cache_path": "/mnt/cache/data/media/tv-a-g/",
"cacheable": true,
"enabled": true
},
{
"name": "TV H-P",
"plex_path": "/media/tv-h-p/",
"real_path": "/mnt/user/data/media/tv-h-p/",
"cache_path": "/mnt/cache/data/media/tv-h-p/",
"cacheable": true,
"enabled": true
},
{
"name": "4K Movies",
"plex_path": "/media/movies-4k/",
"real_path": "/mnt/user/data/media/movies-4k/",
"cache_path": null,
"cacheable": false,
"enabled": false
}
]
}Key features:
- Per-library path mappings for complex folder structures
- Per-library enable/disable (silences logging for disabled libraries)
- Non-cacheable flag for libraries you don't want cached (e.g., 4K content)
--show-mappingsCLI flag for diagnostics- Backwards compatible migration from legacy
plex_source/real_source - Legacy arrays deprecated with startup warning
Related Issue: #28
9. Smart Cache Eviction System
Problem: When cache limit is reached, new files are simply skipped (first-come-first-served). No mechanism to evict lower-priority items for higher-priority ones.
Solution: Priority scoring (0-100) for each cached file:
| Factor | Score Impact |
|---|---|
| OnDeck source | +20 |
| User count | +5/user (max +15) |
| Cache recency | +5 to +15 |
| Watchlist age | +10 fresh, -10 if >60d |
| Episode position | +15 current, +10 next episodes |
New settings:
{
"cache_eviction_mode": "smart",
"cache_eviction_threshold_percent": 90,
"eviction_min_priority": 60
}CLI: --show-priorities displays current cache priority scores
10. Web-Based Log Analyzer
Location: docs/index.html (available to test at https://studionirin.github.io/PlexCache-R/)
A client-side tool to help debug user-submitted log files:
- Drag-drop or paste log files
- 20+ error/warning pattern detection
- Configuration extraction (dry-run, path mappings, users)
- Section-based navigation (Startup, OnDeck, Watchlist, RSS, etc.)
- Filterable log viewer with search (Ctrl+F, F3 navigation)
- User-specific filtering dropdown
- "Copy Diagnosis" button for GitHub issues
- Dark theme UI
11. Code Quality Audit (5 Phases)
Systematic refactoring to reduce complexity and improve maintainability:
| Phase | Focus | Key Changes |
|---|---|---|
| 1 | Dead code removal | Removed unused imports, consolidate utilities |
| 2 | Deduplication | JSONTracker base class, mover detection helpers
|
| 3 | Extract methods | _initialize_components(), smaller focused methods
|
| 4 | Exception handling | Consistent patterns, better error messages |
| 5 | Final cleanup | Docstrings, type hints, logging consistency |
12. Logging Improvements
Cleaner INFO output:
| Before | After |
|---|---|
| 25+ lines of per-user OnDeck counts | OnDeck: 157 items from 16 users
|
| 90+ retention hold messages | Grouped by title with count |
| Per-file "no longer needed" messages | Restoring from backup (6 files) / Moving to array (3 files)
|
Structured user tags:
[USER:Brandon] Fetching onDeck media...
[USER:Brandon] OnDeck found: Movie.mkv
Enhanced --verbose diagnostics:
- Startup diagnostics (platform, running user, uid/gid)
- File ownership logging after copy operations
- Folder deletion verification with hidden file visibility
- Diagnostic summary at end of run
###Bug Fixes
- Fix movies not being moved back to array - (Issue #21)
- Fix watched media bypassing retention period
- Fix stale exclude list entries not being cleaned up
- Fix home user vs managed user token handling
- Fix cross-user data leakage with separate API instances
- Fix notification handlers loading before config
- Many path handling and edge case fixes
- Fix double path conversion (#28) - Paths already in
real_sourceformat are no longer double-converted whenplex_sourceis/ - Graceful error handling (#27) - Script now skips inaccessible files instead of crashing
- Fix RSS author lookup - Plex changed the author ID format in RSS feeds from numeric ID to UUID. Now extracts UUID from user thumb URL for proper username attribution
- Self-healing exclude list - Stale entries (files no longer on cache) are automatically removed at startup
- Prevent multiple instances - Lock file ensures only one PlexCache instance runs at a time
- Improved cache logging - Shows both total cache drive usage and PlexCache-tracked size separately
- Store user UUID - User entries now include UUID for debugging RSS author issues. Run
--refresh-usersto populate - Fix
--restore-plexcachedfor multi-path mode - Fix free space check for multi-path array moves
- Fix empty string check in restore flow
- Fix folder content logging (files vs subdirectories)
- Auto-create cache subdirectories before copying
- Thread-safe console output for parallel operations
New Dependencies
tqdm - Progress bar library
New Settings
| Setting | Default | Description |
|---|---|---|
cache_retention_hours
| 48 | Hours before watched files can move back to array |
watchlist_retention_days
| 30 | Days before watchlist items auto-expire from cache |
cache_limit
| 0 | Accepts "250GB", "50%", or "" (empty = unlimited) |
notification_level
| "normal" | "quiet", "normal", or "verbose" |