Skip to main content

Automated media library cleanup for Radarr and Sonarr based on Tautulli watch status

Project description

PyPI version Python 3.9+ License

PrunArr

Automatically clean up your Radarr and Sonarr libraries based on what you've actually watched in Plex/Jellyfin (via Tautulli).

Stop manually managing your media library. PrunArr removes watched content after a configurable period, checks streaming availability, and gives you complete control over what stays and what goes.


Quick Start

# 1. Install
pip install prunarr

# 2. Configure (create config.yaml with your API keys)
curl -O https://raw.githubusercontent.com/haijeploeg/prunarr/main/config.example.yaml
mv config.example.yaml config.yaml
# Edit config.yaml with your API keys

# 3. Preview what would be removed
prunarr --config config.yaml movies remove --dry-run

# 4. Remove watched content (60+ days old by default)
prunarr --config config.yaml movies remove
prunarr --config config.yaml series remove

๐Ÿ“– Full Quick Start Guide โ†’


Why PrunArr?

The Problem:

  • Your media library keeps growing
  • You're running out of storage space
  • Manually tracking what's been watched is tedious
  • You don't know what's safe to remove
  • There are Movies and Shows in your library that are also availble on streaming providers

The Solution: PrunArr automates media cleanup by:

  • โœ… Checking Tautulli to see what's been watched
  • โœ… Removing content after your specified retention period
  • โœ… Checking if content is available on streaming services
  • โœ… Supporting user-based tracking for multi-user setups
  • โœ… Providing safety features (dry-run, confirmations, previews)

Perfect for:

  • People with limited storage space
  • Multi-user Plex/Jellyfin servers
  • Users of Overseerr request management
  • Anyone tired of manual library cleanup
  • Users who want to prioritize unique content over streamable content

Key Features

๐ŸŽฏ User-Based Tracking

Integrates with Overseerr to automatically track who requested what. Content is only removed when watched by the original requester.

prunarr movies remove --username "alice" --days-watched 30

๐Ÿ“– Tag System Guide โ†’

โฐ Flexible Retention Periods

Control exactly how long to keep watched content:

prunarr movies remove --days-watched 60   # Remove after 60 days
prunarr series remove --days-watched 90   # Keep series longer

๐Ÿ“ฆ Size-Based Filtering

Target large files to free up space quickly:

prunarr movies list --min-filesize "5GB" --sort-by filesize --desc
prunarr movies remove --min-filesize "5GB" --days-watched 60

๐Ÿท๏ธ Tag-Based Organization

Filter content by quality, genre, or any custom tags:

prunarr movies list --tag "4K" --tag "HDR"
prunarr movies remove --tag "Kids" --days-watched 14
prunarr movies remove --exclude-tag "Favorites"

๐ŸŽฌ Streaming Provider Integration

Check if content is available on your streaming services via JustWatch:

# Remove watched movies available on streaming
prunarr movies remove --on-streaming --days-watched 30

# Keep unique content longer (not on streaming)
prunarr movies remove --not-on-streaming --days-watched 180

๐Ÿ“– Streaming Integration Guide โ†’

๐Ÿ›ก๏ธ Safety-First Design

Multiple layers of protection:

  • Dry-run mode - Preview changes before committing
  • Confirmation prompts - Review what will be removed
  • User verification - Only remove content watched by the requester
  • Detailed logging - Track all operations with --debug

๐Ÿ“Š Rich Console Output

Beautiful, informative tables with:

  • ๐ŸŸข Color-coded status (Watched, Partial, Unwatched)
  • ๐Ÿ“ Human-readable file sizes (MB, GB, TB)
  • ๐Ÿ“… Last watched dates and days ago
  • ๐Ÿ”„ JSON output option for automation

โšก Performance & Automation

  • Intelligent caching - Minimize API calls
  • JSON output - Machine-readable for scripts
  • Cron-ready - Perfect for scheduled automation
  • Exit codes - Proper status codes for monitoring

Documentation

Getting Started

Core Concepts


Common Use Cases

Weekly Cleanup Routine

# Preview and remove watched content
prunarr movies remove --days-watched 60 --dry-run
prunarr movies remove --days-watched 60
prunarr series remove --days-watched 90

Free Up Space Quickly

# Target large files first
prunarr movies list --min-filesize "10GB" --sort-by filesize --desc
prunarr movies remove --min-filesize "5GB" --days-watched 30

Smart Streaming-Based Cleanup

# Remove watched movies you can re-stream
prunarr movies remove --on-streaming --days-watched 30

# Keep unique content longer
prunarr movies remove --not-on-streaming --days-watched 180

Multi-User Management

# List content by user
prunarr movies list --username "alice"

# User-specific cleanup
prunarr movies remove --username "bob" --days-watched 45

Kids Content Fast Rotation

# Quick cleanup of kids content
prunarr movies remove --tag "Kids" --days-watched 14
prunarr series remove --tag "Kids" --days-watched 14

๐Ÿ“– More Examples โ†’


Requirements

  • Python 3.9 or higher
  • Radarr (for movies) and/or Sonarr (for TV shows)
  • Tautulli (for watch history tracking)

Deployment Options

๐Ÿ“ฆ PyPI Installation (Recommended)

pip install prunarr

๐Ÿณ Docker

Run PrunArr in a container for isolated, portable deployments:

# Pull from GitHub Container Registry
docker pull ghcr.io/hploeg/prunarr:latest

# Run with Docker
docker run --rm \
  -e RADARR_API_KEY="your-api-key" \
  -e RADARR_URL="https://radarr.example.com" \
  -e SONARR_API_KEY="your-api-key" \
  -e SONARR_URL="https://sonarr.example.com" \
  -e TAUTULLI_API_KEY="your-api-key" \
  -e TAUTULLI_URL="https://tautulli.example.com" \
  ghcr.io/hploeg/prunarr:latest movies list --limit 10

# Or use Docker Compose
docker-compose run --rm prunarr movies remove --dry-run

๐Ÿ“– Docker Deployment Guide โ†’

โ˜ธ๏ธ Kubernetes with Helm

Deploy to Kubernetes for automated, scheduled cleanups:

# Install from OCI registry
helm install prunarr oci://ghcr.io/hploeg/charts/prunarr \
  --version 1.0.0 \
  --set config.radarr.apiKey="your-api-key" \
  --set config.radarr.url="https://radarr.example.com" \
  --set config.sonarr.apiKey="your-api-key" \
  --set config.sonarr.url="https://sonarr.example.com" \
  --set config.tautulli.apiKey="your-api-key" \
  --set config.tautulli.url="https://tautulli.example.com"

# Default: CronJob mode with daily cleanup at 2 AM (movies) and 3 AM (series)

Features:

  • ๐Ÿ• Automated scheduling with Kubernetes CronJobs
  • ๐Ÿ’พ Persistent cache with PVC
  • ๐Ÿ”’ Secret management for API keys
  • ๐Ÿ“Š Resource limits and health checks
  • ๐Ÿ”„ Easy rollbacks and updates

๐Ÿ“– Kubernetes Deployment Guide โ†’


Installation

From PyPI (Recommended)

pip install prunarr

From Source

git clone https://github.com/haijeploeg/prunarr
cd prunarr
pip install -e .

๐Ÿ“– Full Installation Guide โ†’


Configuration

  1. Create config file:

    curl -O https://raw.githubusercontent.com/haijeploeg/prunarr/main/config.example.yaml
    mv config.example.yaml config.yaml
    
  2. Add your API keys:

    radarr_api_key: "your-radarr-api-key"
    radarr_url: "https://radarr.yourdomain.com"
    sonarr_api_key: "your-sonarr-api-key"
    sonarr_url: "https://sonarr.yourdomain.com"
    tautulli_api_key: "your-tautulli-api-key"
    tautulli_url: "https://tautulli.yourdomain.com"
    
  3. Test your config:

    prunarr --config config.yaml movies list --limit 5
    

๐Ÿ“– Full Configuration Guide โ†’


Overseerr Integration

PrunArr works seamlessly with Overseerr's "Tag Requests" feature:

  1. In Overseerr, go to Settings โ†’ Radarr/Sonarr
  2. Enable "Tag Requests"
  3. That's it! PrunArr will automatically track who requested what

When users request content through Overseerr:

  • Tags are automatically created (e.g., "123 - john_doe")
  • PrunArr matches usernames with Tautulli
  • Content is only removed when watched by the original requester

๐Ÿ“– Tag System Guide โ†’


Command Overview

Movies:

prunarr movies list                      # List all movies
prunarr movies remove --dry-run          # Preview removal
prunarr movies remove --days-watched 60  # Remove watched movies

Series:

prunarr series list                      # List all series
prunarr series get "Breaking Bad"        # Get detailed info
prunarr series remove --days-watched 90  # Remove watched series

History:

prunarr history list --limit 20          # View watch history

Streaming:

prunarr providers list                   # List streaming providers
prunarr providers check "The Matrix"     # Check availability

Cache:

prunarr cache init                       # Initialize cache
prunarr cache status                     # View cache stats

๐Ÿ“– Complete Command Reference โ†’


Contributing

Contributions are welcome! Please:

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Make your changes
  4. Run tests (make test)
  5. Format code (make format)
  6. Commit (git commit -m 'feat: add amazing feature')
  7. Push (git push origin feature/amazing-feature)
  8. Open a Pull Request

Development Setup

git clone https://github.com/haijeploeg/prunarr
cd prunarr
python -m venv env
source env/bin/activate
pip install -e ".[dev]"

# Run tests
make test

# Format code
make format

# Run linting
make lint

Support


License

Apache-2.0 License - See LICENSE file for details.


Links


Made with โค๏ธ for the Plex/Jellyfin community

PrunArr is not affiliated with Radarr, Sonarr, Tautulli, Overseerr, Plex, or Jellyfin.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

prunarr-1.1.0.tar.gz (102.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

prunarr-1.1.0-py3-none-any.whl (120.8 kB view details)

Uploaded Python 3

File details

Details for the file prunarr-1.1.0.tar.gz.

File metadata

  • Download URL: prunarr-1.1.0.tar.gz
  • Upload date:
  • Size: 102.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for prunarr-1.1.0.tar.gz
Algorithm Hash digest
SHA256 d26b24bb381776987e78ee61e084ab07e4b4731ee0f99e8edc19b24549bd947d
MD5 7214ebf037ef668ccd3e27156a818d0b
BLAKE2b-256 1104130d34c336b925b6abcb16f8e29fe0285025b9d75705e96cc877c4c4a7cf

See more details on using hashes here.

Provenance

The following attestation bundles were made for prunarr-1.1.0.tar.gz:

Publisher: publish.yml on haijeploeg/Prunarr

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file prunarr-1.1.0-py3-none-any.whl.

File metadata

  • Download URL: prunarr-1.1.0-py3-none-any.whl
  • Upload date:
  • Size: 120.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for prunarr-1.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 93dd2a41fb744df00bd35b9a1cb74f0eac5161671799d1dae87e597f0c438d89
MD5 4efa3db71e585142664f80dd045f39a4
BLAKE2b-256 c6ff6a7938858cc1db90a139ab1c83de64e27b7a0b6db3d9262d384ee91d7d76

See more details on using hashes here.

Provenance

The following attestation bundles were made for prunarr-1.1.0-py3-none-any.whl:

Publisher: publish.yml on haijeploeg/Prunarr

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page