Pilot
A self-hosted TV series manager with a React web UI and a REST API. Tracks your TV library via TMDB, polls indexers for new episodes, grabs through your download client, and files completed downloads into season folders.
Features
What Pilot does
Library management
Full TMDB integration for search, metadata, posters, and episode tracking. Per-series monitoring with configurable monitor types. Season and episode-level monitoring controls, wanted page, and a calendar view of upcoming episodes.
Release handling
Quality profiles with resolution, source, codec, and HDR dimensions. Custom formats with regex matching and weighted scoring. Title-matched release filter — releases for other shows with overlapping title words don't get grabbed.
Dead-torrent detection
The stallwatcher polls your download client for stalled torrents and blocklists them. A per-episode circuit breaker caps auto-blocklist events at three strikes per 24 hours so a misconfigured indexer can't trigger a retry storm.
Automation
Automatic RSS sync on a configurable schedule. Auto-import of completed downloads with rename support. Import lists from TMDB, Trakt, Plex Watchlist, and custom URL lists. Season folder organization with configurable naming.
Integrations
Indexers: Newznab, Torznab, Pulse-managed. Download clients: Haul, qBittorrent, Deluge, Transmission, SABnzbd, NZBGet. Media servers: Plex, Jellyfin, Emby. Notifications: Discord, Slack, Telegram, Pushover, Gotify, ntfy, email, webhook.
Command palette
Cmd/Ctrl+K command palette with fuzzy search for pages, series, and actions. Dark and light themes with 10+ presets shared across the Beacon services. Live queue updates over WebSocket. OpenAPI docs at /api/docs.
Interface
Screenshots
React 19 + TypeScript UI embedded in the Go binary.
Technical
Advanced features
Title matching
The release filter runs every parsed title through a matcher in internal/core/parser/parser.go that rejects titles whose parsed show name doesn't match the requested series after normalization. Year suffixes, bracketed edition tags, and common release-group stylings all pass through cleanly.
Stallwatcher circuit breaker
internal/core/stallwatcher/service.go polls the download client's stall endpoint on a configurable interval, classifies stalled torrents by reason, and blocklists them. The per-episode circuit breaker caps auto-blocklist events at three strikes per 24 hours.
Interactive search ranking
Season-level interactive search orders releases by Quality → Custom Format Score → Protocol → Episode Count. The Episode Count tier lifts season packs above individual episodes within the same quality tier. Pack-type filter pills (Season Pack / Episodes / All) default to Season Pack for season-scoped searches.
Sonarr migration
Pilot imports from a running Sonarr instance in one pass. Open Settings → Import, enter the Sonarr URL and API key, preview, and select categories. Supported: quality profiles, libraries, indexers, download clients, and monitored series.
docker run -d \ --name pilot \ -p 8383:8383 \ -v /path/to/config:/config \ -v /path/to/tv:/tv \ ghcr.io/beacon-stack/pilot:latest
Open http://localhost:8383 — Pilot generates an API key on first run. Find it in Settings → App Settings.
Configuration
Environment variables
| Variable | Default | Description |
|---|---|---|
PILOT_SERVER_PORT | 8383 | Web UI and API port |
PILOT_DATABASE_DSN | — | Postgres DSN (required) |
PILOT_AUTH_API_KEY | auto | API key; autogenerated on first run if unset |
PILOT_PULSE_URL | — | Pulse control-plane URL (optional) |
PILOT_LOG_LEVEL | info | debug, info, warn, error |
PILOT_LOG_FORMAT | json | json or text |