Recyclarr Config Generator
Generates a recyclarr configuration from live Sonarr and Radarr instances, instead of hand-writing one and syncing it the other way.
Point it at each *arr, and it reads what is already configured — quality profiles,
custom format scores, quality definition sizes, naming formats — and renders the
equivalent recyclarr.yml. Custom formats are matched back to their TRaSH Guides
trash_id by name, so the output is guide-backed and safe to recyclarr sync.
This is a one-way snapshot tool. Once the config exists, recyclarr becomes the source of truth and you edit the YAML, not the UI.
Requirements
Section titled “Requirements”- Python 3.9+
pip install -r requirements.txt(requests,PyYAML)- Network access to each *arr, and to GitHub once (the TRaSH Guides tarball is cached
under
~/.cache/recyclarr-config-generator/and refreshed daily)
Only Sonarr and Radarr are supported. recyclarr does not manage Prowlarr, Lidarr, Readarr or Bazarr, so those stacks have no config to generate.
cd utils/recyclarr-config-generatorpip install -r requirements.txt
cp instances.example.yml instances.yml # then edit: one entry per *arrpython generate_recyclarr_config.py # writes recyclarr.yml + secrets.ymlPreview without writing anything:
python generate_recyclarr_config.py --stdoutSupplying API keys
Section titled “Supplying API keys”Each *arr’s key is under Settings → General → API Key.
Keys should not live in instances.yml. Leave api_key out and the generator reads an
environment variable — api_key_env if set, otherwise <KEY>_API_KEY derived from the
instance key. That fits the repo’s BWS convention:
bws run --access-token "$BWS_ACCESS_TOKEN" -- python generate_recyclarr_config.py--api-key-mode controls how the key is referenced in the output:
| Mode | Output | Notes |
|---|---|---|
secret (default) | api_key: !secret sonarr_... | also writes secrets.yml (mode 600) |
env | api_key: !env_var SONARR_.. | recyclarr reads it from its own environment |
inline | api_key: "abc123..." | plain text in the config — avoid committing |
instances.yml, secrets.yml, recyclarr.yml and configs/ are all gitignored here.
Useful flags
Section titled “Useful flags”| Flag | Effect |
|---|---|
--split | one file per instance in --output dir, for recyclarr’s configs |
--reset-unmatched-scores | add reset_unmatched_scores.enabled to every profile |
--include-zero-scores | also emit custom formats currently scored 0 |
--no-modernize | keep retired formats as comments instead of migrating them |
--no-quality-definition | skip the quality_definition block |
--no-media-naming | skip the media_naming block |
--insecure | skip TLS verification (internal Step CA certs) |
--refresh-guides | force a re-download of the TRaSH Guides |
--guides-tarball PATH | use a local Guides tarball; no network needed |
Per-instance, verify_ssl: false does the same as --insecure for one entry.
What it reads, and what it emits
Section titled “What it reads, and what it emits”| From the API | Into the config |
|---|---|
qualityprofile | quality_profiles — upgrade/cutoff, min scores, enabled qualities and groups (top-first) |
qualityprofile | custom_formats — trash_ids grouped by identical per-profile score assignments |
qualitydefinition | quality_definition — closest guide size set, plus per-quality overrides where the instance differs |
config/naming | media_naming — the guide key whose format string matches exactly |
Every emitted trash_id carries the custom format’s name as a trailing comment,
matching the convention in the recyclarr docs.
What it will not do
Section titled “What it will not do”Custom formats you invented yourself are skipped. recyclarr only syncs formats that exist in the TRaSH Guides, so anything with no counterpart is listed as a comment at the end of that instance’s block and stays hand-managed in the UI. The same applies to naming formats you customised — the guide key cannot be inferred, so the raw format is left as a comment.
Profiles are emitted with the qualities that are currently enabled, highest-first. Anything not listed gets disabled by recyclarr on sync, which reproduces the profile as it stands.
How custom formats are matched
Section titled “How custom formats are matched”Instances keep whatever name a format was imported under while the guide renames things, so matching runs in three stages, stopping at the first hit:
- Exact name, case- and punctuation-insensitive —
DTS-XfindsDTS X. - Identical specifications — the matching rules fingerprint the format, so it is
found however far the name drifted (
DV (WEBDL)→DV (w/o HDR fallback)). - Normalized name — drops a trailing parenthetical and reads
v2as2(Anime BD Tier 01 (Top SeaDex Muxers)→Anime BD Tier 01).
Stage 3 alone is not trustworthy, so a stage-3 hit is accepted only when both formats are
built from the same kinds of rules: HDR (undefined) matches release groups while the
guide’s HDR matches title tags, so that pairing is rejected and reported rather than
silently mis-scored. Every stage-2 and stage-3 match is printed as it happens.
Retired formats are migrated, not dropped
Section titled “Retired formats are migrated, not dropped”TRaSH replaced the per-flavour HDR formats with a single HDR plus additive boost
formats. Rather than emitting the old ones as dead comments, the generator rewrites them,
scoring each boost at the difference from the profile’s plain HDR score so the totals a
profile was tuned around survive:
DV, DV HDR10, DV HDR10+, DV HLG, DV SDR at 1500 -> HDR 500 + DV Boost 1000HDR10+ at 600 -> HDR 500 + HDR10+ Boost 100HDR10, PQ, HDR (undefined) at 500 -> dropped, already covered by HDR 500An existing HDR score wins as the base; a flavour scoring no higher than HDR is simply
dropped. Substitutions are printed as they run and recorded as a comment block in the
config. --no-modernize turns the pass off.
Formats with no clean equivalent are never guessed at — Sonarr’s retired
UHD Streaming Cut resembles the current UHD Streaming Boost but covers different
services and is scored the other way, so it is reported for you to decide.
After generating
Section titled “After generating”Always preview before the first sync — it shows exactly what recyclarr would change:
recyclarr sync --previewExpect small diffs on the first run: scores the guide has but your instance never set, and qualities whose sizes were left at *arr defaults. Review them, then sync for real.