Compatibility

What sharerr talks to today, the seam each category plugs into, and what was tried and removed or considered and deliberately left out, with the reason attached so a decision already made is not re-litigated. For usage and config snippets see the README; for what has been considered without being either committed to or declined, see the roadmap; for where to ask for help, see SUPPORT.md.

Contents

Supported services

Library sources (where tagged content comes from)

Sonarr, Radarr, Lidarr, Readarr and Whisparr via tag-driven discovery, and the plain directory ([[library]]). Where a version changes what discovery reads:

  • Whisparr v2 is Sonarr’s codebase and v3 is Radarr’s, on the same /api/v3 prefix, so sharerr reads the version from /system/status on every pass and walks sites and episodes or movies and scenes to match. v3 tags per movie or scene, not per site. Both land in the XXX category. A v3 scene imported without a scene name is titled from its studio and release date (Studio.YY.MM.DD.Title.XXX...), the shape Whisparr matches scenes by; a film is titled like a Radarr one.
  • Sonarr v5 still serves the v3 API sharerr reads, unchanged. It can number a series in an alternate episode order (seasonType, such as dvd); a release title’s SxxEyy carries no order, so a friend’s Sonarr would import the file as a different episode. A tagged series on any order but official is skipped with a warning in the log.
  • Readarr is retired upstream. Bookshelf, the maintained fork, serves the same v1 endpoints and fields discovery reads and reports itself as Readarr, so it is configured as [readarr]. Its hardcover images return Hardcover ids where Readarr returned Goodreads ones; discovery labels a book’s id Hardcover when its metadata server (METADATA_URL, or the one set in its UI) has hardcover in its host, as those images’ does.

Tier 2 drives Bookshelf’s hardcover image on the plain stack and Sonarr v5 with --sonarr-v5; see TESTING.md.

The *arr apps and the plain directory both sit behind the LibrarySource seam in crates/sharerr/src/sync/mod.rs: kind() plus discover(), which returns a scan that also says whether it was complete. A partial walk still shares what it found, but nothing is withdrawn on its behalf. That is where a future source would plug in; none is currently planned.

Torrent clients (what actually seeds)

qBittorrent, Transmission, rTorrent / ruTorrent and Deluge, behind the TorrentClient trait in sharerr-client. The trait is deliberately narrow, which is what made every client after the first tractable: clients disagree about almost everything except “add this torrent, with the data already at this path”. Announces always go to sharerr’s own tracker, so a client needs no tracker of its own; a torrent joined from a friend announces to theirs as well.

Adding another is mostly writing one file. A new client must answer: whether it can remove a torrent without deleting the data; how it replaces a torrent’s tracker list in place (set_trackers, for endpoint rotation) and adds to one without disturbing the rest (add_trackers, for a torrent sharerr adopts rather than creates, whose own trackers sharerr records and keeps after its own whenever an endpoint change rewrites the list); whether it can hand back a .torrent it already holds (export); and how it expresses upload_limit_kib and ratio_limit, at add time and again on an existing torrent (set_limits, for a goal that changed), through whatever native mechanism it offers.

Where they differ:

  qBittorrent Transmission rTorrent
Skip the hash check on add Yes (qbittorrent.skip_checking) No, always verifies No, always verifies
Category and tag Real category plus tags One flat labels list; label stands in for both One free-text d.custom1; label stands in for both
Per-torrent upload cap Yes Yes Yes, via a named throttle
Per-torrent ratio limit Yes Yes No. Ratio enforcement is an .rtorrent.rc schedule, so ratio_limit is accepted and logged as dropped
Credentials WebUI API key (5.2+), sent as a bearer token; no username/password path HTTP Basic plus the 409 session-id handshake; needs 4.0+ (RPC 17) for trackerList HTTP Basic aimed at the reverse proxy fronting XML-RPC; rtorrent.url is that exact endpoint, not a base
export a held .torrent Yes (torrents/export) No, returns Ok(None) No, returns Ok(None)
Replace trackers in place Yes Yes Partial: XML-RPC has no way to remove a tracker (rakshasa/rtorrent#165), so a new tier is inserted ahead of the stale one

Deluge (2.0 and newer, through its web UI) differs from the table this way: a password and no accounts; one label, through the Label plugin, and a torrent seeds unlabelled with the plugin off; upload cap, ratio goal and tracker replacement all work; export returns Ok(None); and although Deluge can skip the hash check, sharerr has no setting for it, so it always verifies on add.

Hybrid v1/v2 torrents

seeding.hybrid builds single-file torrents as BEP 52 hybrids. Every client above accepts one: qBittorrent (libtorrent 2) and Transmission 4 read both halves and keep the v1 info hash as the torrent’s identity, which is the hash sharerr joins its store to the client by; rTorrent and Transmission 3 read the v1 half and ignore the rest. Deluge is the exception: libtorrent 2 reports a hybrid under its v2 hash there, which sharerr would not recognise as the same torrent, so with Deluge the setting is ignored and a plain v1 torrent is built. The tracker admits announces under either identity (shared_items.info_hash_v2 holds the second). A friend’s client needs nothing special: a v1-only one seeds the v1 half.

Joining a friend’s swarm

When a friend already shares the same file, sharerr seeds it under the friend’s info hash instead of building a second torrent, so both instances’ friends land in one swarm. During each gossip exchange it pulls the friend’s catalog (GET /api/catalog, filtered like their feed) and, before building, looks for an entry with the same size to the byte, the same work by its external ids, and the same episode, film, track or book. Titles are not compared.

  • The client already holds the friend’s torrent, usually as the download the library file was imported from: sharerr adopts it like any other existing torrent, adding its tracker and leaving the torrent the operator’s.
  • Otherwise sharerr fetches the friend’s .torrent from the friend’s address it already gossips with, and takes it only when it is single-file, names the file exactly as it is named on disk, and matches the file piece for piece. Sharerr then adds it and treats it as its own. A friend’s hybrid torrent is skipped with Deluge, for the reason above.

Anything else builds sharerr’s own torrent, as before. A joined torrent announces to sharerr’s tracker first and the friend’s after, with the token the friend issued; the .torrent sharerr serves names its own tracker only, so that token never reaches its friends. The item’s page names the friend whose swarm it joined.

The export gap costs every client but qBittorrent one narrow case: a torrent that already covers a file, that sharerr did not create and has no cached copy of, cannot be shared on those. sharerr fails the item with a message naming the choice rather than advertise a release with no .torrent behind it.

All of them are driven through the real tier-2 stack; see docs/TESTING.md.

Indexers (what consumes the feed)

Prowlarr (Generic Torznab, or a per-host definition), Jackett-shaped URLs, and Sonarr/Radarr/Lidarr direct. The tier-2 script adds sharerr as an indexer to a real Sonarr and Lidarr and drives its Jackett-shaped routes and Torznab caps by hand; Prowlarr is an opt-in container in the same stack, and Radarr-direct is exercised only by hand. The feed also advertises book-search and category 7000, so nothing stops a Readarr pointed at it; it is just untested, see below. No further indexer work is currently planned.

Off by default ([feed] magnet_links), resolving what used to be an open roadmap question. Every torrent sharerr builds is private, so a magnet built from one can never complete: nothing in the swarm will answer a ut_metadata request. Worse, a client that supports both a magnet and a .torrent enclosure often prefers the magnet — the two-instance end-to-end test hit exactly this the hard way, when Radarr’s direct Torznab client picked the magnet over the working .torrent and stalled forever (see docker/README.md’s two-instance section for the Prowlarr preferMagnetUrl pin that works around it, since Radarr/Sonarr’s own direct client has no equivalent knob).

Turning feed.magnet_links on only ever emits a magnet for an item that is also not private ([seeding] private = false — private is on by default). The two settings are independent, and the combination “magnets on, item private” is made inert rather than left to stall a friend’s client. Turning private off is the bigger decision of the two — it hands a client DHT and PEX, so revoking a friend no longer removes them from that torrent’s swarm, the one property private exists to guarantee. See docs/SETTINGS.md for both fields’ settings-page documentation.

Not supported

One place to check before re-proposing something.

Media-server library sources (Jellyfin, Emby, Plex)

Tried and removed. The *arr apps and a plain tagged directory already cover the two shapes of “where content lives” this project wants to support; a media server would have been a third way to answer the same question, not a new one.

Readarr as a direct indexer

Out of scope: this project targets homelab media-file sharing, and books are a much smaller scale of content. Out of scope means untested and unsupported, not blocked; a Readarr pointed at the feed may well work. Readarr as a library source is unaffected and fully supported.

Transmission-compatible forks, as their own tier-2 target

Not planned. sharerr-transmission speaks only the documented session-id handshake and standard torrent-*/session-get methods, which is the same surface a compatible fork presents; the one floor is Transmission 4.0 (RPC 17) for trackerList. Standing up a real fork for tier 2 was investigated and set aside: the one actively maintained candidate has no published Docker image and describes its own RPC compatibility as imperfect.

qBittorrent’s embedded tracker as a second backend

Used for a while and removed: two tracker backends meant two independently built announce URLs, and every improvement to endpoint handling had to be made twice. A sharerr.toml still naming tracker.backend fails to load with an error saying exactly this. See DESIGN.md’s “Corrections the implementation forced”.

Multi-user

Decided against. sharerr has exactly one user: the admin who configures it and owns the library. The users table exists and only the first-run claim ever creates a row, and that is the design, not a gap. A second user would mean deciding what a friendship, a library, and a torrent client belong to before any access-control surface could be built, and nothing this project does needs that answer: friends are peers with their own instance, not accounts on yours.

Publishing to crates.io

Decided against. cargo install sharerr was investigated and found feasible, but the project is not taking on a thirteen-crate dependency-ordered release process for a distribution path it does not intend to support. Nothing in the manifests enforces this (only sharerr-testkit carries publish = false); it is a decision, not a guard. The Docker image is the only supported way to run sharerr. Since the workspace version became a placeholder (the tag is the version; see docs/RELEASING.md), every crate would also publish as 0.0.0-dev - a second reason, not a new decision.

A maintained CHANGELOG.md

Decided against. docker.yml’s release job creates a GitHub Release on every v* tag with notes collected from the ## Release note section of each PR merged since the last tag (see docs/RELEASING.md), which is exactly the surface a hand-maintained file would duplicate, and duplicate worse, since it can only drift from what shipped. The roadmap stays a to-do list, not a log: an entry is removed once it ships, not dated and kept. The Release attaches no binaries; the container image is the only distribution channel.


This site uses Just the Docs, a documentation theme for Jekyll.