Imported from mvanbaak/arr_scripts (
AGENTS.md). Install upstream withnpx skills add mvanbaak/arr_scripts. Copyright stays with the author.
AGENTS.md - Agentic Coding Guidelines for arr_scripts
Project Overview
This repository contains shell scripts and configuration files for Radarr and Sonarr automation.
Scripts:
radarr/connect/tag_dvfelmel.sh- Tags movies withfelormelbased on Dolby Vision Enhancement Layer detection.radarr/connect/download_trailer.sh- Downloads official trailers from TMDB/YouTube for movies in Radarr.sonarr/connect/download_recap.sh- Downloads the previous season's recap video when a new series season starts in Sonarr.common/scripts_common.sh- Shared library sourced by connect scripts (config loading, executable checks, Radarr API helpers).radarr/auto_quality_switch.sh- Switches movies from Remux-only to WebDL profiles when no physical release appears within a statistical threshold.radarr/auto_quality_switch_reverse.sh- Switches movies back to Remux-only when physical release dates appear for previously switched movies.radarr/fix_quality_profiles.sh- Switches movies with a physical release date from a wrong quality profile (default[SQP] SQP-3 (Audio)) to the correct Remux-only profile (defaultSQP-3-RemuxOnly).radarr/fetch_physical_dates.sh- Searches Blu-ray.com for physical release dates missing from Radarr, logs results for TMDB submission.common/tmdb_login.sh- Playwright-based TMDB login script, exports session cookies for curl-based automation.common/push_physical_to_tmdb.sh- Pushes physical release dates to TMDB via their website's Kendo grid API.
Agent Behavior
Workflow
- Brainstorm first. Before any code change, discuss the idea with the user. Understand the problem, explore options, call out tradeoffs. Do not skip this step.
- Write a spec/proposal. For non-trivial changes, write a spec document before implementing. The spec should cover: problem, design decisions, implementation plan, edge cases. The spec exists for human sign-off — keep it during implementation, but remove it before the PR stage. This repository does not hold spec docs: code is simple and everything has a clear purpose.
- Get approval. Present the spec and wait for user approval before writing code.
- Implement. Write the code following existing conventions.
- Update docs. Update README.md with user-facing documentation for any new scripts or features. Only document what changed — no padding.
- Update AGENTS.md. If new scripts, dependencies, or file organization changes, update this file. Skip if nothing relevant changed.
- Shellcheck. Run
shellcheck -e SC1091,SC3043on all modified scripts before committing. - Commit and push. Conventional Commits format. Push to the feature branch.
- Update PR. Ensure the PR description and changelogs are current.
Rules
- Always ask before making changes. Propose what you plan to do, wait for confirmation.
- Do not add comments, documentation, or configuration "for later" — only what is needed now.
- Do not add sections to AGENTS.md or README.md that just restate what the code already says.
Build, Lint, and Test Commands
Linting
ShellCheck - Static analysis for shell scripts:
shellcheck radarr/connect/tag_dvfelmel.sh
Run with specific rules disabled (as used in this project):
shellcheck -e SC1091,SC3043 radarr/connect/tag_dvfelmel.sh
Scripts
Run the tag script in test mode:
./radarr/connect/tag_dvfelmel.sh
Run in bulk mode (process all movies):
./radarr/connect/tag_dvfelmel.sh bulk
Direct invocation with arguments:
./radarr/connect/tag_dvfelmel.sh <event_type> <movie_id> [movie_file_path]
Event types: Test, MovieFileDelete, Download, Bulk
Run the trailer script in test mode:
./radarr/connect/download_trailer.sh
Run in bulk mode (process all movies):
./radarr/connect/download_trailer.sh bulk
Direct invocation with arguments:
./radarr/connect/download_trailer.sh <event_type> <movie_id> [movie_path]
Event types: Test, MovieAdded, Download, Bulk
Run the recap script in test mode:
./sonarr/connect/download_recap.sh
Run in bulk mode (process all series):
./sonarr/connect/download_recap.sh bulk
Direct invocation with arguments:
./sonarr/connect/download_recap.sh <event_type> <series_id> [season_number]
Event types: Test, Download, Bulk
Run the auto quality switch in dry-run mode:
./radarr/auto_quality_switch.sh
Run with apply flag:
./radarr/auto_quality_switch.sh --apply
Run migration mode:
./radarr/auto_quality_switch.sh --migrate --apply
Run the reverse script in dry-run mode:
./radarr/auto_quality_switch_reverse.sh
Run the reverse script with apply flag:
./radarr/auto_quality_switch_reverse.sh --apply
Run the quality profile fix in dry-run mode:
./radarr/fix_quality_profiles.sh
Run the quality profile fix with apply flag:
./radarr/fix_quality_profiles.sh --apply
Run the physical release date lookup:
./radarr/fetch_physical_dates.sh
Run with batch limit:
./radarr/fetch_physical_dates.sh --limit 20
Export results to JSON:
./radarr/fetch_physical_dates.sh --export dates.json
Export results to CSV:
./radarr/fetch_physical_dates.sh --export dates.csv --csv
Run the TMDB login script (requires display/Xvfb):
./common/tmdb_login.sh
Run the TMDB login with custom cookie output:
./common/tmdb_login.sh --cookies /path/to/cookies.txt
Push a single release date to TMDB:
./common/push_physical_to_tmdb.sh <tmdb_id> <date> [title]
Push release dates from pipe:
./radarr/fetch_physical_dates.sh --json --quiet | ./common/push_physical_to_tmdb.sh
Dry-run mode:
./common/push_physical_to_tmdb.sh --dry-run 123456 2025-01-15 "Movie Title"
Testing
There are no formal test suites in this project. Manual testing can be performed by:
- Running the script with
Testevent type - Using Radarr's built-in "Test" button for Connect scripts
Code Style Guidelines
Shell Script Conventions
- Shebang: Use
#!/usr/bin/env shfor POSIX compatibility - Disable shellcheck warnings appropriately: Add
# shellcheck disable=SCxxxxcomments when needed (e.g.,SC3043forlocalkeyword in POSIX sh) - Exit codes: Use meaningful exit codes; 0 for success, 1 for general errors, 127 for command not found
Formatting
- Indent with 4 spaces
- Maximum line length: 100 characters (soft limit)
- Use backslash for line continuation with proper indentation
- Pipe operators should have the pipe character at the end of the line, not the start
Naming Conventions
- Functions: Use lowercase with underscores:
function_name() - Variables: Use uppercase for global variables, lowercase for locals
- Constants: All uppercase:
NEEDED_EXECUTABLES - Local variables: Prefix with underscore:
local _variable_name - Configuration variables: Prefix with service name:
RADARR_API_URL
Variable Declaration
# Global constants
NEEDED_EXECUTABLES="curl dovi_tool ffmpeg grep jq mktemp"
# Configuration with defaults
: "${LOG_FILE:=none}"
: "${RADARR_API_URL:=http://ip:7878/api/v3}"
# Local variables
local _movie_id _tag_id
Error Handling
- Always redirect errors to stderr:
echo "ERROR: message" >&2 - Use return codes to indicate success/failure
- Check command exit status when needed
- Provide meaningful error messages that include context
if ! command -v "${executable}" >/dev/null 2>&1
then
echo "ERROR: Executable '${executable} not found." >&2
exit 127
fi
Input Validation
- Validate function arguments with case statements
- Check for empty strings:
[ -z "$var" ] - Validate numeric input using pattern matching:
case "$1" in
''|*[!0-9]*)
echo "ERROR: Argument is not a movie id: $1" >&2
return 1
;;
*)
_movie_id="$1"
;;
esac
API Interactions
- Use curl with
-sfor silent operation - Always set headers:
Accept-Encoding,Content-Type - Parse JSON responses with jq
- Use printf for JSON payloads to avoid injection issues
Function Structure
function_name() {
local _arg1 _arg2
# Input validation
case "$1" in
'')
echo "ERROR: Missing required argument" >&2
return 1
;;
esac
# Main logic
# ...
# Return result
echo "${_result}"
}
Comments
- Use comments to explain non-obvious logic
- Document function purpose at the top
- Reference external sources when basing code on others' work
Changelog Headers
Every script must have a versioned changelog in its header comment block.
- Bump version when adding features or fixing behavior (MAJOR.MINOR.PATCH)
- Add new version block ABOVE the previous one (newest first)
- Prefix each change with
# *for consistent formatting - Use format:
# Version X.Y.Z (Released YYYY-MM-DD) - List user-facing changes, not implementation details
Configuration Files
- Sample files should have
.sampleextension - Document all configuration variables with comments
- Use descriptive variable names
- Place sensitive defaults (like API keys) with placeholder values
Best Practices
- Check for required executables at script start
- Use mktemp for temporary files; always clean up
- Quote all variable expansions:
"$variable" - Use
$()for command substitution (not backticks) - Use arithmetic expansion:
$((_counter+=1)) - Be careful with word splitting - always quote variables
- Use meaningful debug messages:
echo "DEBUG: Doing X for Y"
Commit Conventions
This project uses Conventional Commits.
Format
<type>: <description>
Types
fix:- Bug fixesfeat:- New featuresperf:- Performance improvementsrefactor:- Code restructuring without behavior changestyle:- Formatting, naming, or cosmetic changesdocs:- Documentation changeschore:- Maintenance, tooling, or config changes
Guidelines
- One logical change per commit
- Keep the subject line concise (imperative mood)
- Scope is optional but encouraged for clarity (e.g.,
fix(rpu): ...) - Tag releases with annotated tags:
git tag -a <version> -m "Release <version>"
File Organization
common/
scripts_common.sh # Shared library (sourced by all scripts)
scripts.conf.sample # Shared configuration
tmdb_login.sh # Playwright-based TMDB cookie export
push_physical_to_tmdb.sh # Push release dates to TMDB via curl
radarr/connect/
tag_dvfelmel.sh # Dolby Vision FEL/MEL tagging script
download_trailer.sh # Trailer download script
scripts.conf # Actual configuration (not in git)
radarr/
auto_quality_switch.sh # Forward script: Remux-only → WebDL
auto_quality_switch_reverse.sh # Reverse script: WebDL → Remux-only
fix_quality_profiles.sh # Wrong profile fix: SQP-3 (Audio) → SQP-3-RemuxOnly
fetch_physical_dates.sh # Blu-ray.com physical release date lookup
scripts.conf.sample # Sample Radarr configuration
research/
release_date_stats.sh # Statistical analysis of web vs physical release dates
sonarr/
connect/
download_recap.sh # Season recap downloader for new seasons
scripts.conf.sample # Sample configuration
scripts.conf # Actual configuration (not in git)
docs/
cookie-extraction.md # Guide for exporting YouTube cookies for yt-dlp
Dependencies
Required executables for tag_dvfelmel.sh (checked at runtime):
- curl
- hdrprobe
- jq
- mktemp
Required executables for download_trailer.sh (checked at runtime):
- curl
- cut
- ffmpeg
- jq
- mkdir
- mktemp
- tr
- yt-dlp
Required executables for download_recap.sh (checked at runtime):
- curl
- jq
- ln
- mkdir
- mktemp
- tr
- yt-dlp
Required executables for auto_quality_switch.sh and auto_quality_switch_reverse.sh (checked at runtime):
- curl
- jq
Required executables for fix_quality_profiles.sh (checked at runtime):
- curl
- jq
Required executables for fetch_physical_dates.sh (checked at runtime):
- curl
- jq
Required executables for tmdb_login.sh (checked at runtime):
- node (with playwright package)
Required executables for push_physical_to_tmdb.sh (checked at runtime):
- curl
- jq
- grep
- sed
Notes
- For more extensive Radarr taggers, check out Radarr DV HDR Tagarr from TRaSH-
- Scripts are designed to run in Radarr Connect/post-process context
- Compatible with FreeBSD and Linux environments
Respond terse like smart caveman. All technical substance stay. Only fluff die.
Rules:
- Drop: articles (a/an/the), filler (just/really/basically), pleasantries, hedging
- Fragments OK. Short synonyms. Technical terms exact. Code unchanged.
- Pattern: [thing] [action] [reason]. [next step].
- Not: "Sure! I'd be happy to help you with that."
- Yes: "Bug in auth middleware. Fix:"
Switch level: /caveman lite|full|ultra|wenyan Stop: "stop caveman" or "normal mode"
Auto-Clarity: drop caveman for security warnings, irreversible actions, user confused. Resume after.
Boundaries: code/commits/PRs written normal.