PrunArr
Automatically clean up your Radarr and Sonarr libraries based on what you've actually watched in Plex (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 --watched --days-watched 60 --dry-run
# 4. Remove watched content after 60 days
prunarr --config config.yaml movies remove --watched --days-watched 60
prunarr --config config.yaml series remove --watched --days-watched 60
π 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 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 --watched --days-watched 60 # Remove after 60 days
prunarr series remove --watched --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 --watched --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 --watched --on-streaming --days-watched 30
# Keep unique content longer (not on streaming)
prunarr movies remove --watched --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
- Installation Guide - Install PrunArr via pip or from source
- Configuration Guide - Set up API keys and options
- Quick Start Guide - Get productive in minutes
- Command Reference - Complete command documentation
Core Concepts
- Tag System - User tracking and content organization
- Streaming Integration - JustWatch provider integration
- Advanced Features - Automation, scripting, and optimization
- Troubleshooting - Common issues and solutions
Common Use Cases
Weekly Cleanup Routine
# Preview and remove watched content
prunarr movies remove --watched --days-watched 60 --dry-run
prunarr movies remove --watched --days-watched 60
prunarr series remove --watched --days-watched 90
Free Up Space Quickly
# Target large files first
prunarr movies list --min-filesize "10GB" --sort-by filesize --desc
prunarr movies remove --watched --min-filesize "5GB" --days-watched 30
Smart Streaming-Based Cleanup
# Remove watched movies you can re-stream
prunarr movies remove --watched --on-streaming --days-watched 30
# Keep unique content longer
prunarr movies remove --watched --not-on-streaming --days-watched 180
Multi-User Management
# List content by user
prunarr movies list --username "alice"
# User-specific cleanup
prunarr movies remove --watched --username "bob" --days-watched 45
Kids Content Fast Rotation
# Quick cleanup of kids content
prunarr movies remove --watched --tag "Kids" --days-watched 14
prunarr series remove --watched --tag "Kids" --days-watched 14
π More Examples β
Requirements
- Python 3.9 or higher
- Radarr (for movies) and/or Sonarr (for TV shows)
- Tautulli (for Plex watch history tracking - currently Plex only)
Note: PrunArr currently supports Plex via Tautulli. Jellyfin/Emby support is planned for future releases.
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/haijeploeg/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/haijeploeg/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/haijeploeg/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
-
Create config file:
curl -O https://raw.githubusercontent.com/haijeploeg/prunarr/main/config.example.yaml mv config.example.yaml config.yaml -
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" -
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:
- In Overseerr, go to Settings β Radarr/Sonarr
- Enable "Tag Requests"
- 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 --watched --dry-run # Preview removal
prunarr movies remove --watched --days-watched 60 # Remove watched movies
Series:
prunarr series list # List all series
prunarr series get "Breaking Bad" # Get detailed info
prunarr series remove --watched --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:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Make your changes
- Run tests (
make test) - Format code (
make format) - Commit (
git commit -m 'feat: add amazing feature') - Push (
git push origin feature/amazing-feature) - 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
- Documentation: docs/
- Issues: GitHub Issues
- Discussions: GitHub Discussions
License
Apache-2.0 License - See LICENSE file for details.
Links
- GitHub: https://github.com/haijeploeg/prunarr
- PyPI: https://pypi.org/project/prunarr/
- Issues: https://github.com/haijeploeg/prunarr/issues
Made with β€οΈ for the Plex community
PrunArr is not affiliated with Radarr, Sonarr, Tautulli, Overseerr, or Plex.