Skip to content

Real-time Plex Watchlist synchronization triggered by Radarr/Sonarr deletions, with TMDB/TVDB/IMDB matching, fuzzy fallback, and cached Plex index.

License

Notifications You must be signed in to change notification settings

MrCee/plexpulse

Repository files navigation

🎬 PlexPulse

PlexPulse — keep your Plex Watchlist aligned with reality.

PlexPulse ensures your Plex Account Watchlist accurately reflects what is actually present in your Plex libraries.

If something disappears from Plex, PlexPulse will eventually remove it from your Watchlist — safely, deterministically, and without guesswork.

No stale Watchlist entries.
No accidental removals.
No operator memory required.


✨ What PlexPulse Does

✅ Library-Driven Watchlist Reconciliation

PlexPulse answers one authoritative question:

“Does Plex still report this item as present?”

It does this by running a baseline scan against Plex and maintaining a persistent Library State Ledger.

Every item moves through a strict lifecycle:

current → missing → deleted

Watchlist cleanup is driven only by this lifecycle — never by filesystem state, assumptions, or partial signals.


🧠 The Library State Ledger (Authoritative)

PlexPulse maintains a persistent JSON-lines ledger recording:

  • First time an item was seen in Plex
  • Last time an item was observed
  • When it became missing
  • When it was confirmed deleted
  • Optional historical delete intent from Radarr / Sonarr

The ledger is:

  • Human-auditable
  • Deterministic
  • Idempotent
  • Safe to rebuild against
  • Never truncated automatically

Nothing is inferred.
Nothing is guessed.


🔁 One Canonical Operator Command

There is exactly one command you need to run manually:

maintenance/plexpulse-reconcile.sh

This command always performs the correct sequence:

  1. Baseline — observe current Plex library truth
  2. Backfill — import optional Arr deletion intent (non-fatal)
  3. Reconcile — enforce Watchlist policy via the running server

You never need to remember ordering. You never need to run baseline separately. You never need to call curl manually.

Delete something in Plex → run reconcile → trust the outcome.


🧠 Deletion Semantics (Important)

PlexPulse reacts to what Plex reports, not to filesystem events.

This means:

  • Deleting a file does not immediately change ledger state
  • Plex must stop returning the item via its API
  • Only then does the item become missing
  • Only after that can it become deleted

With:

PLEXPULSE_LEDGER_DELETE_AFTER_HOURS=0

This means:

The moment Plex no longer reports an item, it becomes eligible for Watchlist removal.

There is no grace window after absence is observed, but absence must be observed first.

This design avoids:

  • Race conditions
  • Partial Plex refreshes
  • Temporary metadata inconsistencies
  • Accidental Watchlist removals

PlexPulse is intentionally conservative — and therefore safe.


🧩 Separation of Responsibilities

PlexPulse is deliberately structured into clear phases:

Phase A — Baseline (Observation)

  • Queries Plex libraries
  • Updates ledger presence and timestamps
  • Marks unseen items as missing
  • Optionally promotes missing → deleted based on policy

Phase B — Backfill (Intent Annotation)

  • Parses Radarr / Sonarr logs
  • Records historical delete intent only
  • Never overrides Plex presence truth

Phase C — Reconcile (Policy Enforcement)

  • Reads ledger state
  • Applies Watchlist cleanup policy
  • Executes side-effects only via server Admin API

No phase is skipped. No phase is collapsed. No phase infers intent.


🐳 Docker-First by Design

PlexPulse is designed to run cleanly on:

  • Synology
  • Unraid
  • Linux
  • macOS

Key principles:

  • Docker controls all host ↔ container mappings
  • Absolute paths are used consistently
  • Runtime state lives in a single bind-mounted directory
  • Operator scripts may be run on host or inside container
  • No Docker-in-Docker
  • No hidden host assumptions

🚀 Quick Start

1️⃣ Clone the project

git clone https://github.com/MrCee/plexpulse.git
cd plexpulse

2️⃣ Create your .env

cp .env.example .env
nvim .env

Required values:

  • PLEX_BASEURL
  • PLEX_TOKEN
  • PLEXPULSE_STATE_DIR
  • PLEXPULSE_LIBRARY_LEDGER

Optional policy controls:

  • PLEXPULSE_LEDGER_DELETE_AFTER_HOURS
  • PLEXPULSE_AUTOCLEAN_WATCHLIST_ON_LIBRARY_DELETE

3️⃣ Build & start

docker compose build --no-cache
docker compose up -d

On startup, PlexPulse will:

  • Ensure state directory exists
  • Ensure ledger file exists
  • Run baseline
  • Run backfill
  • Trigger reconciliation
  • Start the webhook server

🔁 Day-to-Day Usage

After deleting items from Plex:

maintenance/plexpulse-reconcile.sh

That’s it.

You do not need to:

  • Run baseline manually
  • Call curl endpoints
  • Inspect internal state unless debugging

🔍 Inspection Endpoints (Optional)

For visibility and debugging:

  • GET /inspect/index — Watchlist index snapshot
  • GET /inspect/watchlist — Current Watchlist view

These are read-only and safe.


🛡 Safety Guarantees

PlexPulse never:

  • Deletes media files
  • Modifies Plex libraries
  • Alters Radarr or Sonarr configuration
  • Acts on partial deletes
  • Performs silent or inferred automation

Watchlist removal happens only when:

  1. Plex no longer reports the item and
  2. Ledger policy allows deletion and
  3. The server confirms the removal

📜 License

MIT License — see the LICENSE file.


⭐ Summary

PlexPulse is designed to be boring, predictable, and safe.

Delete something.
Run one command.
Trust the result.

PlexPulse — because your Watchlist should reflect reality, not memory.

About

Real-time Plex Watchlist synchronization triggered by Radarr/Sonarr deletions, with TMDB/TVDB/IMDB matching, fuzzy fallback, and cached Plex index.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published