Sign inSign up

feeditout/leecharr

By feeditout

•Updated 3 days ago

BitTorrent downloader built on Arr* architecture. Full BEP protocol support, web UI, and more.

Image
0

10K+

feeditout/leecharr repository overview

Leecharr Skull
Leecharr ⁠

High-Performance BitTorrent & Media Downloader — purpose-built for the Servarr (*arr) ecosystem.

WebsiteCI/CDLatest ReleaseLicenseDocker Pulls
GHCR.NET 10React 19TypeScript

Leecharr Web UI Screenshot


⁠🚀 What's Changed in this Version

⁠🐛 Bug Fixes
  • fix(ci): repair qB tracker mapping and live download telemetry
  • fix(style): editorconfig indent on network binding and ffprobe
  • fix(ci): restore main build and lint after swarm drain batch
  • fix(commands): publish TaskFailedEvent when command execution fails (#1813)
  • fix(backup): publish BackupFailedEvent when archive creation fails
  • fix(automation): publish FileMoveFailedEvent when completion move fails
  • fix(config): derive incomplete dir from DownloadDir when unset (#1820)
  • fix(config): lock ConfigFileProvider dictionary reads during save (#1822)
  • fix(config): keep in-memory config unchanged when config.xml save fails
  • fix(config): reload cache from DB after SaveConfigDictionary
  • fix(config): serialize first InstanceUuid generation (#1825)
  • fix(network): treat IPv4 hosts with trailing dot as private/loopback
  • fix(automation): publish MediaInspectionFailedEvent when file probe fails (#1814)
  • fix(network): parse bracketed IPv6 hosts in proxy tunnel paths
  • fix(automation): publish ArrImportCompletedEvent from Arr webhooks
  • fix(download): skip directory symlinks in cross-volume copy
  • fix(torrents): publish pause/resume automation events from TorrentService
  • fix(network): treat 0.0.0.0 as local for proxy tunnel guards (#1836)
  • fix(download): strip incomplete extensions when a subdirectory is unreadable
  • fix(arr): resolve GetByType to enabled primary connection
  • fix(network-binding): probe NIC status in ProxyTunnel IsInterfaceUp
  • fix(arr): require enabled type match in GetByAffinity (#1834)
  • fix(download-history): roll back engine torrent on ReAdd failure
  • fix(torrents): publish TorrentProgressMilestoneEvent at download milestones
  • fix(network-binding): ignore superseded config-driven provider switches
  • fix(arr): score affinity from Category column and whole-word keywords (#1835)
  • fix(mediainsp): run ffprobe on stream inspection (#1842)
  • Fix #1832: clear removal fields when reconcile re-links history
  • fix(inspection): rollback active inspector when config save fails (fixes #1844)
  • fix(media-inspection): propagate FFprobe timeout/cancel instead of TagLib fallback
  • fix(mediainsp): skip attached_pic streams for VideoCodec (#1845)
  • fix(logging): treat blank FileLogLevel as Info on reconfigure
  • Fix #1846: label interlaced FFprobe streams as 1080i/480i from field_order
  • Fix #1847: map FFprobe format.tags to container metadata
  • fix(mediainsp): fall back to stream duration when format duration missing (#1848)
  • Fix #1849: score category names sonarr, radarr, lidarr in affinity
  • fix(bandwidth): publish BandwidthQuotaApproachingEvent when quota threshold is reached
  • Fix #124: Aria2/Flood stopped torrent RPC status mapping
  • Fix tracker stats on history re-add and manual announce (#179).
  • fix(datastore): use boolean params in AutomationScriptRepository for PostgreSQL
  • fix(notifications): expose TORRENT_SIZE_BYTES in custom script env
  • fix(torrents): stop API list from exposing session download bytes (fixes #125)
  • fix(config): apply config.xml LogLevel to console logging (#1826)
  • fix(orchestrator): coordinator-only state after worker overwrites
  • Fix #125: keep lifetime download stats off session counters
  • fix(blocklist): hold switchLock in DynamicBlocklistProxy.ClearRules (#177)
  • fix(mediainsp): map ffprobe format_name tokens using file extension (fixes #1841)
  • fix(disk): keep longest mount match when drive inspection throws
  • fix(automation): publish TrackerBoostAppliedEvent after successful tracker boost
  • fix(automation): publish TrackerBoostAppliedEvent after successful tracker boost
⁠🔧 Maintenance & Improvements
  • test(media-inspection): expect FFprobe timeout/cancel to throw
  • Apply media-type affinity keywords to tags (#1850)
  • chore(orchestrator): #257 done, grant push #179, sloth on #1849
  • orchestrator: queue penguin #124 push after sheep #179
  • chore(orchestrator): refill snake #1851, push queue #179
  • chore(orchestrator): serial push sloth #257, queue sheep #179
  • chore(orchestrator): poll v2, grant push lock #123, queue #257
  • chore(orchestrator): fix v2 issue queue
  • chore(orchestrator): resume v2 with five manual workers
  • chore(orchestrator): validation while halted
  • chore(orchestrator): validation pass while halted
  • chore(orchestrator): remove abandoned agent worktrees
  • chore(orchestrator): re-validate halted state vs swarm and GitHub
  • chore(orchestrator): validate halted state vs GitHub and swarm plan
  • chore(orchestrator): halt swarm; document v2 coordinator-only state
  • chore(orchestrator): poll reconcile; coordinator-only state
  • chore(orchestrator): reconcile state; coordinator-only writes
  • chore: mark orchestrator issue 1841 completed
  • chore(orchestrator): reconcile state with GitHub and swarm v32
  • chore(orchestrator): validate poll, record #1819 closed
  • chore(orchestrator): poll OK five workers active
  • chore(orchestrator): record poll at 12:09Z, five workers active
  • chore: orchestrator poll schedule and issue queue
  • chore: map orchestrator workers to swarm session IDs
  • chore: track Leecharr multi-agent issue orchestrator state
  • chore(orchestrator): poll OK five workers active
  • chore(orchestrator): record poll at 12:09Z, five workers active
  • chore: orchestrator poll schedule and issue queue
  • chore: map orchestrator workers to swarm session IDs
  • chore: track Leecharr multi-agent issue orchestrator state

⁠💡 What is Leecharr?

Leecharr is a modern, high-performance BitTorrent and media downloader purpose-built for the Servarr (*arr) ecosystem (Sonarr, Radarr, Lidarr, Prowlarr, Readarr).

Unlike conventional standalone clients (Deluge, qBittorrent, Transmission) that present torrents as raw filenames and technical progress bars, Leecharr deeply enriches active downloads with metadata and artwork directly from Sonarr, Radarr, and Lidarr — giving you movie posters, TV show banners, episode screenshots, artist fanart, media stream specs, and cast overviews in a unified, beautiful Servarr interface.

⁠Key Highlights
  • *🌟 Deep arr Media Enrichment: Automatic metadata and artwork correlation by release title, info hash, or *arr download ID with posters, fanart, season banners, and stream specs (4K, HDR10+, Dolby Vision, Dolby Atmos).
  • ⚡ Pure C# .NET 10 BitTorrent Engine: Rarest-First, Endgame mode, sequential streaming mode for instant video preview, non-blocking asynchronous disk I/O (64MB–512MB RAM write cache), and fast resume SQLite checkpoints.
  • 🔌 Full Client Interoperability: Built-in RPC and WebAPI emulation for Deluge (JSON-RPC), qBittorrent (WebAPI v2), and Transmission (RPC with form-urlencoded and URL path normalization) — acts as a drop-in replacement for existing download tools.
  • 🌐 Complete BitTorrent Protocol Stack: HTTP/UDP tracker announce & scrape (BEP 3, BEP 15, BEP 12 Multi-Tracker), Peer Wire protocol, MSE/PE Diffie-Hellman RC4 encryption, DHT (BEP 5), PEX (BEP 11), ut_metadata (BEP 9), Fast Extension (BEP 6), LPD (BEP 14), and uTP transport (BEP 29).
  • 📡 Sub-Second Real-Time Updates: Native Leecharr REST API v1 and SignalR WebSocket push for real-time speed pulses, piece maps, and swarm events.
  • 🔔 Multi-Channel Notifications: Discord, Telegram, Gotify, Pushover, Apprise, Email/SMTP, and Generic Webhooks with media artwork attachments.

⁠⚡ Quick Start

⁠Single Container Run (podman run / docker run)

Option 1: Docker Hub

podman run -d \
  --name leecharr \
  -p 7889:7889 \
  -p 7890:7890/tcp \
  -p 7890:7890/udp \
  -v leecharr-config:/config \
  -v leecharr-downloads:/downloads \
  --restart unless-stopped \
  feeditout/leecharr:latest

Option 2: GitHub Container Registry (GHCR)

podman run -d \
  --name leecharr \
  -p 7889:7889 \
  -p 7890:7890/tcp \
  -p 7890:7890/udp \
  -v leecharr-config:/config \
  -v leecharr-downloads:/downloads \
  --restart unless-stopped \
  ghcr.io/dmzoneill/leecharr:latest

Open http://localhost:7889⁠ in your browser.


⁠Container Compose (podman-compose.yml / compose.yaml)
services:
  leecharr:
    # Option 1 (Docker Hub):
    image: feeditout/leecharr:latest
    # Option 2 (GHCR):
    # image: ghcr.io/dmzoneill/leecharr:latest
    container_name: leecharr
    restart: unless-stopped
    ports:
      - "7889:7889"          # Web UI, REST API, & Client RPC Emulation
      - "7890:7890/tcp"      # BitTorrent Peer Wire (Inbound TCP)
      - "7890:7890/udp"      # BitTorrent DHT & uTP (Inbound UDP)
    volumes:
      - /opt/leecharr/config:/config
      - /opt/leecharr/downloads:/downloads
    environment:
      - PUID=1000
      - PGID=1000
      - TZ=Etc/UTC
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:7889/api/v1/health"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 15s

Run with Container Compose:

podman-compose up -d
# or: docker compose up -d

⁠📁 Storage Volumes & Port Parameters

ParameterTypeDefaultDescription
-p 7889:7889Port7889Web UI, REST API v1, SignalR push notifications, Deluge/qBittorrent/Transmission RPC, and Swagger
-p 7890:7890/tcpPort7890BitTorrent Peer Wire inbound connection listener
-p 7890:7890/udpPort7890BitTorrent DHT node and uTP packet exchange listener
-v /configVolume/configApplication database (leecharr.db), configuration settings (config.xml), logs, and certificates
-v /downloadsVolume/downloadsActive and completed download storage directory
-e PUID / PGIDEnv1000:1000User and Group ID for internal filesystem permissions
-e TZEnvUTCTimezone for scheduler matrix, logs, and automated backup cron jobs

⁠🌐 Reverse Proxy Configuration

⁠Nginx
server {
    listen 80;
    server_name leecharr.yourdomain.com;

    location / {
        proxy_pass http://127.0.0.1:7889;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        # WebSocket / SignalR support
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_read_timeout 86400;
    }
}
⁠Traefik (Docker Labels)
labels:
  - "traefik.enable=true"
  - "traefik.http.routers.leecharr.rule=Host(`leecharr.yourdomain.com`)"
  - "traefik.http.routers.leecharr.entrypoints=websecure"
  - "traefik.http.routers.leecharr.tls.certresolver=letsencrypt"
  - "traefik.http.services.leecharr.loadbalancer.server.port=7889"

⁠🛠️ Supported Architectures & Tags

Multi-architecture builds are automatically published to both Docker Hub and GitHub Packages Container Registry (GHCR):

ArchitectureDocker Hub Tag ExampleGHCR Tag ExampleStatus
linux/amd64feeditout/leecharr:latestghcr.io/dmzoneill/leecharr:latest✅ Verified Stable
linux/arm64feeditout/leecharr:latestghcr.io/dmzoneill/leecharr:latest✅ Verified Stable

Tag summary

Content type

Image

Digest

sha256:5e7078781…

Size

287.5 MB

Last updated

3 days ago

docker pull feeditout/leecharr