-
Notifications
You must be signed in to change notification settings - Fork 1
Modules
🏠 Home › Modules
CHUB ships fifteen modules. Each is a scheduled chore you can also run on demand, with its own section in config.yml and its own page under Settings → Modules.
On this page: What every module supports · Module summary · then one section per module (see jump-list below).
Jump to a module:
- 🖼️ poster_renamerr — rename posters to match your library
- 🪧 asset_renamerr — apply logos, square art, and backgrounds
- 🎨 border_replacerr — apply brand or holiday borders
- 🎬 cl2k_maker — generate CL2K-style posters from TMDB/fanart art
- 🧹 poster_cleanarr — sweep Plex Metadata bloat, orphan asset files, and stale-duplicate asset folders
- 🏷️ labelarr — mirror ARR tags into Plex labels
- 🔍 jduparr — find duplicate media files
- 🔗 nohl — find non-hardlinked media
- ❓ unmatched_assets — report media without posters
- ⬆️ upgradinatorr — trigger ARR upgrade searches
- ✏️ renameinatorr — apply ARR naming to existing files
- 🩺 health_checkarr — surface ARR health problems
- 🪺 nestarr — detect mismatches and nested paths
- ☁️ sync_gdrive — pull poster assets from Google Drive
- 🧼 plex_maintenance — run Plex-side cleanup (trash, bundles, DB, photo cache)
-
Dry run —
dry_run: truelogs what the module would do without making changes. Use it the first time. (unmatched_assetsandnestarrare report-only and have nodry_runflag.) -
Log level —
debug/info/warning/error, per module. Defaultinfo. -
Cancel from the UI — Settings → Jobs → click the running job → Cancel. Most modules stop on the next iteration. Exceptions:
border_replacerrruns to completion;plex_maintenanceis partial (see its section). - Run history — Settings → Jobs, with full log output.
| Module | What it does | Cancellable | Report-only |
|---|---|---|---|
poster_renamerr |
Match posters to your library and rename/apply them | Yes | No |
asset_renamerr |
Apply logos, backgrounds, and square art | Yes | No |
border_replacerr |
Apply brand or holiday borders | No | No |
cl2k_maker |
Generate CL2K-style posters (develop-only) | Yes | No |
poster_cleanarr |
Sweep Plex Metadata bloat, orphan asset files, and stale-duplicate asset folders | Yes | No (has report mode) |
sync_gdrive |
Pull poster assets from Google Drive | Yes | No |
unmatched_assets |
Report media missing a poster | Yes | Yes |
| Module | What it does | Cancellable | Report-only |
|---|---|---|---|
labelarr |
Mirror ARR tags into Plex labels | Yes | No |
jduparr |
Find duplicate media files by hash | Yes | No |
nohl |
Find non-hardlinked media | Yes | No (has scan mode) |
upgradinatorr |
Trigger ARR upgrade searches | Yes | No |
renameinatorr |
Apply ARR naming to existing files | Yes | No |
health_checkarr |
Delete items removed from TMDB/TVDB | Yes | No (has dry_run) |
nestarr |
Report ARR↔Plex mismatches and nested paths | Yes | Yes |
| Module | What it does | Cancellable | Report-only |
|---|---|---|---|
plex_maintenance |
Plex housekeeping (trash, bundles, DB, photo cache) | Partial | No (has dry_run) |
Matches poster files against your Radarr/Sonarr/Plex libraries, renames them, and either copies/moves/hardlinks them into a destination tree (Kometa) or uploads them straight to Plex.
Run modes: Cancellable: yes.
Setup
- Set
apply_method:kometa(write renamed files todestination_dir) orplex(upload to Plex). It does one or the other, not both. - List your poster
source_dirs. They process top→bottom and later entries win — put your highest-priority source last. - List
instances. For theplexpath, addadd_posters: trueon each Plex instance you want uploads pushed to. - Optionally chain post-hooks:
run_border_replacerr,run_asset_renamerr,clean_orphan_assets,report_unmatched_assets.
Gotcha: if nothing moves, check
dry_runis off,destination_diris writable by your PUID/PGID, andaction_type: hardlinkisn't crossing filesystems.
How matching works. CHUB matches each poster against the metadata your *arr already holds (title, year, TVDb/TMDb/IMDb id, season) — pulled live from the API, not parsed from your media folder names. ID match (TVDb → TMDb → IMDb) is most reliable and fires only when the poster filename also carries the id; otherwise it falls back to title+year+season parsed from the poster filename.
TL;DR — Poster matching reads your *arr's API, not your disk. Name your library however TRaSH recommends; to improve matching, focus on the poster set's filenames and id tags.
See Kometa Integration for end-to-end setup.
poster_renamerr:
dry_run: false
log_level: info
apply_method: kometa # kometa (write to destination_dir) | plex (upload to Plex); legacy "direct" = plex
action_type: copy # copy | move | hardlink | symlink (kometa path)
asset_folders: true # expect Kometa-style per-item folders (kometa path)
sync_posters: false
print_only_renames: false
run_border_replacerr: false # chain border_replacerr after rename
run_asset_renamerr: false # chain asset_renamerr (logos/art) after rename
clean_orphan_assets: false # chain orphan-asset cleanup (mode from poster_cleanarr.orphan_assets_mode)
report_unmatched_assets: false # chain unmatched_assets report
upload_delay_ms: 0 # optional pause (ms) after each Plex upload
source_dirs:
- /kometa
destination_dir: /posters
# Music / Lidarr art (only when a Lidarr instance is configured):
music_source_dirs: [] # dirs of custom music art (artist posters / album covers)
music_lock_artist_art: false # plex path: lock Plex thumb/art after an artist-poster upload
music_lma_sidecars: false # also write cover.jpg / artist-poster.jpg / background.jpg sidecars
instances:
- radarr_main
- sonarr_main
- plex_main:
library_names: ["Movies", "TV Shows"]
add_posters: true # plex apply_method only: upload to this instance| Field | Default | Purpose |
|---|---|---|
apply_method |
kometa |
kometa writes to destination_dir; plex uploads to Plex. Legacy direct = plex. |
action_type |
copy |
copy / move / hardlink / symlink (kometa path). |
music_source_dirs |
[] |
Custom artist/album art dirs (Lidarr only). |
music_lock_artist_art |
false |
Lock Plex art after upload so the music agent can't re-derive it (Plex path). |
music_lma_sidecars |
false |
Write image-only sidecars into Plex music folders for refresh-proof art. |
Applies the non-poster artwork types — logo, square art, and background/fanart — to matched media, reusing poster_renamerr's matching engine.
Run modes: Cancellable: yes. Idempotent — unchanged assets (same file mtime / same fanart.tv URL) are skipped.
Setup
- Set
sources(ordered, first hit wins):local(files fromsource_dirs) and/orfanart(live from fanart.tv). - For
fanart, add your personal fanart.tv API key under Settings → fanart.tv (free; cuts new-art delay 7→2 days). Without it,fanartis skipped. - Set
asset_types(default[logo, background]— the two that work on both apply paths). - Set
apply_method(kometaorplex) andaction_type. - Run it chained (set
poster_renamerr.run_asset_renamerr: true— reuses that run's sync/scan/snapshot) or standalone (its ownsync_assets+ scan).
Gotcha: on the
plexpath, art uploads to every library the item lives in (e.g. both a 1080p and a 4K library). On thekometapath,asset_foldersmust match your Kometa config.
local file naming: same convention as posters — Title (Year) {tmdb-123} — plus a type tag: - Logo.png, - Background.png, - SquareArt.png. The tag must be separated by - or _ (no delimiter = treated as a poster); case-insensitive. Banner is recognized but never applied.
Apply capability (which types work on each path):
apply_method |
logo | background | squareart |
|---|---|---|---|
plex (upload via API; legacy direct = plex) |
✅ | ✅ | ✅ |
kometa (rename into destination_dir) |
✅ logo.ext
|
✅ background.ext
|
❌ not read by Kometa |
Banner is unsupported on both paths. On the kometa path, season art uses Kometa's Season##_logo.ext / Season##_background.ext naming.
Media-level support:
| Level | logo | background | squareart |
|---|---|---|---|
| Movie | ✅ plex / ✅ kometa | ✅ plex / ✅ kometa | ✅ plex only |
| Show | ✅ plex / ✅ kometa | ✅ plex / ✅ kometa | ✅ plex only |
| Season | ❌ not expected | ✅ plex / ✅ kometa (Season##_background) |
✅ plex only |
| Collection | ✅ plex / ✅ kometa | ✅ plex / ✅ kometa | ✅ plex only |
Seasons never expect a logo — no provider publishes per-season logos, so CHUB doesn't attempt or count them.
asset_renamerr:
dry_run: false
log_level: info
print_only_renames: false # true = only list applied assets in the log
sources: [local, fanart] # ordered; first hit wins (local | fanart)
asset_types: [logo, background] # + squareart (plex only); banner unsupported
apply_method: kometa # kometa | plex (legacy "direct" = plex)
action_type: copy # copy | move | hardlink | symlink (kometa path)
asset_folders: false # match your Kometa asset_folders setting
destination_dir: /posters # kometa path: where renamed art lands
source_dirs:
- /kometa # local source (same convention as posters)
music_source_dirs: [] # music art source dirs (artist logos/backgrounds; Lidarr)
sync_assets: false # run sync_gdrive first (standalone only)
tmdb_language: [en] # preferred image languages; string or list (coerced to list)
instances:
- radarr_main
- sonarr_main
- plex_main:
library_names: ["Movies", "TV Shows"]
add_posters: true # plex apply_method only: upload to this instance| Field | Default | Purpose |
|---|---|---|
sources |
[local, fanart] |
Ordered; first source with an image wins. |
asset_types |
[logo, background] |
Add squareart for the plex path only. |
apply_method |
kometa |
kometa or plex; legacy direct = plex. |
music_source_dirs |
[] |
Artist logo/background source dirs (Lidarr). |
tmdb_language |
[en] |
Preferred fanart.tv image languages; single string or list. |
Re-applies a brand or holiday border to every matched poster.
Run modes: Cancellable: no — it runs to completion. Restart the container to stop a big run.
Two modes:
-
Color mode (default): crops
border_widthpx off all four edges and re-paints a flat border from a cycling color inborder_colors. Holiday windows substitute that holiday'scolors. -
Image mode: composites a 1000×1500 decorative PNG over the poster (transparent center shows the artwork). Activates when a holiday's
borders:field is populated;border_widthis ignored.
The crop step trusts the TPDB convention of a 26 px white border.
Gotcha (color mode):
border_widthmust match the actual border on your source posters. The default26is right for MediUX/TPDB art; non-standard art loses 26 px of real content per edge. If two holidays overlap, the one listed first wins.
Where settings live: Module Settings → Border Replacerr holds border_width, exclusion_list, ignore_folders, log_level, dry_run, and the holiday list (name + schedule). The Border Replacerr page (/poster/border-replacerr) holds border_colors, per-holiday colors/borders, the thumbnail picker, and the live preview. The YAML below is the source of truth either way.
CHUB ships 56 SVG borders across 13 holidays. Each variant is a complete decorative ring with a transparent center.
| Holiday | Variants | Schedule (default preset) |
|---|---|---|
| 🎆 New Year's Day |
v1 – v4
|
12/30 – 01/02 |
| 🧧 Lunar New Year |
v1 – v4
|
01/20 – 02/20 |
| 💘 Valentine's Day |
v1 – v5
|
02/05 – 02/15 |
| 🍀 St. Patrick's Day |
v1 – v4
|
03/14 – 03/18 |
| 🐣 Easter |
v1 – v4
|
03/31 – 04/02 |
| 🌸 Mother's Day |
v1 – v4
|
05/10 – 05/15 |
| 👨👧👦 Father's Day |
v1 – v4
|
06/15 – 06/20 |
| 🏳️🌈 Pride |
v1 – v5
|
06/01 – 06/30 |
| 🗽 Independence Day |
v1 – v4
|
07/01 – 07/05 |
| 🧹 Labor Day |
v1 – v4
|
09/01 – 09/07 |
| 🎃 Halloween |
v1 – v5
|
10/01 – 10/31 |
| 🦃 Thanksgiving |
v1 – v4
|
11/01 – 11/30 |
| 🎄 Christmas |
v1 – v5
|
12/01 – 12/31 |
Browse the full set in backend/assets/borders/.
Drop PNGs into /config/borders/<holiday-folder>/ to extend or override the bundled set. User files win over bundled files of the same name.
PNG requirements:
| Requirement | Value |
|---|---|
| Dimensions | 1000 × 1500 (2:3) |
| Format | PNG with alpha channel (RGBA) |
| Inner transparent area |
(60, 60) to (940, 1440) must be fully transparent (poster shows through) |
| Outer ring | The 60 px band around all edges should be opaque — your decoration zone |
| Corner ornaments | May extend ~120 px inward but not into the transparent center |
| Content | No text, faces, or copyrighted IP — appears on every poster |
Off-spec dimensions are resized to 1000×1500 on the fly (lossy). A file with no transparent center hides the artwork behind it.
Holiday folder slugs: newyear, lunarnewyear, valentines, stpatricks, easter, mothersday, fathersday, pride, independence, labor, halloween, thanksgiving, christmas. Custom holiday names get a slug auto-generated by the same rule (alphanumeric, lowercase, no spaces).
Add a custom border:
- Design and export a PNG at exactly 1000×1500 with the inner
(60,60)–(940,1440)area transparent. Start from a bundled SVG if you want a template. - Save it to
/config/borders/<holiday-folder>/<your-name>.png. - On the Border Replacerr page, expand the holiday card and click the file in the Custom thumbnail row (or edit the
borders:list inconfig.ymldirectly). - Hit Save changes. The next run picks it up — no image rebuild needed.
borders: config notes: the list is the rotation order; entries are filenames without .png (added automatically — v1 and v1.png both work). Resolution is case-sensitive. A name that resolves to nothing is skipped with a log warning; the rest still cycle.
border_replacerr:
dry_run: false
log_level: info
source_dirs:
- /posters
destination_dir: /posters
border_width: 26 # integer 0–200; matches the TPDB white-border standard (color mode only)
border_workers: null # advanced: re-encode thread pool; null = min(8, CPU cores)
border_colors: # color-mode fallback when no holiday active
- "#ff7300"
ignore_folders: [] # source folder names to skip
exclusion_list: null # media titles to leave alone
holidays:
# Color-mode holiday — cycles through colors
- name: 🎃 Halloween
schedule: "range(10/01-10/31)"
colors: ["#FF6600", "#000000"]
# Image-mode holiday — borders win over colors when set
- name: 🎄 Christmas
schedule: "range(12/01-12/26)"
colors: ["#C8102E", "#00843D"] # fallback if a border PNG is missing
borders: [v1, v2, v3, v4, v5]
# Mixed example with a custom border
- name: 💘 Valentine's Day
schedule: "range(02/05-02/15)"
colors: ["#D41F3A", "#FFC0CB"]
borders:
- v1
- v2
- custom-roses # /config/borders/valentines/custom-roses.png| Field | Default | Purpose |
|---|---|---|
border_width |
26 |
Pixels cropped per edge (color mode). Integer 0–200. |
border_workers |
null |
Re-encode thread pool size; null = min(8, CPU cores). |
border_colors |
["#ff7300"] |
Color-mode fallback when no holiday is active. |
Generates CL2K-style posters (contain-fit backdrop, black-fill bottom, template gradient, logo or typeset wordmark) from TMDB/fanart.tv art, saves them to output_dir, and records them in the poster cache for poster_renamerr to apply. Develop-only extension.
Run modes: Cancellable: yes (batch runs).
Setup
- Set
enabled: trueand anoutput_dir— add that dir toposter_renamerr.source_dirs. - Tune
logo_max_width(CL2K standard 600, max 800),whiten_logo, andtext_logo_fallback. - Use the Posters → CL2K Maker page for search, art picking, framing, preview, season batches, and PSD export.
Gotcha: scheduled batch runs cover movies and shows only. Collections and seasons are supported but only on demand from the page/API.
cl2k_maker:
log_level: info
enabled: false
output_dir: /posters/cl2k # add to poster_renamerr.source_dirs
language: en # preferred logo/backdrop language
logo_max_width: 600 # px; CL2K standard 600, max 800
whiten_logo: true # recolor dark logos to white
text_logo_fallback: true # synth a typeset wordmark when no logo exists
skip_existing: true # batch runs skip items that already have a CL2K poster
style: CL2K # poster_cache style tag
priority: 0
# Optional Google Drive upload (rclone copy; uses the sync_gdrive OAuth token).
upload_to_gdrive: false
gdrive_folder_id: ""
# Optional AI text removal for backdrops with baked-in titles.
ai_provider: none # none | lama_sidecar | openai | huggingface
ai_endpoint: "" # lama sidecar URL, or HF inference URL
ai_api_key: "" # openai / huggingface token
ai_model: "" # openai model id (default gpt-image-1) / HF model id
ai_timeout: 120The API lives under /api/cl2k-maker/* (search, resolve, images, season-images, fanart-images, external-ids, preview, generate, generate-seasons, generated, upload-generate, upload-poster, retext, psd-export, upload-status).
Three independent cleanup operations in one module. All three run on every scheduled (or manual) Poster Cleanarr job.
Run modes: Cancellable: yes. All passes default to report.
-
Bloat-image cleanup — sweeps Plex's
Metadata/folder for poster variants Plex no longer references. Driven bymode. -
Orphan-asset cleanup — walks
asset_dirsand acts on poster files whose title matches no media in the configured instances. Comparison set comes from CHUB's cachedmedia_cache/collections_cache(no live API calls). Driven byorphan_assets_enabled+orphan_assets_mode. -
Stale-duplicate cleanup — detects Kometa asset folders whose
{tmdb-N}/{tvdb-N}id matches a live library item but whose folder name no longer matches the item's canonical folder (e.g. after a Sonarr/Radarr folder rename). The canonical folder is always kept; only the misnamed duplicate is reported/moved/removed. A folder with no matching live id is left to the orphan pass. Move/remove are skipped when the canonical destination is not yet present on disk (never deletes the only copy). Driven bystale_duplicates_enabled+stale_duplicates_mode. Uses the same instance comparison set as orphan cleanup (orphan_instances, falling back toinstances).
Not the same as
unmatched_assets. Unmatched Assets reports media missing a poster (media → asset). Orphan cleanup acts on posters missing a media (asset → media). Opposite directions.
Gotcha:
plex_pathmust be a filesystem path (e.g.…/Plex Media Server/Metadata), not a URL.
Bloat-image modes (mode): report (lists), move (to a Poster Cleanarr Restore folder), remove (deletes), restore (moves restore items back), clear (deletes the restore folder), nothing (skips bloat so orphan/stale can still run). Promote report → move → remove.
Orphan-asset modes (orphan_assets_mode): report (log only), move (to a hidden .chub_orphan_restore subdir — recoverable), remove (permanent). Leave on report for one run before promoting.
Stale-duplicate modes (stale_duplicates_mode): report (log only), move (to .chub_orphan_restore inside the asset dir — recoverable, same restore dir as orphan), remove (permanent). Leave on report for one run before promoting.
Overlays-only mode: with overlays_only: true, each bloat candidate is checked for Kometa's EXIF marker; files without it (your own uploads) are skipped. Small CPU cost; bloat pass only.
poster_cleanarr:
log_level: info
mode: report # bloat: report | move | remove | restore | clear | nothing
plex_path: "/plex-config/Library/Application Support/Plex Media Server/Metadata"
local_db: false # clone Plex DB before scanning (safer on a running server)
use_existing_db: false # reuse the last cloned DB
ignore_running: false # skip when Plex is active
overlays_only: false # only sweep Kometa-tagged overlays; preserve custom uploads
timeout: 600 # seconds to wait for Plex tasks
instances:
- plex_main # Plex for bloat; add Radarr/Sonarr for orphan comparison
# Orphan-asset cleanup (default off)
orphan_assets_enabled: false
orphan_assets_mode: report # report | move | remove
orphan_instances: [] # comparison-set instances; empty = use `instances`
orphan_ignore_titles: [] # media titles to exclude from orphan matching
asset_dirs: [] # walked recursively; .chub_orphan_restore is skipped
include_collections: true # treat Plex collection titles as part of the comparison set
# Stale-duplicate cleanup (default off)
stale_duplicates_enabled: false
stale_duplicates_mode: report # report | move | removeMirrors Radarr/Sonarr tags into Plex labels — tag an item favorite in Sonarr and it shows up with the favorite label in the mapped Plex library.
Run modes: Cancellable: yes.
Setup
- Add a mapping per ARR instance:
app_instance,labels, and the targetplex_instances+library_names. -
labelsmay be a YAML list or a comma-separated string.
Gotcha: label updates are batched — untagging many items reflects in Plex on the next run, not instantly.
labelarr:
dry_run: false
log_level: info
mappings:
- app_instance: sonarr_main
labels: [watched, favorite] # list OR comma-separated string ("watched, favorite")
plex_instances:
- instance: plex_main
library_names: ["TV Shows"]
- app_instance: radarr_main
labels: [favorite]
plex_instances:
- instance: plex_main
library_names: ["Movies"]Finds duplicate files across your media tree by content hash, persisting hashes so repeat runs are incremental.
Run modes: Cancellable: yes.
Setup
- Point
source_dirsat your media trees. - Set
hash_databaseto a writable path.
Gotcha: the first run on a large library takes hours; later runs are fast.
hash_databasecan't contain null bytes or start with-, and its parent dir must exist (a safety check) — see Troubleshooting if you hit it.
jduparr:
dry_run: false
log_level: info
hash_database: /config/jduparr.db
source_dirs:
- /media/movies
- /media/tvFinds media files not hardlinked to your downloader's completed directory (usually a broken rename or a non-hardlinked re-import) and optionally re-queues an ARR upgrade search.
Run modes: Cancellable: yes. Per-path scan mode is report-only.
Setup
- List
source_dirs, each with amode:resolve(default — match to ARR and queue re-searches) orscan(report only, no ARR processing). - Set
searches(re-searches per run) and anyexclude_*lists. - List ARR
instances.
nohl:
dry_run: false
log_level: info
searches: 10 # re-searches to queue per run
print_files: false # log the full list of non-hardlinked files
source_dirs:
- path: /media/movies
mode: resolve # scan | resolve (default: resolve)
- path: /media/tv
mode: resolve
exclude_profiles: [] # ARR quality-profile names to skip
exclude_movies: [] # movie titles to skip
exclude_series: [] # series titles to skip
instances:
- radarr_main
- sonarr_mainReports media items that don't have a matching poster in your renamed tree. Report-only — never changes anything.
Run modes: Cancellable: yes. Report-only (no dry_run).
Setup
- List
instances. String form includes the whole instance; dict form (withlibrary_names) limits which Plex libraries count. - Tune the
ignore_*filters. - Run standalone or chain it via
poster_renamerr.report_unmatched_assets: true.
What gets flagged (all must hold): cache matched=0; status not in {announced, tba, upcoming, deleted}; content actually exists (Radarr hasFile; Sonarr episodeFileCount > 0); passes your ignore_* filters. ignore_unmonitored honors the per-season monitored flag.
Where to act: open Assets → Statistics (/poster/statistics). Each unmatched row has a Request button that copies a Discord-ready block (title + TMDb link; series add Missing main poster / Missing seasons: …, with a direct season link when exactly one is missing).
unmatched_assets:
log_level: info
ignore_folders: [] # folders to skip while scanning posters
ignore_profiles: [] # ARR quality profiles to ignore
ignore_titles: [] # media titles to ignore
ignore_tags: [] # ARR tags to ignore
ignore_collections: [] # Plex collection names to ignore
ignore_unmonitored: false # skip unmonitored items (per-season aware)
instances:
- radarr_main
- sonarr_main
- plex_main: # dict form narrows to specific libraries
library_names: ["Movies", "TV Shows"]Picks a fixed number of items per ARR instance that haven't been searched recently, fires an upgrade search, and tags them so they aren't re-picked right away. Lidarr fully supported.
Run modes: Cancellable: yes.
Setup
- Add each instance under
instances_listwith acount,tag_name,ignore_tag, andsearch_mode(upgrade|missing|cutoff). - For Sonarr/Lidarr, choose
count_mode(below).
count_mode (Sonarr + Lidarr only):
| Mode | What count caps |
Tagging |
|---|---|---|
series_artist (default)
|
Series / artists processed per run (all monitored children searched) | Parent tagged after one pass |
season_album |
Individual SeasonSearch / AlbumSearch calls per run |
Parent tagged only when all children searched (progress persisted, resumes across runs) |
Switching modes is safe — leftover progress rows clear automatically when a parent next gets tagged.
upgradinatorr:
dry_run: false
log_level: info
instances_list:
- instance: radarr_main
count: 10 # items to search per run
tag_name: chub-upgradinatorr # tag applied after search
ignore_tag: ignore # skip items carrying this tag
unattended: false
search_mode: upgrade # upgrade | missing | cutoff
- instance: sonarr_main
count: 5 # interpreted by count_mode
count_mode: season_album # series_artist (default) | season_album
tag_name: chub-upgradinatorr
ignore_tag: ignore
season_monitored_threshold: 0.5 # Sonarr: require ≥ this fraction of monitored seasons
search_mode: upgrade
- instance: lidarr_main
count: 5
count_mode: season_album # 5 album searches/run, resumes mid-artist
tag_name: chub-upgradinatorr
ignore_tag: ignore
search_mode: upgradeWalks Radarr/Sonarr and applies the ARR's own naming scheme to existing files — useful after changing a naming template.
Run modes: Cancellable: yes.
Setup
- Set
count(total items per run) — or useradarr_count/sonarr_countto override per type.countaccepts an integer or an empty string""meaning "all items". - Set
ignore_tags(comma-separated ARR tag names) to skip items. - Set
refresh_before_rename: trueto trigger a metadata refresh in the ARR before reading the rename list (skipped on dry runs).
renameinatorr:
dry_run: false
log_level: info
rename_folders: true
refresh_before_rename: false # refresh ARR metadata before reading the rename list (skipped on dry run)
count: 100 # total items per run; integer OR "" = all items
radarr_count: 0 # override per type (used when count drives the rest)
sonarr_count: 0
tag_name: chub-renameinatorr
ignore_tags: "" # comma-separated ARR tag names; items carrying any are skipped
enable_batching: false # batch API calls for speed
instances:
- radarr_main
- sonarr_main| Field | Default | Purpose |
|---|---|---|
refresh_before_rename |
false |
Refresh ARR metadata first so renamed-on-TVDB/TMDB items pick up new names. Skipped on dry runs. |
count |
100 |
Total items per run. Integer, or "" for all items. |
Checks each ARR's health feed for items removed from TMDB/TVDB (Radarr RemovedMovieCheck, Sonarr RemovedSeriesCheck) and deletes them from the ARR. Radarr and Sonarr only.
Run modes: Cancellable: yes. Use dry_run: true to preview deletions.
health_checkarr:
dry_run: false
log_level: info
instances:
- radarr_main
- sonarr_mainScans for two library problems and reports them — never moves or deletes. (1) Compares your ARR cache against Plex and flags mismatches (in ARR but not Plex, in Plex but tracked by no ARR). (2) Detects nested paths (tracked media inside another tracked item's folder, usually a botched import).
Run modes: Cancellable: yes. Report-only.
Setup
- Add
library_mappingsto scope ARR↔Plex library pairs. - Add
path_mapping(arr_path/local_path) when ARR and CHUB see media at different paths.
nestarr:
log_level: info
library_mappings: # scope to specific ARR↔Plex library pairs
- arr_instance: radarr_main
plex_instances:
- instance: plex_main
library_names: ["Movies"]
- arr_instance: sonarr_main
plex_instances:
- instance: plex_main
library_names: ["TV Shows"]
path_mapping: # translate ARR paths → local paths when volumes differ
- arr_path: /media/movies
local_path: /data/moviesPulls poster assets from Google Drive folders into a local directory using rclone. Supports OAuth tokens or a service-account JSON file (SA preferred).
Run modes: Cancellable: yes.
Setup
- Provide auth:
gdrive_sa_location(preferred) or the OAuthclient_id/client_secret/tokentriple. - Add each Drive folder under
gdrive_listwith anid,location, andname.
Gotcha:
sync_location,gdrive_sa_location, and folder IDs can't contain null bytes or start with-(a safety check against rclone-flag injection).
For service-account creation and the rclone OAuth flow, see the DAPS wiki's rclone configuration guide — CHUB uses the same backend.
sync_gdrive:
dry_run: false
log_level: info
verbose: false # log individual file actions (Copied/Deleted/Updated/Renamed)
gdrive_sa_location: /config/gdrive-sa.json # preferred — service account JSON
# OR the OAuth client triple (alternative to gdrive_sa_location):
# client_id: "<oauth-client-id>"
# client_secret: "<oauth-client-secret>"
# token: "<rclone-token-json>"
gdrive_list:
- id: "<google-drive-folder-id>"
location: /posters/gdrive-pull
name: "Community poster mirror"Runs Plex-side housekeeping on its own schedule (split from poster_cleanarr so heavy chores run less often). Four independent toggles:
-
empty_trash—library.emptyTrash(), permanently removes items marked for deletion. -
clean_bundles—library.cleanBundles(), drops orphaned.bundledirs. -
optimize_db—library.optimize(), VACUUMs Plex's metadata DB. Longest-running; run monthly. -
photo_transcoder— deletes$PLEX/Cache/PhotoTranscoder/files directly; runs even if Plex is unreachable.
Run modes: Cancellable: partial. photo_transcoder checks the cancel flag per file; the three Plex-API tasks run to completion (Plex's API has no interrupt). Restart the container to kill one mid-run.
Gotcha:
photo_transcoderneedsplex_pathpointed at the Plex application-support dir (containingCache/PhotoTranscoder/). Emptyplex_path= photo cleanup silently skipped.
plex_maintenance:
log_level: info
dry_run: false # log what each task would do without changing anything
empty_trash: true
clean_bundles: true
optimize_db: false # heavier — run on a slower cron
photo_transcoder: true
plex_path: /plex # Plex application-support dir (for photo cache cleanup)
sleep: 60 # seconds to pause between Plex-API tasks
timeout: 600 # seconds to wait for the Plex connection
instances:
- plex_mainNext: Configuration · Related: Kometa Integration, UI Guide