media-purge

media-purge

Docker app from ktordoff13's Repository

Overview

Rule-based media cleanup for Plex and Jellyfin. Scans your libraries, recommends what to delete (never watched, watched years ago, duplicates, low quality, dead series...) with a transparent explanation for every suggestion, and reclaims space through a staged pipeline: approve -> recycle bin -> purge after retention. Ships dry-run enabled so nothing is deleted until you decide you trust it. Also includes ImageMaid-style server maintenance (Plex PhotoTranscoder cache purge, Clean Bundles / Optimize DB, Jellyfin cache tasks). Every action is written to a permanent activity log.

Media Purge

Rule-based media cleanup for Plex & Jellyfin. Storage keeps getting more expensive, and every library quietly fills up with stuff nobody watches — duplicate remuxes, shows nobody finished, 4K rips of movies you saw once. Media Purge scans your libraries, gives you explainable recommendations for what to delete (never watched, watched years ago, duplicates, low quality, dead series…), and lets you reclaim that storage through a staged, reversible pipeline — built to run as an unraid Community Applications container, but works on any Docker host.

Deletion decisions are never made by AI. Every recommendation is produced by plain heuristics you can read, tune, or disable, and every action is written to a permanent activity log: what was deleted, when, and why. (There is an optional, purely-for-fun local AI advisor — see below.)

Media Purge dashboard — reclaimable storage, per-library breakdown, and a live purge in progress

Features

  • Plex and Jellyfin, first-class. Neutral provider layer — a media_source per server, scan as many as you like. Both aggregate play stats across all server users: Jellyfin via its per-user API, Plex via the server-wide play history log (the same data Plex Dash shows).
  • 8 tunable built-in rules + a custom rule builder — compose your own conditions (field/operator/value, ALL/ANY, points) over the scan data with live preview, feeding the same scoring system — items are ranked by how strong the case is and how much space they free. Rules that need data your server can't provide disable themselves.
  • Safety first. Ships with dry-run ON. Deletion is staged: approve → files move to a recycle bin → purged only after a retention window (default 30 days). Restore anytime before purge. Protected list + keep label support for never-touch items.
  • Sonarr/Radarr aware. On approval the matching entry is unmonitored so the *arrs don't re-download what you just deleted.
  • Server maintenance (ImageMaid-style). Purge Plex's PhotoTranscoder cache (commonly 50–100+ GB), trigger Clean Bundles / Optimize Database / Empty Trash, and run Jellyfin's cache/transcode/DB-optimize tasks — from the Maintenance page.
  • Optional local AI "regret check" (just for fun). Point it at any OpenAI-compatible local server (Ollama, LM Studio) and it flags recommendations you might regret deleting — cult classics, award winners, franchise pieces — as playful display-only notes. Zero effect on scoring or deletions, nothing ever leaves your LAN, and the app is fully functional without it.
  • Nice UI, documented API. Angular 22 + Material dark UI; NestJS 11 API with full OpenAPI/Swagger docs at /api/docs. SQLite keeps everything in one file in /config.

Quick start (Docker)

Nothing about the app is unraid-specific — it's a standard container (API + SQLite + a static web UI, one port, three bind mounts) that runs the same on any Docker host: unraid, Synology, TrueNAS, or a plain Linux box.

Prebuilt images are published to GHCR on every push to main:

docker run -d --name media-purge \
  -p 8484:8484 \
  -v /mnt/user/appdata/media-purge:/config \
  -v /mnt/user/media:/media \
  -v /mnt/user/media/.media-purge-bin:/recycle-bin \
  ghcr.io/ktordoff13/media-purge:latest

Or with docker-compose.yml — copy it, edit the volume paths, then:

docker compose up -d

Or build locally:

docker build -f docker/Dockerfile -t media-purge .
docker run -d --name media-purge \
  -p 8484:8484 \
  -v /mnt/user/appdata/media-purge:/config \
  -v /mnt/user/media:/media \
  -v /mnt/user/media/.media-purge-bin:/recycle-bin \
  media-purge

Runs as root by default (fine on unraid and most single-user NAS setups). On Synology, TrueNAS, or anywhere else that cares about file ownership, set PUID/PGID env vars (id -u / id -g on the host) and the container drops to that user before touching /config; it does not chown your media share, since that mount can be huge — make sure the host already grants that user read/write on it.

Open http://<host>:8484, add your server under Settings → Media sources, set path mappings if your media server sees the share at a different path (see docs/path-mapping.md), then hit Scan now.

unraid

Use the template in docker/unraid-template.xml: download it into /boot/config/plugins/dockerMan/templates-user/ on your flash drive, then pick media-purge from the Template dropdown under Docker → Add Container.

New to unraid or containers? Follow the step-by-step setup guide — it walks through the whole install and first scan with no assumed knowledge.

Development

Requires Node ≥ 24.15 (.nvmrc provided).

npm install
npm run dev        # API on :3000 (+ Swagger at /api/docs), web on :4200 (proxied)
npm test           # rule engine + path mapping unit tests
npm run build

Repo layout: apps/api (NestJS 11), apps/web (Angular 22), docker/, docs/.

The rules

See docs/rules.md for the full reference. Summary: never watched & aging · watched long ago · big and unloved · duplicate versions · low quality unwatched · ended & fully watched series · poorly rated & never played · growing series nobody watches. Each has tunable thresholds and points; items past the score threshold become recommendations.

License

MIT

Install media-purge on Unraid in a few clicks.

Find media-purge in Community Apps on your Unraid server, review the template, and click Install. Unraid handles the Docker app or plugin setup from the published template.

Open the Apps tab on your Unraid server Search Community Apps for media-purge Review the template variables and paths Click Install

Related apps

Details

Repository
ghcr.io/ktordoff13/media-purge:latest
Last Updated2026-08-24
First Seen2026-08-24

Runtime arguments

Web UI
http://[IP]:[PORT:8484]/
Network
bridge
Shell
sh
Privileged
false

Template configuration

WebUI PortPorttcp

Web UI and API port

Target
8484
Default
8484
Value
8484
ConfigPathrw

Database and settings

Target
/config
Default
/mnt/user/appdata/media-purge
Value
/mnt/user/appdata/media-purge
MediaPathrw

Your media share. Must be read-write for cleanup to work. Add a path mapping in Settings if your media server mounts this share at a different path.

Target
/media
Default
/mnt/user/media
Value
/mnt/user/media
Recycle BinPathrw

Where approved deletions wait out the retention window. Keep it on the SAME share as your media so moves are instant instead of copies.

Target
/recycle-bin
Default
/mnt/user/media/.media-purge-bin
Value
/mnt/user/media/.media-purge-bin
Plex Appdata (optional)Pathrw

Optional: mount your Plex appdata to enable the PhotoTranscoder cache purge (often frees 50-100+ GB). Point Settings -&gt; Appdata paths at /plex-appdata/Library/Application Support/Plex Media Server.

Target
/plex-appdata
Jellyfin Appdata (optional)Pathrw

Optional: mount your Jellyfin config dir (the one containing cache/) to enable the on-disk cache purge with dry-run size estimates. Point Settings -&gt; Appdata paths at /jellyfin-appdata.

Target
/jellyfin-appdata
PUID (optional)Variable

Not needed on unraid — leave blank to run as root (the default). Only set this if you have a specific reason to run as another user.

Target
PUID
PGID (optional)Variable

Not needed on unraid — leave blank to run as root (the default). Only set this if you have a specific reason to run as another group.

Target
PGID