Media file relationship and orphan detection tool for qBittorrent, Radarr, and Sonarr
qbit-arr analyzes your media setup to show file relationships, hardlink status, and identify orphaned files across qBittorrent torrents, Radarr movies, and Sonarr TV shows.
- 🔍 Complete System Scan - Analyze all files across qBittorrent, Radarr, and Sonarr
- 🔗 Hardlink Detection - Find files hardlinked between torrent and library directories
- 🗑️ Orphan Detection - Identify files not tracked by any service
- 🌱 Cross-Seed Analysis - Detect torrents seeding the same files across multiple trackers
- 💻 Dual Interface - Both CLI and web dashboard
- 📊 Rich Visualizations - Tables, statistics, and relationship views
When cross-seeding torrents across multiple trackers with hardlinked files:
- Hard to track which files belong to which torrents
- Risk of orphaned files when deleting media from one service but not others
- No visibility into hardlink relationships between torrent downloads and library files
- Manual cleanup is error-prone and time-consuming
qbit-arr gives you complete visibility and helps prevent orphaned files.
# Clone the repository
git clone https://github.com/yourusername/qbit-arr.git
cd qbit-arr
# Create virtual environment
python3 -m venv venv
source venv/bin/activate
# Install the package
pip install -e .docker build -t qbit-arr .
docker run -d \
--name qbit-arr \
-p 8000:8000 \
-v /data/media:/data/media:ro \
-v $(pwd)/config.yaml:/app/config.yaml \
qbit-arrCopy the example configuration:
cp config.example.yaml config.yamlEdit config.yaml with your settings:
qbittorrent:
host: localhost
port: 8080
username: admin
password: your_password
radarr:
host: localhost
port: 7878
api_key: your_radarr_api_key
sonarr:
host: localhost
port: 8989
api_key: your_sonarr_api_key
paths:
torrent_movies: /data/media/torrents/movies
torrent_tv: /data/media/torrents/tv
library_movies: /data/media/libraries/movies
library_tv: /data/media/libraries/tvCopy the example environment file:
cp .env.example .envEdit .env with your settings:
QBIT_HOST=localhost
QBIT_PORT=8080
QBIT_USERNAME=admin
QBIT_PASSWORD=your_password
RADARR_HOST=localhost
RADARR_PORT=7878
RADARR_API_KEY=your_radarr_api_key
SONARR_HOST=localhost
SONARR_PORT=8989
SONARR_API_KEY=your_sonarr_api_key
PATH_TORRENT_MOVIES=/data/media/torrents/movies
PATH_TORRENT_TV=/data/media/torrents/tv
PATH_LIBRARY_MOVIES=/data/media/libraries/movies
PATH_LIBRARY_TV=/data/media/libraries/tvqbit-arr scanShow detailed output:
qbit-arr scan --detail fullExport to JSON:
qbit-arr scan --json > scan-results.jsonqbit-arr orphansqbit-arr hardlinksqbit-arr infoqbit-arr --config /path/to/config.yaml scanStart the web server:
# Using Python
python -m uvicorn qbit_arr.web.app:app --host 0.0.0.0 --port 8000
# Or use the run_server function
python -c "from qbit_arr.web.app import run_server; run_server()"Then open your browser to http://localhost:8000
The web dashboard provides:
- Real-time scan progress
- Interactive data tables
- Statistics cards
- Export to JSON
- REST API endpoints
GET /api/scan- Perform complete scanGET /api/orphans- Get orphaned files onlyGET /api/hardlinks- Get hardlink groupsGET /api/config- View current configuration (sanitized)GET /docs- Interactive API documentationWS /ws- WebSocket for real-time updates
- Connects to Services - Queries qBittorrent, Radarr, and Sonarr APIs
- Scans Filesystems - Recursively scans your torrent and library directories
- Detects Hardlinks - Uses inode numbers to identify hardlinked files
- Builds Relationships - Maps files to torrents and arr services
- Identifies Orphans - Finds files not tracked by any service
- Analyzes Cross-Seeds - Groups torrents sharing the same files
╭──────────────────────────────╮
│ qbit-arr Media Scanner │
╰──────────────────────────────╯
╭─────── Scan Statistics ───────╮
│ Total Files 1,234 │
│ Total Size 2.5 TB │
│ Orphaned Files 12 │
│ Hardlink Groups 156 │
│ Torrents 89 │
│ Cross-Seeded 23 │
╰───────────────────────────────╯
The web interface shows:
- Statistics cards with key metrics
- Tabbed interface for different views
- Sortable tables with file details
- Color-coded badges for services
- Export functionality
Before deleting media:
- Run
qbit-arr scanto see all relationships - Check which torrents use the files
- Delete all related torrents from qBittorrent
- Delete from Radarr/Sonarr (which removes library files)
- Verify no orphans remain
View which torrents share files:
qbit-arr scan --detail fullShows torrent groups seeding identical files across trackers.
Find files not tracked anywhere:
qbit-arr orphansReview and safely delete orphaned files.
Understand storage usage:
qbit-arr hardlinksSee which files are hardlinked between directories.
# Clone and install with dev dependencies
git clone https://github.com/yourusername/qbit-arr.git
cd qbit-arr
python3 -m venv venv
source venv/bin/activate
pip install -e ".[dev]"pytestblack src/
ruff check src/mypy src/qbit-arr/
├── src/
│ └── qbit_arr/
│ ├── core/ # Business logic
│ │ ├── models.py # Data models
│ │ ├── scanner.py # Main scanner
│ │ └── hardlink.py # Hardlink detection
│ ├── api/ # API clients
│ │ ├── qbit_client.py
│ │ ├── radarr_client.py
│ │ └── sonarr_client.py
│ ├── cli/ # CLI interface
│ │ ├── commands.py
│ │ └── formatters.py
│ ├── web/ # Web interface
│ │ ├── app.py # FastAPI app
│ │ └── static/ # Frontend
│ └── config.py # Configuration
├── pyproject.toml
├── Dockerfile
└── README.md
- Python 3.9+
- qBittorrent with Web UI enabled
- Radarr API access
- Sonarr API access
- Linux filesystem (for inode-based hardlink detection)
Ensure services are accessible:
# Test qBittorrent
curl http://localhost:8080
# Test Radarr
curl -H "X-Api-Key: YOUR_KEY" http://localhost:7878/api/v3/system/status
# Test Sonarr
curl -H "X-Api-Key: YOUR_KEY" http://localhost:8989/api/v3/system/statusEnsure read access to media directories:
ls -la /data/media/torrents/
ls -la /data/media/libraries/For large libraries (1000+ files), scans may take several minutes. Consider:
- Running scans during off-peak hours
- Using the
--detail summaryoption for faster results - Checking network connectivity to services
Contributions welcome! Please:
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests
- Submit a pull request
MIT License - see LICENSE file for details
- Built with FastAPI, Click, Rich, and Pydantic
- Uses qbittorrent-api and pyarr for service integration
- Create an issue on GitHub
- Check the
/docsAPI endpoint for API documentation - Review logs for detailed error information